omads/omadsextensions/adapters/mediads/src/mediadsstore.cpp
branchRCL_3
changeset 24 8e7494275d3a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omads/omadsextensions/adapters/mediads/src/mediadsstore.cpp	Tue Aug 31 15:05:37 2010 +0300
@@ -0,0 +1,1210 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Part of SyncML Data Synchronization Plug In Adapter
+*
+*/
+
+
+#include "mediadsstore.h"
+#include <mpxmessagegeneraldefs.h>
+#include <mpxcollectionmessage.h>
+
+#include "mediadsproviderdefs.h"
+#include "mediamanager.h"
+#include "cmdemanager.h"
+#include "playlistitem.h"
+#include "omadsfolderobject.h"
+#include "snapshotitem.h"
+#include "logger.h"
+
+_LIT8( KFolderMimeType, "application/vnd.omads-folder+xml" );
+_LIT8( KFolderMimeVersion, "1.2" );
+
+_LIT8( KPlaylistMimeType, "audio/x-mpegurl");
+_LIT8( KPlaylistMimeVersion, "1.0");
+
+_LIT8( KSongMimeType, "application/x-song");
+_LIT8( KSongMimeVersion, "1.0");
+
+
+const TInt KDataBufferSize = 1024;
+
+const TInt KAlbumsOffSet = 0x0000f000;
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::CMediaDsDataStore
+// C++ default constructor can NOT contain any code, that might leave.
+// -----------------------------------------------------------------------------
+CMediaDsDataStore::CMediaDsDataStore( RFs& aFs):
+    iKey(TKeyArrayFix(_FOFF(TSnapshotItem, ItemId()), ECmpTInt)),
+    iFs( aFs )
+    { 
+    TRACE_FUNC;
+    }
+  
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::ConstructL
+// Symbian 2nd phase constructor, can leave.
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::ConstructL()
+    {
+    TRACE_FUNC_ENTRY;
+    
+    // Item UID sets, used to transfer change info
+    iNewItems = new (ELeave) CNSmlDataItemUidSet;
+    iDeletedItems = new (ELeave) CNSmlDataItemUidSet;
+    iUpdatedItems = new (ELeave) CNSmlDataItemUidSet;
+    iMovedItems = new (ELeave) CNSmlDataItemUidSet;
+    iSoftDeletedItems = new (ELeave) CNSmlDataItemUidSet;
+    
+    iHasher = CMD5::NewL();
+    
+    iMediaManager = CMediaManager::NewL( iFs, this, iKey, *iHasher );
+    
+    iMdEManager = CMdEManager::NewL( *this );
+    
+    TRACE_FUNC_EXIT;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+CMediaDsDataStore* CMediaDsDataStore::NewLC( RFs& aFs)
+    {
+    TRACE_FUNC_ENTRY;
+    CMediaDsDataStore* self = new (ELeave) CMediaDsDataStore( aFs );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    TRACE_FUNC_EXIT;
+    return self;    
+    }
+
+    
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::~CMediaDsDataStore
+// Destructor
+// -----------------------------------------------------------------------------
+CMediaDsDataStore::~CMediaDsDataStore()
+    {
+    TRACE_FUNC_ENTRY;
+    
+    delete iDataBuffer;
+    
+    delete iChangeFinder;
+    
+    delete iNewItems;
+    delete iDeletedItems;
+    delete iUpdatedItems;
+    delete iMovedItems;
+    delete iSoftDeletedItems;
+    
+    delete iMediaManager;
+    LOGGER_WRITE("iMediaManager deleted");
+    
+    delete iMdEManager;
+    LOGGER_WRITE("iMdEManager deleted");
+    
+    delete iHasher;
+    LOGGER_WRITE("iHasher deleted");
+    // normally iSnapshot is NULL, but if error has occured we need to delete it.
+    delete iSnapshot;
+    TRACE_FUNC_EXIT;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoOpenL
+// Opens database. This operation is performed SYNCHRONOUSLY
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoOpenL( const TDesC& aStoreName,
+    MSmlSyncRelationship& aContext, TRequestStatus& aStatus )
+    {
+    TRACE_FUNC_ENTRY;
+    
+    iCallerStatus = &aStatus;
+    *iCallerStatus = KRequestPending;
+    
+    if ( iCurrentState != EClosed )
+        {
+        User::RequestComplete( iCallerStatus, KErrInUse );
+        LOGGER_WRITE("CMmsDataStore::DoOpenL failed with KErrInUse.");
+        return;
+        }
+    
+    // Create ChangeFinder object
+    if ( iChangeFinder )
+        {
+        delete iChangeFinder;
+        iChangeFinder = NULL;
+        }
+    iChangeFinder = CChangeFinder::NewL( aContext, iKey, iHasHistory, KMediaDataProviderImplUid );
+    
+    if ( aStoreName.CompareF( KMediaDsRefreshDbName ) == 0 )
+        {
+        LOGGER_WRITE("Refresh library and open database");
+        // just kick off scanner, don't wait ready status
+        // Async. func. HandleCollectionMessage is called when ready
+        iMediaManager->ScanL();
+        
+        }
+    else if ( aStoreName.CompareF( KMediaDsDbName ) == 0 )
+        {
+        LOGGER_WRITE("Open database");
+        
+        if ( !iHasHistory )
+            {
+            LOGGER_WRITE("No history, scan library");
+            // just kick off scanner, don't wait ready status
+            // Async. func. HandleCollectionMessage is called when ready
+            iMediaManager->ScanL();
+            }
+        
+        }
+    else
+        {
+        LOGGER_WRITE("Unknown database");
+        User::Leave( KErrNotSupported );
+        }
+    
+    // Set current snapshot, this will be compared against the old one   
+    RegisterSnapshotL();
+    
+    TRACE_FUNC_EXIT;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoCancelRequest
+// Not supported, does nothing.
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoCancelRequest()
+    {
+    TRACE_FUNC_ENTRY;
+    if ( iCurrentState == EOpening )
+        {
+        LOGGER_WRITE("Cancel Open command");
+        iMediaManager->Cancel();
+        iMdEManager->Cancel();
+        }
+    TRACE_FUNC_EXIT;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoStoreName
+// Returns the name of the DataStore
+// -----------------------------------------------------------------------------
+const TDesC& CMediaDsDataStore::DoStoreName() const
+    {
+    TRACE_FUNC;
+    return KNullDesC;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoBeginTransactionL
+// Transactions are not supported.
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoBeginTransactionL()
+    {
+    TRACE_FUNC;
+    User::Leave( KErrNotSupported );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoCommitTransactionL
+// Transactions are not supported.
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoCommitTransactionL( TRequestStatus& /*aStatus*/ )
+    {
+    TRACE_FUNC;
+    User::Leave( KErrNotSupported );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoRevertTransaction
+// Transactions are not supported.
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoRevertTransaction( TRequestStatus& aStatus )
+    {
+    TRACE_FUNC;
+    iCallerStatus = &aStatus;
+    User::RequestComplete( iCallerStatus, KErrNotSupported );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoBeginBatchL
+// Batching is not supported.
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoBeginBatchL()
+    {
+    TRACE_FUNC;
+    User::Leave( KErrNotSupported );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoCommitBatchL
+// Batching is not supported
+// -----------------------------------------------------------------------------
+//
+void CMediaDsDataStore::DoCommitBatchL( RArray<TInt>& /*aResultArray*/, TRequestStatus& /*aStatus*/ )
+    {
+    TRACE_FUNC;
+    User::Leave( KErrNotSupported );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoCancelBatch
+// Batching is not supported
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoCancelBatch()
+    {
+    TRACE_FUNC;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoSetRemoteStoreFormatL
+// Not supported
+// -----------------------------------------------------------------------------
+//
+void CMediaDsDataStore::DoSetRemoteStoreFormatL( const CSmlDataStoreFormat& /*aServerDataStoreFormat*/ )
+    {
+    TRACE_FUNC;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoSetRemoteMaxObjectSize
+// Not supported
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoSetRemoteMaxObjectSize( TInt /*aServerMaxObjectSize*/ )
+    {
+    TRACE_FUNC;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoMaxObjectSize
+// Reads the maximum MMS Message size from the central repository
+// -----------------------------------------------------------------------------
+TInt CMediaDsDataStore::DoMaxObjectSize() const
+    {
+    TRACE_FUNC;
+    return 0;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoOpenItemL
+// Opens item in the DataStore, reads it (either completely or partially) 
+// to the temporary buffer where it can be later read to the remote database.
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoOpenItemL( TSmlDbItemUid aUid, TBool& /*aFieldChange*/, 
+    TInt& aSize, TSmlDbItemUid& aParent, TDes8& aMimeType, 
+    TDes8& aMimeVer, TRequestStatus& aStatus )
+    {
+    TRACE_FUNC_ENTRY;
+
+    LOGGER_WRITE_1( "Opening item %d.", aUid );
+    
+    // Store these for later use
+    iCallerStatus = &aStatus;
+    *iCallerStatus = KRequestPending;
+    
+    iReadPosition=0;
+    
+    // Check that we're in a proper state
+    if ( iCurrentState != EOpenAndWaiting )
+        {
+        LOGGER_WRITE_1( "CMediaDsDataStore::DoOpenItemL, invalid state %d.", iCurrentState );
+        User::RequestComplete( iCallerStatus, KErrNotReady );
+        return;
+        }
+    
+    if ( !iDataBuffer )
+        {
+        iDataBuffer = CBufFlat::NewL( KDataBufferSize );
+        }
+    iDataBuffer->Reset();
+
+    
+    if ( aUid <= KLastFolderId )
+        {
+        COMADSFolderObject* folderObject = COMADSFolderObject::NewLC();
+        
+        switch ( aUid )
+            {
+            case KAllSongsFolderId:
+                folderObject->SetName( KAllSongs );
+                break;
+            case KPlaylistsFolderId:
+                folderObject->SetName( KPlaylists );
+                break;
+            case KAlbumsFolderId:
+                folderObject->SetName( KAlbums );
+                break;
+            default:
+                User::Leave( KErrNotFound );
+                break;
+            }
+        folderObject->ExportFolderXmlL( *iDataBuffer );
+        CleanupStack::PopAndDestroy( folderObject );
+        aMimeType.Copy( KFolderMimeType );
+        aMimeVer.Copy( KFolderMimeVersion );
+        aParent = KErrNotFound;
+        }
+    else
+        {
+        CSongItem* song = CSongItem::NewLC();
+        LOGGER_WRITE("Try to read song");
+        TRAPD( err, iMediaManager->GetSongL( aUid, *song ));
+        if ( !err )
+            {
+            RBufWriteStream stream( *iDataBuffer );
+            CleanupClosePushL( stream );
+            song->ExportL( stream );
+            CleanupStack::PopAndDestroy( &stream );
+            CleanupStack::PopAndDestroy( song );
+            
+            aMimeType.Copy( KSongMimeType );
+            aMimeVer.Copy( KSongMimeVersion );
+            aParent = KAllSongsFolderId;
+            }
+        else // could not read song, maybe it is playlist
+            {
+            CleanupStack::PopAndDestroy( song );
+            CPlaylistItem* playList = CPlaylistItem::NewLC();
+            LOGGER_WRITE("Try to read playlist");
+            TRAP(err, iMediaManager->GetPlayListL( aUid, *playList ));
+            if ( !err )
+                {
+                RBufWriteStream stream( *iDataBuffer );
+                CleanupClosePushL( stream );
+                
+                playList->ExportL( stream );
+                CleanupStack::PopAndDestroy( &stream );
+                CleanupStack::PopAndDestroy( playList );
+                
+                aMimeType.Copy( KPlaylistMimeType );
+                aMimeVer.Copy( KPlaylistMimeVersion );
+                aParent = KPlaylistsFolderId;
+                }
+            else
+                {
+                CleanupStack::PopAndDestroy( playList );
+                LOGGER_WRITE("Try to read album");
+                // Could not read song, maybe it's a Album
+                const CPlaylistItem& album = iMdEManager->AlbumL( MapSyncIdToAlbumId(aUid) );
+                RBufWriteStream stream( *iDataBuffer );
+                CleanupClosePushL( stream );
+                
+                album.ExportL( stream );
+                CleanupStack::PopAndDestroy( &stream );
+                
+                aMimeType.Copy( KPlaylistMimeType );
+                aMimeVer.Copy( KPlaylistMimeVersion );
+                aParent = KAlbumsFolderId;
+                }
+            }
+        
+        }
+    
+    aSize = iDataBuffer->Size();
+    
+    LOGGER_WRITE_1("aSize: %d", aSize);
+    
+    // Signal we're complete
+    User::RequestComplete( iCallerStatus, KErrNone ); 
+
+    TRACE_FUNC_EXIT;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoCreateItemL
+// Create new item to the message store.
+// Return the id number of the newly created item
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoCreateItemL( TSmlDbItemUid& aUid, TInt aSize, TSmlDbItemUid aParent, 
+    const TDesC8& aMimeType, const TDesC8& /*aMimeVer*/, TRequestStatus& aStatus )
+    {
+    TRACE_FUNC_ENTRY;
+    LOGGER_WRITE_1( "Parent folder: %d.", aParent );
+    
+    // Store some variables for further use
+    iCallerStatus = &aStatus;
+    *iCallerStatus = KRequestPending;
+    
+    // Ensure that we're in proper state
+    if ( iCurrentState != EOpenAndWaiting )
+        {
+        LOGGER_WRITE_1( "Invalid state %d.", iCurrentState );
+        }
+    
+    iWrittenDataLength = 0;
+    iCreatedUid = &aUid;
+    LOGGER_WRITE8_1( "aMimeType: %S", &aMimeType );
+    
+    if ( aMimeType.Compare( KPlaylistMimeType() ) == 0 )
+        {
+        LOGGER_WRITE("Add Playlist");
+        iCurrentState = ECreatePlaylist;
+        }
+    else if ( aMimeType.Compare( KSongMimeType() ) == 0 )
+        {
+        LOGGER_WRITE("Add Song not supported");
+        User::Leave( KErrNotSupported );
+        }
+    else
+        {
+        User::RequestComplete( iCallerStatus, KErrNotSupported );
+        LOGGER_WRITE("Bad MIME type");
+        return;
+        }
+    
+    if ( iDataBuffer )
+        {
+        iDataBuffer->ResizeL( aSize );
+        }
+    else
+        {
+        iDataBuffer = CBufFlat::NewL( KDataBufferSize );
+        iDataBuffer->ResizeL( aSize );
+        }
+    LOGGER_WRITE_1("iDataBuffer->Size: %d", iDataBuffer->Size());
+    
+    LOGGER_WRITE_1("aSize: %d", aSize);
+    iParentId = aParent;
+    
+    // Signal we're complete
+    User::RequestComplete( iCallerStatus, KErrNone );
+    
+    TRACE_FUNC_EXIT;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoReplaceItemL
+// Begin the replace operation, ensure that the item really exists
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoReplaceItemL( TSmlDbItemUid aUid, TInt aSize, TSmlDbItemUid aParent, 
+    TBool /*aFieldChange*/, TRequestStatus& aStatus )
+    {
+    TRACE_FUNC_ENTRY;
+    LOGGER_WRITE_1("Replacing item %d.", aUid);
+    LOGGER_WRITE_1("Parent folder: %d.", aParent);
+    
+    // Store some variables for further use
+    iCallerStatus = &aStatus;
+    *iCallerStatus = KRequestPending;
+    
+    // Ensure proper state
+    if ( iCurrentState != EOpenAndWaiting )
+        {
+        LOGGER_WRITE_1("Invalid state %d.", iCurrentState);
+        }
+    
+    iCurrentState = EReplace;
+    
+    iParentId = aParent;
+    iCurrentId = aUid;
+    
+    if ( iDataBuffer )
+        {
+        iDataBuffer->ResizeL( aSize );
+        }
+    else
+        {
+        iDataBuffer = CBufFlat::NewL( KDataBufferSize );
+        iDataBuffer->ResizeL( aSize );
+        }
+    
+    // Signal we're complete
+    User::RequestComplete( iCallerStatus, KErrNone );
+    
+    TRACE_FUNC_EXIT;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoReadItemL
+// Read specified amount of data from the temporary buffer
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoReadItemL( TDes8& aBuffer )
+    {
+    TRACE_FUNC_ENTRY;
+    // Thiw is how much data there is left in the buffer    
+    TInt left = iDataBuffer->Size() - iReadPosition;
+    
+    if ( left > 0 )
+        {
+        // This is how much there's space in the destination buffer
+        TInt destSize = aBuffer.MaxSize();
+        
+        // This is how much we can read
+        TInt toRead = destSize < left ? destSize : left;
+        
+        // Read the data from the buffer, then update the position      
+        iDataBuffer->Read( iReadPosition, aBuffer, toRead );
+        iReadPosition += toRead;
+        }
+    else
+        {
+        LOGGER_WRITE( "No data to read" );
+        User::Leave( KErrEof );
+        }   
+    TRACE_FUNC_EXIT;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoWriteItemL
+// Write specified amount of data to the temporary buffer
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoWriteItemL( const TDesC8& aData )
+    {
+    TRACE_FUNC_ENTRY;
+    
+    iDataBuffer->Write( iWrittenDataLength, aData );
+    iWrittenDataLength += aData.Size();
+    
+    TRACE_FUNC_EXIT;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoCommitItemL
+// Commits item from temporary buffer to the message store
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoCommitItemL( TRequestStatus& aStatus )
+    {
+    TRACE_FUNC_ENTRY;
+    
+    // Store some variables
+    iCallerStatus = &aStatus;
+    *iCallerStatus = KRequestPending;
+    
+    iDataBuffer->Compress();
+    
+    // Read the playlist item
+    CPlaylistItem* newItem = CPlaylistItem::NewLC();
+    
+    const TUint8* ptr8 = iDataBuffer->Ptr(0).Ptr();
+    const TUint16* ptr16 = reinterpret_cast<const TUint16*>( ptr8 );
+    TPtrC dataPtr;
+    dataPtr.Set( ptr16, iDataBuffer->Size()/2 );
+    newItem->ImportL( dataPtr );
+    
+    iDataBuffer->Reset();
+    
+#ifdef _DEBUG
+    LOGGER_WRITE_1("Name: %S", &newItem->Title());
+    LOGGER_WRITE_1("Items count: %d", newItem->ItemCount());
+    for ( TInt i=0; i<newItem->ItemCount(); i++ )
+        {
+        TPtrC16 ptr = newItem->ItemAt(i);
+        LOGGER_WRITE_1("item: %S", &ptr);
+        }
+#endif
+    
+    
+    TInt error(KErrNone);
+    if ( iCurrentState == ECreatePlaylist )
+        {
+        if ( iParentId == KPlaylistsFolderId )
+            {
+            iMediaManager->CreateNewPlaylistL( *iCreatedUid, *newItem );
+            }
+        else if ( iParentId == KAlbumsFolderId )
+            {
+            iMdEManager->CreateAlbumL( *newItem );
+            *iCreatedUid = MapAlbumIdToSyncId( newItem->Id() );
+            }
+        else
+            {
+            LOGGER_WRITE("Not supported");
+            User::Leave( KErrNotSupported);
+            }
+        
+        // Inform ChangeFinder of the added item
+        TSnapshotItem snapshotItem( *iCreatedUid );
+        snapshotItem.SetParentId( iParentId );
+        snapshotItem.SetItemHash( *newItem, *iHasher );
+        iChangeFinder->ItemAddedL( snapshotItem );
+        
+        }
+    else if ( iCurrentState == EReplace )
+        {
+        if ( iParentId == KPlaylistsFolderId )
+            {
+            iMediaManager->ReplacePlaylistL( iCurrentId, *newItem );
+            }
+        else if ( iParentId == KAlbumsFolderId )
+            {
+            iItemInReplacement.SetItemId( iCurrentId );
+            iItemInReplacement.SetParentId( iParentId );
+            iItemInReplacement.SetItemHash( *newItem, *iHasher );
+            // Async function, calls AlbumReplaced when completed
+            iMdEManager->ReplaceAlbumL( MapSyncIdToAlbumId(iCurrentId), *newItem );
+            
+            CleanupStack::PopAndDestroy( newItem );
+            return;
+            }
+        else
+            {
+            LOGGER_WRITE("Not supported");
+            User::Leave( KErrNotSupported);
+            }
+        
+        // Inform ChangeFinder of the replaced item
+        TSnapshotItem snapshotItem( iCurrentId );
+        snapshotItem.SetParentId( iParentId );
+        snapshotItem.SetItemHash( *newItem, *iHasher );
+        iChangeFinder->ItemUpdatedL( snapshotItem );
+        }
+    else
+        {
+        LOGGER_WRITE_1("Wrong state: %d", iCurrentState);
+        User::Leave( KErrNotSupported );
+        }
+    CleanupStack::PopAndDestroy( newItem );
+    
+    
+    
+    LOGGER_WRITE_1("error: %d", error);
+    // We'll be waiting for next event, signal we're done
+    iCurrentState = EOpenAndWaiting;
+    User::RequestComplete( iCallerStatus, error );
+    
+    TRACE_FUNC_EXIT;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoCloseItem
+// Closes open item in the data store
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoCloseItem()
+    {
+    TRACE_FUNC_ENTRY;
+    if ( iDataBuffer )
+        {
+        iDataBuffer->Reset();
+        }
+    iCurrentState = EOpenAndWaiting;
+    iReadPosition = 0;
+    TRACE_FUNC_EXIT;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoMoveItemL
+// Moves item from one folder to another in the message store
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoMoveItemL( TSmlDbItemUid /*aUid*/,
+    TSmlDbItemUid /*aNewParent*/, TRequestStatus& /*aStatus*/ )
+    {
+    TRACE_FUNC;
+    User::Leave( KErrNotSupported );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoDeleteItemL
+// Removes item from the message store
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoDeleteItemL( TSmlDbItemUid aUid, TRequestStatus& aStatus  )
+    {
+    TRACE_FUNC_ENTRY;
+    LOGGER_WRITE_1("Deleting item %d.", aUid);
+    
+    // Store some variables for further use
+    iCallerStatus = &aStatus;
+    *iCallerStatus = KRequestPending;
+    
+    TInt error(KErrNone);
+    
+    // Check that we're in proper state
+    if ( iCurrentState != EOpenAndWaiting ) 
+        {
+        LOGGER_WRITE_1("CMmsDataStore::DoDeleteItemL, invalid state %d.", iCurrentState);        
+        }
+    
+    TRAP( error,  iMediaManager->DeletePlaylistL( aUid ) );
+    if ( error )
+        {
+        error = KErrNone;
+        iMdEManager->DeleteAlbumL( MapSyncIdToAlbumId( aUid ) );
+        }
+    
+    if ( !error )
+        {
+        // Inform ChangeFinder of the deleted item
+        TSnapshotItem snapshotItem( aUid );
+        iChangeFinder->ItemDeletedL( snapshotItem );
+        }
+    
+    LOGGER_WRITE_1("complete error: %d", error);
+    // Signal we're done
+    User::RequestComplete( iCallerStatus, error );
+    TRACE_FUNC_EXIT;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoSoftDeleteItemL
+// Soft delete isn't supported.
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoSoftDeleteItemL( TSmlDbItemUid /*aUid*/, TRequestStatus& aStatus )
+    {
+    TRACE_FUNC_ENTRY;
+    
+    // Store some variables for further use
+    iCallerStatus = &aStatus;
+    *iCallerStatus = KRequestPending;
+
+    // Signal we're done
+    User::RequestComplete( iCallerStatus, KErrNotSupported );
+    
+    TRACE_FUNC_EXIT;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoDeleteAllItemsL
+// Deletes all items in the standard folders of message store
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoDeleteAllItemsL( TRequestStatus& aStatus )
+    {
+    TRACE_FUNC_ENTRY;
+    
+    // Store some variables for further use 
+    iCallerStatus = &aStatus;
+    *iCallerStatus = KRequestPending;
+    
+    User::RequestComplete( iCallerStatus, KErrNotSupported );
+    
+    TRACE_FUNC_EXIT;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoHasSyncHistory
+// This method returns ETrue if Data Store has history information. 
+// Slow-sync will be used if Data Store does not have history information.
+// -----------------------------------------------------------------------------
+TBool CMediaDsDataStore::DoHasSyncHistory() const
+    {
+    TRACE_FUNC_RET( (TInt)iHasHistory );      
+    
+    // iHasHistory is initialized in DoOpenL method
+    return iHasHistory;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoAddedItems
+// This method returns UIDs of added items. Those items are added after previous
+// synchronization with current synchronization relationship. 
+// -----------------------------------------------------------------------------
+const MSmlDataItemUidSet& CMediaDsDataStore::DoAddedItems() const
+    {
+    TRACE_FUNC;
+    
+    // Ensure that we're in a proper state
+    if ( iCurrentState != EOpenAndWaiting )
+        {
+        LOGGER_WRITE_1("CMmsDataStore::DoAddedItems, invalid state %d.", iCurrentState);
+        }
+    
+    TInt error(KErrNone);
+
+    // Clear new-items array
+    iNewItems->Reset();
+
+    // Set current snapshot, this will be compared against the old one      
+    // Search for new items
+    TRAP( error, iChangeFinder->FindNewItemsL(*iNewItems) )
+    if ( error != KErrNone )
+        {
+        LOGGER_WRITE_1("CMmsDataStore::DoAddedItems, iChangeFinder->FindNewItemsL leaved with %d.", error);
+        }
+    
+    LOGGER_WRITE_1("New item count: %d.", iNewItems->ItemCount());
+    
+    return *iNewItems;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoDeletedItems
+//
+// -----------------------------------------------------------------------------
+const MSmlDataItemUidSet& CMediaDsDataStore::DoDeletedItems() const
+    {
+    TRACE_FUNC;
+    
+    // Ensure that we're in a proper state
+    if ( iCurrentState != EOpenAndWaiting )
+        {
+        LOGGER_WRITE_1("CMmsDataStore::DoDeletedItems, invalid state %d.", iCurrentState);
+        }
+    
+    TInt error(KErrNone);
+    
+    // Clear deleted-items array
+    iDeletedItems->Reset();
+    
+    // Search for deleted items
+    TRAP( error, iChangeFinder->FindDeletedItemsL( *iDeletedItems ) );
+    if ( error != KErrNone )
+        {
+        LOGGER_WRITE_1("CMmsDataStore::DoDeletedItems, iChangeFinder->FindDeletedItemsL leaved with %d.", error);
+        }           
+    
+    LOGGER_WRITE_1("Deleted item count: %d.", iDeletedItems->ItemCount());
+    return *iDeletedItems;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoSoftDeletedItems
+// Not directly supported, equals to "hard" delete
+// -----------------------------------------------------------------------------
+const MSmlDataItemUidSet& CMediaDsDataStore::DoSoftDeletedItems() const
+    {
+    TRACE_FUNC;
+
+    iSoftDeletedItems->Reset();
+    return *iSoftDeletedItems;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoModifiedItems
+// Finds all modified items in the data store
+// -----------------------------------------------------------------------------
+const MSmlDataItemUidSet& CMediaDsDataStore::DoModifiedItems() const
+    {
+    TRACE_FUNC;
+    
+    // Ensure that we're in a proper state
+    if ( iCurrentState != EOpenAndWaiting )
+        {
+        LOGGER_WRITE_1("CMmsDataStore::DoModifiedItems, invalid state %d.", iCurrentState);
+        }
+    
+    TInt error(KErrNone);
+    
+    // Clear updated-items array
+    iUpdatedItems->Reset();
+    
+    // Search for updated items
+    TRAP( error, iChangeFinder->FindChangedItemsL( *iUpdatedItems ) )
+    if ( error != KErrNone )
+        {
+        LOGGER_WRITE_1("CMmsDataStore::DoModifiedItems, iChangeFinder->FindChangedItemsL leaved with %d.", error);
+        }
+    
+    LOGGER_WRITE_1("Modified item count: %d.", iUpdatedItems->ItemCount()); 
+    return *iUpdatedItems;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoMovedItems
+// Finds all moved items in the data store
+// -----------------------------------------------------------------------------
+const MSmlDataItemUidSet& CMediaDsDataStore::DoMovedItems() const
+    {
+    TRACE_FUNC;
+    // return empty array
+    return *iMovedItems;    
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoResetChangeInfoL
+// Resets change history in the data store. All content is considered
+// new in the data store point of view.
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoResetChangeInfoL( TRequestStatus& aStatus )
+    {
+    TRACE_FUNC_ENTRY;
+    
+    iCallerStatus = &aStatus;
+    *iCallerStatus = KRequestPending;
+    
+    // Check that we're in proper state
+    if ( iCurrentState != EOpenAndWaiting ) 
+        {
+        LOGGER_WRITE_1("CMmsDataStore::DoResetChangeInfoL, invalid state %d.", iCurrentState);
+        }   
+            
+    // Reset change info in ChangeFinder
+    iChangeFinder->ResetL();
+    iHasHistory = EFalse;
+    
+    // Signal we're done
+    User::RequestComplete( iCallerStatus, KErrNone ); 
+    
+    TRACE_FUNC_EXIT;
+    }
+        
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoCommitChangeInfoL
+// Commits change info. These items are no longer reported, when change
+// information is being queried.
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoCommitChangeInfoL( TRequestStatus& aStatus, const MSmlDataItemUidSet& aItems )
+    {
+    TRACE_FUNC_ENTRY;
+    
+    iCallerStatus = &aStatus;
+    *iCallerStatus = KRequestPending;
+    
+    // Ensure that we're in a proper state
+    if ( iCurrentState != EOpenAndWaiting ) 
+        {
+        LOGGER_WRITE_1("CMmsDataStore::DoCommitChangeInfoL, invalid state %d.", iCurrentState);
+        }
+
+    // Notify ChangeFinder
+    iChangeFinder->CommitChangesL(aItems);
+    iHasHistory = ETrue;
+        
+    // Signal we're done
+    User::RequestComplete(iCallerStatus, KErrNone);
+        
+    TRACE_FUNC_EXIT;
+    }
+        
+    
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::DoCommitChangeInfoL
+// Commits change info. There is no more nothing to report when change
+// information is being queried. 
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::DoCommitChangeInfoL(TRequestStatus& aStatus)
+    {
+    TRACE_FUNC_ENTRY;
+    
+    iCallerStatus = &aStatus;
+    *iCallerStatus = KRequestPending;
+    
+    // Ensure that we're in a proper state
+    if ( iCurrentState != EOpenAndWaiting ) 
+        {
+        LOGGER_WRITE_1("CMmsDataStore::DoCommitChangeInfoL, invalid state %d.", iCurrentState);
+        }
+    
+    // Notify ChangeFinder
+    iChangeFinder->CommitChangesL();
+    iHasHistory = ETrue;
+        
+    // Signal we're done
+    User::RequestComplete( iCallerStatus, KErrNone );
+    
+    TRACE_FUNC_EXIT;
+    }
+
+
+void CMediaDsDataStore::HandleCollectionMessage(CMPXMessage* /*aMsg*/, TInt /*aErr*/) 
+    {
+    TRACE_FUNC;
+    }
+
+void CMediaDsDataStore::HandleOpenL(const CMPXMedia& /*aEntries*/,
+        TInt /*aIndex*/,TBool /*aComplete*/,TInt /*aError*/)
+    {
+    TRACE_FUNC;
+    }
+
+void CMediaDsDataStore::HandleOpenL(const CMPXCollectionPlaylist& /*aPlaylist*/,
+        TInt /*aError*/)
+    {
+    TRACE_FUNC;
+    }
+    
+void CMediaDsDataStore::HandleCommandComplete(CMPXCommand* /*aCommandResult*/, 
+         TInt /*aError*/)
+    {
+    TRACE_FUNC;
+    }
+
+void CMediaDsDataStore::HandleCollectionMediaL(const CMPXMedia& /*aMedia*/, 
+        TInt /*aError*/)
+    {
+    TRACE_FUNC;
+    }
+
+void CMediaDsDataStore::AlbumsReaded( TInt aError )
+    {
+    TRACE_FUNC_ENTRY;
+    iMdEManagerReady = ETrue;
+    LOGGER_WRITE_1("aError: %d", aError );
+    
+    if ( aError )
+        {
+        iError = aError;
+        }
+    
+    FinalizeOpenStore();
+    
+    TRACE_FUNC_EXIT;
+    }
+
+void CMediaDsDataStore::AlbumReplaced( TInt aError )
+    {
+    TRACE_FUNC_ENTRY;
+    LOGGER_WRITE_1("aError: %d", aError);
+    if ( !aError )
+        {
+        // Inform ChangeFinder of the replaced item
+        iChangeFinder->ItemUpdatedL( iItemInReplacement );
+        }
+    
+    iCurrentState = EOpenAndWaiting;
+    User::RequestComplete( iCallerStatus, aError );
+    TRACE_FUNC_EXIT;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::RegisterSnapshotL
+// Sets Changefinder to compare against current message store content
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::RegisterSnapshotL()
+    {
+    TRACE_FUNC_ENTRY;
+    if ( iSnapshot )
+        {
+        delete iSnapshot;
+        iSnapshot = NULL;
+        }
+    iSnapshot = new (ELeave) CSnapshotArray( KSnapshotGranularity );
+    RegisterFoldersL( *iSnapshot );
+    iMediaManager->SetSnapshot( iSnapshot );
+    
+    iCurrentState = EOpening;
+    TInt err = iMediaManager->RegisterAllPlayLists();
+    if ( err )
+        {
+        LOGGER_WRITE_1("Could not start, err: %d", err);
+        iCurrentState = EClosed;
+        User::RequestComplete( iCallerStatus, err );
+        }
+    else
+        {
+        iMdEManager->GetAlbumsL();
+        }
+
+    
+    TRACE_FUNC_EXIT;
+    }
+
+void CMediaDsDataStore::RegisterAllPlayListsCompleted( TInt aError )
+    {
+    TRACE_FUNC_ENTRY;
+    if ( !aError )
+        {
+        TInt err = iMediaManager->RegisterAllSongs();
+        if ( err )
+            {
+            LOGGER_WRITE_1("Could not start, err: %d", err);
+            iMediaManagerReady = ETrue;
+            iError = err;
+            }
+        }
+    else
+        {
+        // Error happened or cancelled.
+        iMediaManagerReady = ETrue;
+        iError = aError;
+        }
+    
+    FinalizeOpenStore();
+    TRACE_FUNC_EXIT;
+    }
+
+void CMediaDsDataStore::RegisterAllSongsCompleted( TInt aError )
+    {
+    TRACE_FUNC_ENTRY;
+    iMediaManagerReady = ETrue;
+    if ( aError )
+        {
+        // Error happened or cancelled, save error code
+        iError = aError;
+        }
+    
+    FinalizeOpenStore();
+    
+    TRACE_FUNC_EXIT;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediaDsDataStore::RegisterFoldersL
+// 
+// -----------------------------------------------------------------------------
+void CMediaDsDataStore::RegisterFoldersL( CSnapshotArray& aItemArray )
+    {
+    TRACE_FUNC_ENTRY;
+    
+    TKeyArrayFix key( iKey );
+    TSnapshotItem folder;
+    folder.SetItemId( KAllSongsFolderId );
+    folder.SetItemHash( KAllSongs, *iHasher );
+    aItemArray.InsertIsqL( folder, key );
+    
+    folder.SetItemId( KPlaylistsFolderId );
+    folder.SetItemHash( KPlaylists, *iHasher );
+    aItemArray.InsertIsqL( folder, key );
+    
+    folder.SetItemId( KAlbumsFolderId );
+    folder.SetItemHash( KAlbums, *iHasher );
+    aItemArray.InsertIsqL( folder, key );
+    TRACE_FUNC_EXIT;
+    }
+
+void CMediaDsDataStore::FinalizeOpenStore()
+    {
+    TRACE_FUNC_ENTRY;
+    // Signal client if all ready
+    if ( iMediaManagerReady && iMdEManagerReady )
+        {
+        if ( !iError )
+            {
+            RPointerArray<CPlaylistItem> albums = iMdEManager->AlbumsArray();
+            TKeyArrayFix key( iKey );
+            LOGGER_WRITE("Album snapshots:")
+            for (TInt i=0; i<albums.Count(); i++)
+                {
+                TSnapshotItem playlistItem( MapAlbumIdToSyncId( albums[i]->Id() ) );
+                playlistItem.SetItemHash( *albums[i], *iHasher );
+                playlistItem.SetParentId( KAlbumsFolderId );
+                TRAP(iError, iSnapshot->InsertIsqL( playlistItem, key ));
+                if ( iError )
+                    {
+                    LOGGER_WRITE_1("iSnapshot->InsertIsqL err: %d", iError);
+                    iError = KErrGeneral;
+                    }
+                }
+            
+            if ( !iError )
+                {
+                // Set new snapshot to compare against
+                iChangeFinder->SetNewSnapshot(iSnapshot);
+                
+                // Changefinder takes ownership of the snapshot
+                iSnapshot = NULL;
+                iCurrentState = EOpenAndWaiting;
+                }
+            }
+        
+        if ( iError )
+            {
+            iCurrentState = EClosed;
+            }
+        
+        LOGGER_WRITE_1("Signal client with %d", iError);
+        User::RequestComplete( iCallerStatus, iError );
+        }
+    TRACE_FUNC_EXIT;
+    }
+
+inline TInt CMediaDsDataStore::MapSyncIdToAlbumId( TSmlDbItemUid aSyncId )
+    {
+    return aSyncId - KAlbumsOffSet;
+    }
+
+inline TSmlDbItemUid CMediaDsDataStore::MapAlbumIdToSyncId( TInt aAlbumId )
+    {
+    return KAlbumsOffSet + aAlbumId;
+    }