connectivitymodules/SeCon/servers/syncserver/src/sconasynchandler.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:20:56 +0100
branchRCL_3
changeset 20 4a793f564d72
parent 18 453dfc402455
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201032 Kit: 201035

/*
* 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:  CSconAsyncHandler implementation
*
*/


#include "sconasynchandler.h"

#include <ecom/ecom.h>
#include <SmlDataProvider.h>
#include <s32mem.h>
#include <nsmlchangefinder.h>
#include <e32cmn.h>
#include <ecom/ImplementationInformation.h>
#include <mmf/common/mmfcontrollerpluginresolver.h>

#include "sconsyncclientserver.h"
#include "sconsyncrelationship.h"
#include "scondataproviderinfo.h"
#include "debug.h"
#include "logdatastoreformat.h"

// Data Store interface implementation Uid.
// Load all plugins with this uid.
const TUid KDSEcomIFUid = {0x101F4D3A};

const TInt KDefaultExpandSize = 1024;

// one store per computer, max store count.
const TInt KMaxStoresCount = 10;

const TInt KDefaultTimeOutInMicroSeconds = 30 * 1000000; // 30 seconds
const TInt KDeleteAllTimeOutInMicroSeconds = 300 * 1000000; // 5 minutes
const TInt KOpenStoreTimeOutInMicroSeconds = 180 * 1000000; // 180 seconds

CSconAsyncHandler::~CSconAsyncHandler()
    {
    TRACE_FUNC_ENTRY;
    Cancel();
    DoCloseStore();
    delete iItems;
    delete iWriteData;
    delete iDataStore;
    delete iDataProvider;
    delete iContext;
    delete iStoreFormat;
    iStringPool.Close();
    iFs.Close();
    REComSession::FinalClose();
    iChunk.Close();
    delete iTimeOut;
    TRACE_FUNC_EXIT;
    }

CSconAsyncHandler::CSconAsyncHandler(): CActive( EPriorityStandard )
    {
    TRACE_FUNC;
    CActiveScheduler::Add( this );
    }

CSconAsyncHandler* CSconAsyncHandler::NewL()
    {
    TRACE_FUNC;
    CSconAsyncHandler* self = new(ELeave) CSconAsyncHandler();
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }

void CSconAsyncHandler::ConstructL()
    {
    TRACE_FUNC;
    User::LeaveIfError( iFs.Connect() );
    TInt err = iFs.CreatePrivatePath( EDriveC );
    LOGGER_WRITE_1("CreatePrivatePath err: %d", err);
    iStringPool.OpenL();
    iTimeOut = CCSconTimeOut::NewL( *this );
    }

// -----------------------------------------------------------------------------
// CSconAsyncHandler::HandleServiceL()
// Handles the client request
// -----------------------------------------------------------------------------
//
void CSconAsyncHandler::HandleServiceL( const RMessage2& aMessage )
    {
    TRACE_FUNC_ENTRY;
    if ( aMessage.Function() == ECancelRequest )
        {
        LOGGER_WRITE("ECancelRequest");
        if ( IsActive() )
            {
            Cancel();
            LOGGER_WRITE("iMessage.Complete( KErrCancel )");
            CompleteRequest( KErrCancel );
            }
        
        LOGGER_WRITE("aMessage.Complete( KErrNone )");
        aMessage.Complete( KErrNone );
        TRACE_FUNC_EXIT;
        return;
        }
    
    iTimeOut->Start( KDefaultTimeOutInMicroSeconds );
    
    iMessage = aMessage;
    switch ( aMessage.Function() )
        {
        case ESendChunkHandle:
            LOGGER_WRITE( "CSconSyncSession::ServiceL() : ESendChunkHandle" );
            HandleChunkMessage();
            break;
            
        case EListImplementations:
            LOGGER_WRITE( "CSconSyncSession::ServiceL() : EListImplementations" );
            ListAllImplementationsL();
            break;
            
        case EOpenStore:
            LOGGER_WRITE( "CSconSyncSession::ServiceL() : EOpenStore" );
            iTimeOut->Start( KOpenStoreTimeOutInMicroSeconds );
            OpenStoreL();
            break;
            
        case EOpenItem:
            OpenItemL();
            break;
        case ECreateItem:
            CreateItemL();
            break;
        case EReplaceItem:
            ReplaceItemL();
            break;
        case EMoveItem:
            MoveItemL();
            break;
        case EDeleteItem:
            DeleteItemL();
            break;
        case ESoftDeleteItem:
            SoftDeleteItemL();
            break;
        case EDeleteAllItems:
            iTimeOut->Start( KDeleteAllTimeOutInMicroSeconds );
            DeleteAllItemsL();
            break;
        case EReadParent:
            ReadParentL();
            break;
            
        case EHasHistory:
            HasHistoryL();
            break;
        case EAddedItems:
            AddedItemsL();
            break;
        case EDeletedItems:
            DeletedItemsL();
            break;
        case ESoftDeletedItems:
            SoftDeletedItemsL();
            break;
        case EModifiedItems:
            ModifiedItemsL();
            break;
        case EMovedItems:
            MovedItemsL();
            break;
        case EResetChangeInfo:
            ResetChangeInfoL();
            break;
        case ECommitChangeInfo:
            CommitChangeInfoL();
            break;
        case ECloseStore:
            CloseStore();
            break;
        case ESetSyncTimeStamp:
            SetSyncTimeStampL();
            break;
        case EGetSyncTimeStamp:
            GetSyncTimeStampL();
            break;
        case EExportStoreFormat:
            ExportStoreFormatL();
            break;
        case ESetRemoteStoreFormat:
            SetRemoteStoreFormatL();
            break;
            
        default:
            aMessage.Complete(KErrNotSupported);
            break;
        }
    TRACE_FUNC_EXIT;
    }


void CSconAsyncHandler::RunL()
    {
    TRACE_FUNC_ENTRY;
    LOGGER_WRITE_1("iStatus.Int(): %d", iStatus.Int());
    switch ( iMessage.Function() )
        {
        case EOpenStore:
            LOGGER_WRITE( "CSconAsyncHandler::RunL() : EOpenStore" );
            CompleteRequest( iStatus.Int() );
            break;
            
        case EOpenItem:
            LOGGER_WRITE( "CSconAsyncHandler::RunL() : EOpenItem" );
            OpenItemCompletedL( iStatus.Int() );
            break;
            
        case ECreateItem:
            LOGGER_WRITE( "CSconAsyncHandler::RunL() : ECreateItem" );
            if (!iCommitInProgress)
                {
                // Write data to item
                CreateItemCompletedL( iStatus.Int() );
                }
            else
                {
                // commit is done, all ready
                LOGGER_WRITE( "CSconAsyncHandler::RunL() : ECreateItem, commit done" );
                TPckg<TSmlDbItemUid> pckg(iNewItem);
                iMessage.WriteL( 0, pckg, 0);
                CompleteRequest( iStatus.Int() );
                }
            break;
            
        case EReplaceItem:
            LOGGER_WRITE( "CSconAsyncHandler::RunL() : EReplaceItem" );
            if (!iCommitInProgress)
                {
                // Write data to item
                ReplaceItemCompletedL( iStatus.Int() );
                }
            else
                {
                // commit is done, all ready
                LOGGER_WRITE( "CSconAsyncHandler::RunL() : EReplaceItem, commit done" );
                CompleteRequest( iStatus.Int() );
                }
            break;
            
        case EMoveItem:
            LOGGER_WRITE( "CSconAsyncHandler::RunL() : EMoveItem" );
            CompleteRequest( iStatus.Int() );
            break;
            
        case EDeleteItem:
            LOGGER_WRITE( "CSconAsyncHandler::RunL() : EDeleteItem" );
            CompleteRequest( iStatus.Int() );
            break;
            
        case ESoftDeleteItem:
            LOGGER_WRITE( "CSconAsyncHandler::RunL() : ESoftDeleteItem" );
            CompleteRequest( iStatus.Int() );
            break;
            
        case EDeleteAllItems:
            LOGGER_WRITE( "CSconAsyncHandler::RunL() : EDeleteAllItems" );
            CompleteRequest( iStatus.Int() );
            break;
            
        case EReadParent:
            LOGGER_WRITE( "CSconAsyncHandler::RunL() : EReadParent" );
            ReadParentCompletedL( iStatus.Int() );
            break;
            
        case EResetChangeInfo:
            LOGGER_WRITE( "CSconAsyncHandler::RunL() : EResetChangeInfo" );
            CompleteRequest( iStatus.Int() );
            break;
            
        case ECommitChangeInfo:
            LOGGER_WRITE( "CSconAsyncHandler::RunL() : ECommitChangeInfo" );
            delete iItems;
            iItems = NULL;
            CompleteRequest( iStatus.Int() );
            break;
            
        default:
            LOGGER_WRITE("Not asynchronous function")
            CompleteRequest( KErrNotSupported );
            break;
        }
    TRACE_FUNC_EXIT;
    }

TInt CSconAsyncHandler::RunError(TInt aError)
    {
    LOGGER_WRITE_1("CSconAsyncHandler::RunError() aError: %d", aError);
    delete iItems;
    iItems = NULL;
    delete iWriteData;
    iWriteData = NULL;
    
    if ( IsActive() )
        {
        LOGGER_WRITE("IsActive");
        //iDataStore->CancelRequest();
        Cancel();
        }
    
    if ( iDataStore && iMessage.Function() == EOpenItem )
        {
        LOGGER_WRITE( "CSconAsyncHandler::RunError() : EOpenItem" );
        iDataStore->CloseItem();
        }
    
    CompleteRequest( aError );
    aError = KErrNone;
    LOGGER_WRITE_1("CSconAsyncHandler::RunError() : Return %d", aError);
    return aError;
    //return KErrNone;//aError;
    }

void CSconAsyncHandler::DoCancel()
    {
    TRACE_FUNC_ENTRY;
    iDataStore->CancelRequest();
    iTimeOut->Cancel();
    
    if ( iStatus == KRequestPending )
        {
        LOGGER_WRITE( "iStatus == KRequestPending" );
        }
    
    if ( iDataStore && iMessage.Function() == EOpenItem )
        {
        LOGGER_WRITE( "CSconAsyncHandler::RunError() : EOpenItem" );
        iDataStore->CloseItem();
        }
    
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::TimeOut()
    {
    TRACE_FUNC_ENTRY;
    if ( IsActive() )
        {
        Cancel();
        CompleteRequest( KErrCancel );
        }
    TRACE_FUNC_EXIT;
    }


void CSconAsyncHandler::HandleChunkMessage()
    {
    TRACE_FUNC_ENTRY;
    TInt ret ( KErrNone );
    
    ret = iChunk.Open( iMessage, 0, EFalse );
        
    LOGGER_WRITE_1( "CSconAsyncHandler::HandleChunkMessageL() : ret %d", ret );
    CompleteRequest( ret );
    }



void CSconAsyncHandler::ListAllImplementationsL()
    {
    TRACE_FUNC_ENTRY;
    
    RImplInfoPtrArray implInfoArray;
    CleanupResetAndDestroyPushL( implInfoArray );
    REComSession::ListImplementationsL( KDSEcomIFUid, implInfoArray );
    
    const TInt KDataproviderInfoSize = 250; // 250 bytes should be enought
    TInt requiredSize = implInfoArray.Count() * KDataproviderInfoSize;
    if ( iChunk.Size() < requiredSize )
        {
        User::LeaveIfError( iChunk.Adjust( requiredSize ) );
        }
    
    RMemWriteStream stream ( iChunk.Base(), iChunk.Size() );
    CleanupClosePushL( stream );
    
    RSconDataProviderInfoArray dpInfoArray;
    CleanupResetAndDestroyPushL( dpInfoArray );
    
    // Collect information from dataproviders
    for ( TInt i=0; i < implInfoArray.Count(); i++ )
        {
        LOGGER_WRITE_1("implInfoArray: %d",i);
        CImplementationInformation& implInfo = *implInfoArray[i];
        
        CSmlDataProvider* dp(NULL);
        TRAPD( err, dp = CSmlDataProvider::NewL( implInfo.ImplementationUid().iUid ) );
        LOGGER_WRITE_2("CSmlDataProvider::NewL, uid(0x%08x) err: %d",implInfo.ImplementationUid().iUid, err );
        if ( !err )
            {
            CleanupStack::PushL( dp );
            
            CSconDataproviderInfo *dpInfo = CSconDataproviderInfo::NewL();
            CleanupStack::PushL( dpInfo );
            
            dpInfo->SetImplementationUid( implInfo.ImplementationUid() );
            LOGGER_WRITE_1("ImplementationUid: 0x%08x", implInfo.ImplementationUid().iUid );
            dpInfo->SetDisplayNameL( implInfo.DisplayName() );
            LOGGER_WRITE_1("DisplayName: %S", &implInfo.DisplayName() );
            
            dpInfo->SetDefaultStoreL( dp->DefaultStoreL() );
            LOGGER_WRITE_1("DefaultStoreL: %S", &dp->DefaultStoreL() );
            CDesCArray* stores = dp->ListStoresLC();
            dpInfo->SetStoresL( *stores );
            CleanupStack::PopAndDestroy( stores );
            
            dpInfoArray.AppendL( dpInfo );
            CleanupStack::Pop( dpInfo );
            
            CleanupStack::PopAndDestroy( dp );
            }
        }
    
    // Wrtie to stream
    stream.WriteUint16L( dpInfoArray.Count() );
    for ( TInt i = 0; i < dpInfoArray.Count(); i++ )
        {
        CSconDataproviderInfo& dpInfo = *dpInfoArray[i];
        dpInfo.ExternalizeL( stream );
        }
    
    stream.CommitL();
    
    CleanupStack::PopAndDestroy( &dpInfoArray );
    CleanupStack::PopAndDestroy( &stream );
    CleanupStack::PopAndDestroy( &implInfoArray );
    
    CompleteRequest( KErrNone );
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::OpenStoreL()
    {
    TRACE_FUNC_ENTRY;
    if ( iDataStore )
        {
        LOGGER_WRITE("Warning: Previous DataStore was not closed properly.");
        DoCloseStore();
        }
    
    // copy data from the chunk
    RMemReadStream readStream( iChunk.Base(), iChunk.Size() );
    CleanupClosePushL( readStream );
    
    TSmlDataProviderId providerId = readStream.ReadUint32L();
    LOGGER_WRITE_1("providerId: 0x%08x", providerId);
    
    TInt len = readStream.ReadUint32L();
    HBufC* storeName = HBufC::NewLC(len);
    TPtr storeNamePtr = storeName->Des();
    readStream.ReadL(storeNamePtr, len);
    LOGGER_WRITE_1("storeName: %S", &storeNamePtr);
    
    TInt contextUid = readStream.ReadUint32L();
    
    LOGGER_WRITE_1("contextIdentifier: 0x%08x", contextUid);
    
    LOGGER_WRITE("Open provider");
    delete iDataProvider;
    iDataProvider = NULL;
    iDataProvider = CSmlDataProvider::NewL( providerId );
    
    delete iContext;
    iContext = NULL;
    
    delete iStoreFormat;
    iStoreFormat = NULL;

    LOGGER_WRITE("Create context");
    iContext = CSconSyncRelationship::NewL( iFs, TUid::Uid(contextUid), providerId );
    
    
    LOGGER_WRITE("Create NewStoreInstanceLC");
    iDataStore = iDataProvider->NewStoreInstanceLC();
    CleanupStack::Pop( iDataStore );
    
    SetActive();
    iStatus = KRequestPending;
    LOGGER_WRITE("OpenL");
    TRAPD(err, iDataStore->OpenL(storeNamePtr,*iContext, iStatus));
    if ( err )
        {
        // we are on active state, call request completed (RunL)
        LOGGER_WRITE_1("iDataStore->OpenL leaved with err: %d", err);
        TRequestStatus* status = &iStatus;
        User::RequestComplete( status, err );
        }
    
    CleanupStack::PopAndDestroy( storeName );
    CleanupStack::PopAndDestroy( &readStream );
    
    TRACE_FUNC_EXIT;
    }


void CSconAsyncHandler::OpenItemL()
    {
    TRACE_FUNC_ENTRY;
    LeaveIfNoInstanceL();
    if ( IsActive() )
        {
        LOGGER_WRITE("Was still in Active");
        Cancel();
        }
    
    TSmlDbItemUid itemUid = iMessage.Int0();
    LOGGER_WRITE_1("Open item: %d", itemUid);
    
    // set default values
    iFieldChange = EFalse;
    iSize = 0;
    iParent = 0;
    iMimeType.Copy(KNullDesC);
    iMimeVer.Copy(KNullDesC);
    
    SetActive();
    LOGGER_WRITE("iDataStore->OpenItemL");
    iStatus = KRequestPending;
    TRAPD( err, iDataStore->OpenItemL(itemUid,iFieldChange,iSize,iParent,iMimeType,iMimeVer,iStatus));
    if ( err )
        {
        // we are on active state, call request completed (RunL)
        LOGGER_WRITE_1("iDataStore->OpenItemL leaved with err: %d", err);
        TRequestStatus* status = &iStatus;
        User::RequestComplete( status, err );
        }
    
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::OpenItemCompletedL( TInt aError )
    {
    TRACE_FUNC_ENTRY;
    // item opened, now read it
    if ( aError )
        {
        CompleteRequest( aError );
        return;
        }
    LeaveIfNoInstanceL();
    
    LOGGER_WRITE_1("item size: %d", iSize);
    
    TInt totalObjectSize( 0 );
    totalObjectSize+= sizeof(TInt32);   // data length
    totalObjectSize+= iSize;            // data
    totalObjectSize+= sizeof(TInt8);    // iFieldChange
    totalObjectSize+= sizeof(TInt32);   // iParent
    totalObjectSize+= sizeof(TInt32);   // iMimeType
    totalObjectSize+= iMimeType.Length();  // iMimeType
    totalObjectSize+= sizeof(TInt32);   // iMimeVer
    totalObjectSize+= iMimeVer.Length();  // iMimeType
    
    LOGGER_WRITE_1("iChunk.Size(): %d", iChunk.Size());
    LOGGER_WRITE_1("iChunk.MaxSize(): %d", iChunk.MaxSize());
    LOGGER_WRITE_1("totalObjectSize: %d", totalObjectSize);
    
    if ( iChunk.Size() < totalObjectSize )
        {
        LOGGER_WRITE("adjust chunk");
        TInt err = iChunk.Adjust( totalObjectSize );
        LOGGER_WRITE_1("Chunk.Adjust err: %d", err);
        User::LeaveIfError( err );
        }
    LOGGER_WRITE_1("new Chunk size: %d", iChunk.Size());
    LOGGER_WRITE_1("new ChunkMaxSize(): %d", iChunk.MaxSize());
    RMemWriteStream stream ( iChunk.Base(), iChunk.Size() );
    CleanupClosePushL( stream );
    
    LOGGER_WRITE("ReadItemL");
    HBufC8* tempBuf = HBufC8::NewLC(iSize);
    TPtr8 tempPtr = tempBuf->Des();
    
    TUint8* ptr = (TUint8*) tempPtr.Ptr();
    
    TPtr8 tempPtr2( ptr, 0, iSize );
    LOGGER_WRITE_1( "tempPtr2.Size(): %d", tempPtr2.Size());
    iDataStore->ReadItemL( tempPtr2 );
    LOGGER_WRITE("ReadItemL -ok");
    
    LOGGER_WRITE_1("readed Length: %d", tempPtr2.Length() );
    LOGGER_WRITE_1("readed Size: %d", tempPtr2.Size() );
    
    LOGGER_WRITE8_1("iMimeType: %S", &iMimeType );
    LOGGER_WRITE_1("iMimeType.Length(): %d", iMimeType.Length() );
    LOGGER_WRITE_1("iMimeType Size: %d", iMimeType.Size() );
    
    LOGGER_WRITE8_1("iMimeVer: %S", &iMimeVer );
    LOGGER_WRITE_1("iMimeVer.Length(): %d", iMimeVer.Length() );
    LOGGER_WRITE_1("iMimeVer Size: %d", iMimeVer.Size() );
    
    iDataStore->CloseItem();
    LOGGER_WRITE("Write to chunk");
    stream.WriteInt32L( tempPtr2.Length() );
    stream.WriteL( tempPtr2 );
    CleanupStack::PopAndDestroy( tempBuf );
    
    stream.WriteInt8L( (TInt)iFieldChange );
    stream.WriteInt32L( iParent );
    stream.WriteInt32L( iMimeType.Length() );
    stream.WriteL( iMimeType );
    stream.WriteInt32L( iMimeVer.Length() );
    stream.WriteL( iMimeVer );
    
    stream.CommitL();
    LOGGER_WRITE("Writed ok");
    CleanupStack::PopAndDestroy( &stream );
    CompleteRequest( KErrNone );
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::CreateItemL()
    {
    TRACE_FUNC_ENTRY;
    LeaveIfNoInstanceL();
    iCommitInProgress = EFalse;
    RMemReadStream readStream( iChunk.Base(), iChunk.Size() );
    CleanupClosePushL( readStream );
    
    TSmlDbItemUid parent = readStream.ReadUint32L();
    TInt len = readStream.ReadUint32L();
    readStream.ReadL(iMimeType, len);
    len = readStream.ReadUint32L();
    readStream.ReadL(iMimeVer, len);
    len = readStream.ReadUint32L();
    delete iWriteData;
    iWriteData = NULL;
    iWriteData = HBufC8::New(len);
    TPtr8 dataPtr = iWriteData->Des();
    readStream.ReadL(dataPtr, len);
    CleanupStack::PopAndDestroy( &readStream );
    SetActive();
    iStatus = KRequestPending;
    TRAPD(err, iDataStore->CreateItemL( iNewItem, dataPtr.Size(), parent, iMimeType, iMimeVer, iStatus ));
    if ( err )
        {
        // we are on active state, call request completed (RunL)
        LOGGER_WRITE_1("iDataStore->CreateItemL leaved with err: %d", err);
        TRequestStatus* status = &iStatus;
        User::RequestComplete( status, err );
        }
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::CreateItemCompletedL( TInt aError )
    {
    TRACE_FUNC_ENTRY;
    User::LeaveIfError( aError );
    LeaveIfNoInstanceL();
    // CreateItem completed, now we must write the data to the created item and commit it.
    
    iDataStore->WriteItemL( iWriteData->Des() );
    delete iWriteData;
    iWriteData = NULL;
    SetActive();
    iStatus = KRequestPending;
    TRAPD(err, iDataStore->CommitItemL( iStatus ));
    if ( err )
        {
        // we are on active state, call request completed (RunL)
        LOGGER_WRITE_1("iDataStore->CommitItemL leaved with err: %d", err);
        TRequestStatus* status = &iStatus;
        User::RequestComplete( status, err );
        }
    iCommitInProgress = ETrue;
    
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::ReplaceItemL()
    {
    TRACE_FUNC_ENTRY;
    LeaveIfNoInstanceL();
    
    iCommitInProgress = EFalse;
    RMemReadStream readStream( iChunk.Base(), iChunk.Size() );
    CleanupClosePushL( readStream );
    
    TSmlDbItemUid uid = readStream.ReadUint32L();
    TSmlDbItemUid parent = readStream.ReadUint32L();
    TBool fieldChange = readStream.ReadUint8L();
    TInt len = readStream.ReadUint32L();
    delete iWriteData;
    iWriteData = NULL;
    iWriteData = HBufC8::New(len);
    TPtr8 dataPtr = iWriteData->Des();
    readStream.ReadL(dataPtr, len);
    
    CleanupStack::PopAndDestroy( &readStream );
    SetActive();
    iStatus = KRequestPending;
    TRAPD(err,iDataStore->ReplaceItemL( uid,dataPtr.Size(),parent,fieldChange, iStatus ));
    if ( err )
        {
        // we are on active state, call request completed (RunL)
        LOGGER_WRITE_1("iDataStore->CommitItemL leaved with err: %d", err);
        TRequestStatus* status = &iStatus;
        User::RequestComplete( status, err );
        }
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::ReplaceItemCompletedL( TInt aError )
    {
    TRACE_FUNC_ENTRY;
    User::LeaveIfError( aError );
    LeaveIfNoInstanceL();
    // CreateItem completed, now we must write the data to the created item and commit it.
    
    iDataStore->WriteItemL( iWriteData->Des() );
    delete iWriteData;
    iWriteData = NULL;
    
    SetActive();
    iStatus = KRequestPending;
    TRAPD(err, iDataStore->CommitItemL( iStatus ));
    if ( err )
        {
        // we are on active state, call request completed (RunL)
        LOGGER_WRITE_1("iDataStore->CommitItemL leaved with err: %d", err);
        TRequestStatus* status = &iStatus;
        User::RequestComplete( status, err );
        }
    iCommitInProgress = ETrue;
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::MoveItemL()
    {
    TRACE_FUNC_ENTRY;
    LeaveIfNoInstanceL();
    TSmlDbItemUid uid = iMessage.Int0();
    TSmlDbItemUid newParent = iMessage.Int1();
    LOGGER_WRITE_1( "uid: %d", uid );
    LOGGER_WRITE_1( "newParent: %d", newParent );
    
    SetActive();
    iStatus = KRequestPending;
    TRAPD(err, iDataStore->MoveItemL( uid, newParent, iStatus )); 
    if ( err )
        {
        // we are on active state, call request completed (RunL)
        LOGGER_WRITE_1("iDataStore->MoveItemL leaved with err: %d", err);
        TRequestStatus* status = &iStatus;
        User::RequestComplete( status, err );
        }
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::DeleteItemL()
    {
    TRACE_FUNC_ENTRY;
    LeaveIfNoInstanceL();
    
    TSmlDbItemUid uid = iMessage.Int0();
    LOGGER_WRITE_1( "uid: %d", uid );
    
    SetActive();
    iStatus = KRequestPending;
    TRAPD(err, iDataStore->DeleteItemL( uid, iStatus ));
    if ( err )
        {
        // we are on active state, call request completed (RunL)
        LOGGER_WRITE_1("iDataStore->DeleteItemL leaved with err: %d", err);
        TRequestStatus* status = &iStatus;
        User::RequestComplete( status, err );
        }
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::SoftDeleteItemL()
    {
    TRACE_FUNC_ENTRY;
    LeaveIfNoInstanceL();
    
    TSmlDbItemUid uid = iMessage.Int0();
    LOGGER_WRITE_1( "uid: %d", uid );
    
    SetActive();
    iStatus = KRequestPending;
    TRAPD(err, iDataStore->SoftDeleteItemL( uid, iStatus ));
    if ( err )
        {
        // we are on active state, call request completed (RunL)
        LOGGER_WRITE_1("iDataStore->SoftDeleteItemL leaved with err: %d", err);
        TRequestStatus* status = &iStatus;
        User::RequestComplete( status, err );
        }
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::DeleteAllItemsL()
    {
    TRACE_FUNC_ENTRY;
    LeaveIfNoInstanceL();
    
    SetActive();
    iStatus = KRequestPending;
    TRAPD(err, iDataStore->DeleteAllItemsL( iStatus ));
    if ( err )
        {
        // we are on active state, call request completed (RunL)
        LOGGER_WRITE_1("iDataStore->DeleteAllItemsL leaved with err: %d", err);
        TRequestStatus* status = &iStatus;
        User::RequestComplete( status, err );
        }
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::ReadParentL()
    {
    TRACE_FUNC_ENTRY;
    OpenItemL();
    
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::ReadParentCompletedL( TInt aError )
    {
    TRACE_FUNC_ENTRY;
    // item opened, now read it
    if ( aError )
        {
        CompleteRequest( aError );
        return;
        }
    LeaveIfNoInstanceL();
    
    iDataStore->CloseItem();
    
    TPckg<TSmlDbItemUid> pckg(iParent);
    iMessage.WriteL( 1, pckg, 0);
    CompleteRequest( KErrNone );
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::HasHistoryL()
    {
    TRACE_FUNC_ENTRY;
    LeaveIfNoInstanceL();
    TBool hasHistory = iDataStore->HasSyncHistory();
    
    TPckgC<TBool> pckg(hasHistory);
    iMessage.WriteL( 0, pckg, 0);
    CompleteRequest( KErrNone );
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::AddedItemsL()
    {
    TRACE_FUNC_ENTRY;
    LeaveIfNoInstanceL();
    const MSmlDataItemUidSet& items = iDataStore->AddedItems();
    
    RMemWriteStream stream ( iChunk.Base(), iChunk.Size() );
    CleanupClosePushL( stream );
    items.ExternalizeL( stream );
    CleanupStack::PopAndDestroy( &stream );
    
    CompleteRequest( KErrNone );
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::DeletedItemsL()
    {
    TRACE_FUNC_ENTRY;
    LeaveIfNoInstanceL();
    const MSmlDataItemUidSet& items = iDataStore->DeletedItems();
    
    RMemWriteStream stream ( iChunk.Base(), iChunk.Size() );
    CleanupClosePushL( stream );
    items.ExternalizeL( stream );
    CleanupStack::PopAndDestroy( &stream );
    
    CompleteRequest( KErrNone );
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::SoftDeletedItemsL()
    {
    TRACE_FUNC_ENTRY;
    LeaveIfNoInstanceL();
    const MSmlDataItemUidSet& items = iDataStore->SoftDeletedItems();
    
    RMemWriteStream stream ( iChunk.Base(), iChunk.Size() );
    CleanupClosePushL( stream );
    items.ExternalizeL( stream );
    CleanupStack::PopAndDestroy( &stream );
    
    CompleteRequest( KErrNone );
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::ModifiedItemsL()
    {
    TRACE_FUNC_ENTRY;
    LeaveIfNoInstanceL();
    const MSmlDataItemUidSet& items = iDataStore->ModifiedItems();
    
    RMemWriteStream stream ( iChunk.Base(), iChunk.Size() );
    CleanupClosePushL( stream );
    items.ExternalizeL( stream );
    CleanupStack::PopAndDestroy( &stream );
    
    CompleteRequest( KErrNone );
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::MovedItemsL()
    {
    TRACE_FUNC_ENTRY;
    LeaveIfNoInstanceL();
    const MSmlDataItemUidSet& items = iDataStore->MovedItems();
    
    RMemWriteStream stream ( iChunk.Base(), iChunk.Size() );
    CleanupClosePushL( stream );
    items.ExternalizeL( stream );
    CleanupStack::PopAndDestroy( &stream );
    
    CompleteRequest( KErrNone );
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::ResetChangeInfoL()
    {
    TRACE_FUNC_ENTRY;
    LeaveIfNoInstanceL();
    SetActive();
    iStatus = KRequestPending;
    TRAPD(err, iDataStore->ResetChangeInfoL( iStatus ));
    if ( err )
        {
        // we are on active state, call request completed (RunL)
        LOGGER_WRITE_1("iDataStore->ResetChangeInfoL leaved with err: %d", err);
        TRequestStatus* status = &iStatus;
        User::RequestComplete( status, err );
        }
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::CommitChangeInfoL()
    {
    TRACE_FUNC_ENTRY;
    LeaveIfNoInstanceL();
    RMemReadStream readStream( iChunk.Base(), iChunk.Size() );
    CleanupClosePushL( readStream );
    
    if ( iItems )
        {
        delete iItems;
        iItems = NULL;
        }
    iItems = new (ELeave) CNSmlDataItemUidSet();
    iItems->InternalizeL( readStream );
    
    CleanupStack::PopAndDestroy( &readStream );
    
    SetActive();
    iStatus = KRequestPending;
    TRAPD(err, iDataStore->CommitChangeInfoL( iStatus, *iItems ));
    if ( err )
        {
        // we are on active state, call request completed (RunL)
        LOGGER_WRITE_1("iDataStore->CommitChangeInfoL leaved with err: %d", err);
        TRequestStatus* status = &iStatus;
        User::RequestComplete( status, err );
        }
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::CloseStore()
    {
    TRACE_FUNC_ENTRY;
    DoCloseStore();
    REComSession::FinalClose();
    CompleteRequest( KErrNone );
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::SetSyncTimeStampL()
    {
    TRACE_FUNC_ENTRY;
    RMemReadStream readStream( iChunk.Base(), iChunk.Size() );
    CleanupClosePushL( readStream );
    TInt relationId = readStream.ReadInt32L();
    TInt providerId = readStream.ReadInt32L();
    CleanupStack::PopAndDestroy( &readStream );
    
    CSconSyncRelationship::SetTimeStampL( iFs, TUid::Uid(relationId), providerId);
    
    CompleteRequest( KErrNone );
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::GetSyncTimeStampL()
    {
    TRACE_FUNC_ENTRY;
    TInt providerId = iMessage.Int0();
    TInt relationId = iMessage.Int1();
        
    TDateTime time;
    CSconSyncRelationship::GetTimeStampL( iFs, TUid::Uid(relationId), providerId, time);
    
    // write timestamp
    TPckgC<TDateTime> timeBuf(time);
    iMessage.WriteL( 2, timeBuf, 0);
    
    CompleteRequest( KErrNone );
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::ExportStoreFormatL()
    {
    TRACE_FUNC_ENTRY;
    LeaveIfNoInstanceL();
    if ( !iDataProvider )
        {
        User::Leave( KErrNotReady );
        }
    CBufFlat* buffer = CBufFlat::NewL( KDefaultExpandSize );
    CleanupStack::PushL( buffer );
    RBufWriteStream stream( *buffer );
    CleanupClosePushL( stream );
    
    const CSmlDataStoreFormat& storeFormat = iDataProvider->StoreFormatL();
    TRAP_IGNORE( TLogDataStoreFormat::LogDataStoreFormatL( _L("iDataProvider->StoreFormatL()"), storeFormat ));
    
    storeFormat.ExternalizeL( stream );
    
    stream.CommitL();
    CleanupStack::PopAndDestroy( &stream );
    buffer->Compress();
    
    RMemWriteStream chunkStream( iChunk.Base(), iChunk.Size() );
    CleanupClosePushL( chunkStream );
    
    chunkStream.WriteInt32L( buffer->Size() );
    chunkStream.WriteL( buffer->Ptr(0), buffer->Size());
    chunkStream.CommitL();
    CleanupStack::PopAndDestroy( &chunkStream );
    
    CleanupStack::PopAndDestroy( buffer );
    
    CompleteRequest( KErrNone );
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::SetRemoteStoreFormatL()
    {
    TRACE_FUNC_ENTRY;
    LeaveIfNoInstanceL();
    
    RMemReadStream readStream( iChunk.Base(), iChunk.Size() );
    CleanupClosePushL( readStream );
    
    if ( iStoreFormat )
        {
        delete iStoreFormat;
        iStoreFormat = NULL;
        }
    iStoreFormat = CSmlDataStoreFormat::NewLC( iStringPool, readStream);
    CleanupStack::Pop( iStoreFormat );
    TRAP_IGNORE( TLogDataStoreFormat::LogDataStoreFormatL( _L("iDataProvider->SetRemoteStoreFormatL()"), *iStoreFormat ));
    iDataStore->SetRemoteStoreFormatL( *iStoreFormat );
    
    CleanupStack::PopAndDestroy( &readStream );
    
    CompleteRequest( KErrNone );
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::LeaveIfNoInstanceL()
    {
    if ( !iDataStore )
        {
        LOGGER_WRITE("DataStore instance was not ready, leaving KErrNotReady");
        User::Leave( KErrNotReady );
        }
    }

void CSconAsyncHandler::DoCloseStore()
    {
    TRACE_FUNC_ENTRY;
    delete iItems;
    iItems = NULL;
    delete iWriteData;
    iWriteData = NULL;
    if ( iDataProvider && iContext )
        {
        TInt providerId = iDataProvider->Identifier();
        TInt contextId = iContext->SyncTaskKey();
        TRAP_IGNORE( CSconSyncRelationship::SetTimeStampL( iFs, TUid::Uid(contextId), providerId) );
        }
    delete iDataStore;
    iDataStore = NULL;
    delete iDataProvider;
    iDataProvider = NULL;
    delete iContext;
    iContext = NULL;
    delete iStoreFormat;
    iStoreFormat = NULL;
    
    CleanOldStoresL();
    
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::CleanOldStoresL()
    {
    TRACE_FUNC_ENTRY;
    TFileName path;
    User::LeaveIfError( iFs.PrivatePath( path ) );
    CDir* dir;
    iFs.GetDir( path, KEntryAttNormal, ESortByDate, dir );
    CleanupStack::PushL( dir );
    TInt storesCount(0);
    LOGGER_WRITE_1("count: %d", dir->Count() );
    for ( TInt i=dir->Count()-1; i >= 0; i-- )
        {
        LOGGER_WRITE_1("dir[%d]", i);
        TEntry entry = (*dir)[i];
        LOGGER_WRITE_1("file: %S", &entry.iName);
        _LIT(KContextStoreName, "contextstore");
        _LIT(KTimeStoreName, "timestore");
        if ( entry.iName.Find(KContextStoreName) == 0 )
            {
            storesCount++;
            LOGGER_WRITE_1("storeNro: %d", storesCount);
#ifdef _DEBUG
            TTime time = entry.iModified;
            TDateTime dt = time.DateTime();
            _LIT(KFormat, "%d.%d %02d:%02d");
            TFileName mod;
            mod.Format(KFormat, dt.Day()+1, dt.Month()+1, dt.Hour()+1,dt.Minute() );
            LOGGER_WRITE_1("time: %S", &mod);
#endif
            if ( storesCount > KMaxStoresCount )
                {
                LOGGER_WRITE_1("delete contextstore: '%S'", &entry.iName );
                iFs.Delete( entry.iName );
                TFileName timeStoreFile;
                timeStoreFile = entry.iName.Right(15);
                timeStoreFile.Insert(0, KTimeStoreName);
                LOGGER_WRITE_1("delete timeStoreFile: %S", &timeStoreFile);
                iFs.Delete( timeStoreFile );
                }
            }
        
        }
    CleanupStack::PopAndDestroy( dir );
    TRACE_FUNC_EXIT;
    }

void CSconAsyncHandler::CompleteRequest( TInt aError )
    {
    TRACE_FUNC;
    iTimeOut->Cancel();
    LOGGER_WRITE_1("iMessage.Complete( %d )", aError);
    iMessage.Complete( aError );
    }