diff -r 000000000000 -r 8e480a14352b messagingfw/msgsrvnstore/server/src/MSVLOCAL.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/messagingfw/msgsrvnstore/server/src/MSVLOCAL.CPP Mon Jan 18 20:36:02 2010 +0200 @@ -0,0 +1,796 @@ +// Copyright (c) 1998-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: +// + + +#include + +#include "MSVSTD.H" +#include "MSVSTORE.H" +#include "MSVIDS.H" + +#include "MSVENTRY.H" +#include "MSVSERV.H" +#include "MSVLOPS.H" +#include "MSVMOVE.H" +#include "MSVCOPY.H" +#include "MSVDELET.H" +#include "MSVPANIC.H" +#include +#include "msvindexadapter.h" + +//********************************** +// CMsvLocalOperation +//********************************** + +CMsvLocalOperation::CMsvLocalOperation(const RMessage2& aMessage, TMsvOp aId, CMsvServer& aMsvServer) +: CMsvServerOperation(aMessage, aId, KUidMsvLocalServiceMtm, KMsvLocalServiceIndexEntryId, -1), iMsvServer(aMsvServer) + { + __DECLARE_NAME(_S("CMsvLocalOperation")); + } + +const TDesC8& CMsvLocalOperation::Progress() + { + return iProgress; + } + +/** +Obtain the local progress information +@param aOutSysProg The TMsvSystemProgress structure to be populated +@return system wide error code +*/ +TInt CMsvLocalOperation::SystemProgress(TMsvSystemProgress& aSysProgress) + { + aSysProgress.iErrorCode = iProgress().iError; + aSysProgress.iId = iProgress().iId; + return KErrNone; // This method will not fail + } + +//********************************** +// CMsvLocalCopyOperation +//********************************** + + + +CMsvLocalCopyOperation::CMsvLocalCopyOperation(const RMessage2& aMessage, TMsvOp aId, CMsvEntrySelection* aSelection, TMsvId aTarget, CMsvServer& aMsvServer) +: CMsvLocalOperation(aMessage, aId, aMsvServer), iOrigEntries(aSelection), iTarget(aTarget) +// +// +// + { + __DECLARE_NAME(_S("CMsvLocalCopyOperation")); + // set up the progress + iProgress().iType = TMsvLocalOperationProgress::ELocalCopy; + iProgress().iTotalNumberOfEntries = iOrigEntries->Count(); + iProgress().iNumberRemaining = iProgress().iTotalNumberOfEntries; + CActiveScheduler::Add(this); + } + + +CMsvLocalCopyOperation::~CMsvLocalCopyOperation() +// +// +// + { + Cancel(); + delete iOrigEntries; + delete iNewEntries; + delete iCopy; + } + + +void CMsvLocalCopyOperation::DoCancel() +// +// +// + { + iCopy->Cancel(); + iProgress().iError = KErrCancel; + Completed(); + } + + +void CMsvLocalCopyOperation::RunL() +// +// +// + { + // sort out descendent copying + if (iDescendentCopying && iDescendentId == KMsvNullIndexEntryId) + iDescendentId = iCopy->NewEntryId(); + + // record details of the previous move + iProgress().iNumberRemaining--; + if (iStatus!=KErrNone) + { + iProgress().iNumberFailed++; + iProgress().iError=iStatus.Int(); + } + else + { + iNewEntries->AppendL(iCopy->NewEntryId()); // will not fail, as space has been reserved + iProgress().iNumberCompleted++; + } + + if (iIndex < iOrigEntries->Count()) + { + // start the next move + TInt error = CopyNextEntry(); + if (error==KErrNone) + return; // doing another move + __ASSERT_DEBUG(iProgress().iNumberRemaining==0, PanicServer(EMsvCopyingOperationInvariant)); + } + + // complete the operation + Completed(); + } + + +void CMsvLocalCopyOperation::StartL() +// +// +// + { + iNewEntries = new(ELeave) CMsvEntrySelection; + iCopy = CMsvCopy::NewL(iMsvServer); + + iIndex = 0; + iNewEntries->SetReserveL(iOrigEntries->Count()); + iDescendentId = KMsvNullIndexEntryId; + + // check for copying into a descedent + TInt count = iOrigEntries->Count(); + while (count--) + { + TMsvId id = iOrigEntries->At(count); + iDescendentCopying = (id==iTarget); + if (!iDescendentCopying) + { + iMsvServer.IndexAdapter().IsADescendent(id, iTarget, iDescendentCopying); // error ignored + } + + if (iDescendentCopying) + { + // has to be done first + iOrigEntries->Delete(count); + iOrigEntries->InsertL(0, id); + break; + } + } + + + TInt error = CopyNextEntry(); + if (error==KErrNone) + SetState(EMsvOperationRunning); + else + { + iProgress().iNumberFailed = iProgress().iTotalNumberOfEntries; + iProgress().iNumberRemaining = 0; + iProgress().iError=error; + Completed(); + } + } + + +TInt CMsvLocalCopyOperation::CopyNextEntry() +// +// +// + { + FOREVER + { + TRAPD(error, iCopy->StartL(iOrigEntries->At(iIndex++), iTarget, iStatus, iDescendentCopying)); + if (error) + { + iProgress().iNumberRemaining--; + iProgress().iNumberFailed++; + iProgress().iError=error; + if (iIndex==iOrigEntries->Count()) + return error; + } + else + { + SetActive(); + break; + } + } + return KErrNone; + } + + +void CMsvLocalCopyOperation::Completed() +// +// +// + { + SetState(EMsvOperationCompleted); + if (iNewEntries->Count()) + { + iProgress().iId = iNewEntries->At(0); + iMsvServer.NotifyChanged(EMsvEntriesCreated, *iNewEntries, iTarget); + } + iMessage.Complete(KErrNone); + } + + + + +//********************************** +// CMsvLocalMoveOperation +//********************************** + + +CMsvLocalMoveOperation::CMsvLocalMoveOperation(const RMessage2& aMessage, TMsvOp aId, CMsvEntrySelection* aSelection, TMsvId aTarget, CMsvServer& aMsvServer) +: CMsvLocalOperation(aMessage, aId, aMsvServer), iTarget(aTarget), iParent(KMsvNullIndexEntryId), iOrigEntries(aSelection) + { + __DECLARE_NAME(_S("CMsvLocalMoveOperation")); + // set up the progress + iProgress().iType = TMsvLocalOperationProgress::ELocalMove; + iProgress().iTotalNumberOfEntries = iOrigEntries->Count(); + iProgress().iNumberRemaining = iProgress().iTotalNumberOfEntries; + CActiveScheduler::Add(this); + } + + +CMsvLocalMoveOperation::~CMsvLocalMoveOperation() + { + Cancel(); + delete iOrigEntries; + delete iMove; + } + +void CMsvLocalMoveOperation::DoCancel() + { + iMove->Cancel(); + iOrigEntries->Delete(0,iNextEntry); + iProgress().iError = KErrCancel; + Completed(); + } + +void CMsvLocalMoveOperation::RunL() +// +// +// + { + // record details of the previous move + iProgress().iNumberRemaining--; + if (iStatus!=KErrNone) + { + iProgress().iNumberFailed++; + iProgress().iError=iStatus.Int(); + iOrigEntries->Delete(iNextEntry); + } + else + iProgress().iNumberCompleted++; + + TInt error=KErrNone; + if (iNextEntry) // will be zero when completed + { + // start the next move + error = MoveNextEntry(); + if (error==KErrNone) + return; // doing another move + __ASSERT_DEBUG(iProgress().iNumberRemaining==0, PanicServer(EMsvMovingOperationInvariant)); + } + + // complete the operation + Completed(); + } + +void CMsvLocalMoveOperation::Completed() +// +// +// + { + SetState(EMsvOperationCompleted); + if (iOrigEntries->Count()) + { + iProgress().iId = iOrigEntries->At(0); + iMsvServer.NotifyChanged(EMsvEntriesMoved, *iOrigEntries, iTarget, iParent); + } + iMessage.Complete(KErrNone); + } + +void CMsvLocalMoveOperation::StartFailed(TInt aError) +// +// +// + { + iProgress().iNumberFailed = iProgress().iTotalNumberOfEntries; + iProgress().iNumberRemaining = 0; + iProgress().iError=aError; + iOrigEntries->Reset(); + Completed(); + } + +void CMsvLocalMoveOperation::StartL() +// +// +// + { + // check if the target exists + TMsvEntry* entry; + TInt err = KErrNone; + err = iMsvServer.IndexAdapter().GetEntry(iTarget, entry); + if (err !=KErrNone) + { + StartFailed(KErrPathNotFound); + return; + } + + // find the current parent + TInt count=iOrigEntries->Count(); + while (count--) + { + TInt error = KErrNone; + error = iMsvServer.IndexAdapter().GetEntry(iOrigEntries->At(count), entry); + if (error ==KErrNone) + { + iParent=entry->Parent(); + break; + } + } + + // nothing to copy + if (count==KErrNotFound) + { + StartFailed(count); + return; + } + +#if defined(_DEBUG) + // check all the entries are local + TInt dCount=iOrigEntries->Count(); + while (dCount--) + { + TInt dSourceLocal; + TInt dError = KErrNone; + dError = iMsvServer.IndexAdapter().IsLocal(iOrigEntries->At(count), dSourceLocal); + __ASSERT_DEBUG(dError!=KErrNone || dSourceLocal, PanicServer(EMsvMovingLocalEntryIsRemote)); + } +#endif + + // start the copying + iMove = CMsvMove::NewL(iMsvServer); + iNextEntry=iOrigEntries->Count(); + TInt error = MoveNextEntry(); + if (error==KErrNone) + SetState(EMsvOperationRunning); + else + StartFailed(error); + } + + +TInt CMsvLocalMoveOperation::MoveNextEntry() +// +// +// + { + TInt error=KErrGeneral; + while (error!=KErrNone && iNextEntry) + { + iMove->Reset(); + error=KErrNone; + TRAP(error, iMove->StartL(iOrigEntries->At(--iNextEntry), iTarget, iStatus)); + if (error) + { + iProgress().iNumberRemaining--; + iProgress().iNumberFailed++; + iProgress().iError=error; + iOrigEntries->Delete(iNextEntry); + } + } + if (error==KErrNone) + SetActive(); + return error; + } + + + +//********************************** +// CMsvLocalDeleteOperation +//********************************** + + +CMsvLocalDeleteOperation::CMsvLocalDeleteOperation(const RMessage2& aMessage, TMsvOp aId, CMsvEntrySelection* aSelection, CMsvServer& aMsvServer) +: CMsvLocalOperation(aMessage, aId, aMsvServer), iSelection(aSelection) + { + __DECLARE_NAME(_S("CMsvLocalDeleteOperation")); + // set up the progress + iProgress().iType = TMsvLocalOperationProgress::ELocalDelete; + iProgress().iTotalNumberOfEntries = iSelection->Count(); + iProgress().iNumberRemaining = iProgress().iTotalNumberOfEntries; + CActiveScheduler::Add(this); + } + + +CMsvLocalDeleteOperation::~CMsvLocalDeleteOperation() + { + Cancel(); + delete iSelection; + delete iDeletedEntries; + delete iMovedEntries; + delete iDelete; + delete iWorkSelection1; + delete iWorkSelection2; + } + + +void CMsvLocalDeleteOperation::DoCancel() +// +// +// + { + iDelete->Cancel(); + iProgress().iError = KErrCancel; + Completed(); + // if the last entry was removed, update the notification selections + TRAP_IGNORE(PartialCompletionNotificationL()); + } + + +void CMsvLocalDeleteOperation::PartialCompletionNotificationL() +// +// +// + { + TMsvId id=iSelection->At(iIndex-1); + TBool entryExists = EFalse; + entryExists = iMsvServer.IndexAdapter().EntryExists(id); + if (!entryExists) + id = iParent; + + if (iWorkSelection1->Count()) + { + iDeletedEntries->Reset(); + iDeletedEntries->AppendL(iWorkSelection1->Back(0), iWorkSelection1->Count()); + iMsvServer.NotifyChanged(EMsvEntriesDeleted, *iDeletedEntries, id); + } + + if (iWorkSelection2->Count()) + { + iDeletedEntries->Reset(); + iMovedEntries->AppendL(iWorkSelection2->Back(0), iWorkSelection2->Count()); + iMsvServer.NotifyChanged(EMsvEntriesMoved, *iMovedEntries, KMsvDeletedEntryFolderEntryId, id); + } + } + + +void CMsvLocalDeleteOperation::RunL() +// +// Attempts the next delete +// + { + TRAPD(leave, DoRunL()); + if (leave) + { + // probably OOM so complete the operation + iProgress().iError = leave; + Completed(); + } + } + + +void CMsvLocalDeleteOperation::DoRunL() +// +// +// + { + // record the result of the last delete + iProgress().iNumberRemaining--; + if (iStatus.Int()==KErrNone) + { + iProgress().iNumberCompleted++; + iDeletedEntries->AppendL(iWorkSelection1->Back(0), iWorkSelection1->Count()); + iMovedEntries->AppendL(iWorkSelection2->Back(0), iWorkSelection2->Count()); + } + else + { + iProgress().iNumberFailed++; + if (iProgress().iError==KErrNone) + iProgress().iError = iStatus.Int(); + } + + // start thje next delete or complete the operation + if (iProgress().iNumberRemaining) + { + iWorkSelection1->Reset(); + iWorkSelection2->Reset(); + iDelete->StartL(iSelection->At(iIndex++), *iWorkSelection1, *iWorkSelection2, iStatus); + SetActive(); + } + else + { + __ASSERT_DEBUG(iIndex==iSelection->Count(), PanicServer(EMsvLocalDeletionMisCount)); + Completed(); + } + } + + +void CMsvLocalDeleteOperation::Completed() +// +// The operation has completed +// + { +/** +Added code to commit transaction for bulk deletion. +*/ + TRAP_IGNORE(iMsvServer.IndexAdapter().GetDbAdapter()->CommitTransactionL()); + + // notify server of any deletions or moves to the deleted folder + if (iDeletedEntries->Count()) + iMsvServer.NotifyChanged(EMsvEntriesDeleted, *iDeletedEntries, iParent); + if (iMovedEntries->Count()) + iMsvServer.NotifyChanged(EMsvEntriesMoved, *iMovedEntries, KMsvDeletedEntryFolderEntryId, iParent); + + // complete the request + SetState(EMsvOperationCompleted); + iMessage.Complete(KErrNone); + } + +void CMsvLocalDeleteOperation::StartL() + { + // reserve space so we don't manage to delete the entries but run + // out of memory when trying to report the fact. + iDeletedEntries = new(ELeave)CMsvEntrySelection; + iDeletedEntries->SetReserveL(iSelection->Count()); + iMovedEntries = new(ELeave)CMsvEntrySelection; + iMovedEntries->SetReserveL(iSelection->Count()); + iWorkSelection1 = new(ELeave)CMsvEntrySelection; + iWorkSelection2 = new(ELeave)CMsvEntrySelection; + iDelete = CMsvDelete::NewL(iMsvServer); + + // find the parent + TInt count=iSelection->Count(); + while (count--) + { + TMsvEntry* entry; + TInt error = KErrNone; + error = iMsvServer.IndexAdapter().GetEntry(iSelection->At(count),entry); + if (error) + { + iSelection->Delete(count); + iProgress().iNumberRemaining--; + iProgress().iNumberCompleted++; + } + else + iParent = entry->Parent(); + } + + if (iSelection->Count()) + { + // start deleting the first entry + iDelete->StartL(iSelection->At(iIndex++), *iWorkSelection1, *iWorkSelection2, iStatus); + SetActive(); + SetState(EMsvOperationRunning); + } + else + Completed(); + } + + + + + +//********************************** +// CMsvLocalChangeOperation +//********************************** + + +CMsvLocalChangeOperation::CMsvLocalChangeOperation(const RMessage2& aMessage, TMsvOp aId, const TMsvEntry& aEntry, CMsvServer& aMsvServer) +: CMsvLocalOperation(aMessage, aId, aMsvServer), iEntry(aEntry) + { + __DECLARE_NAME(_S("CMsvLocalChangeOperation")); + // set up the progress + iProgress().iType = TMsvLocalOperationProgress::ELocalChanged; + iProgress().iTotalNumberOfEntries = 1; + iProgress().iId = iEntry.Id(); + CActiveScheduler::Add(this); + } + +CMsvLocalChangeOperation::~CMsvLocalChangeOperation() +// +// +// + { + Cancel(); + delete iDelete; + delete iWorkSelection1; + delete iWorkSelection2; + } + +void CMsvLocalChangeOperation::DoCancel() +// +// +// + { + __ASSERT_DEBUG(iDelete!=NULL, PanicServer(EMsvChangeEntryBadState)); + iDelete->Cancel(); + iProgress().iError = KErrCancel; + Completed(); + } + +void CMsvLocalChangeOperation::RunL() +// +// +// + { + if (iStatus.Int()==KErrNone) + { + iProgress().iNumberCompleted++; + } + else + { + iProgress().iNumberFailed++; + iProgress().iError = iStatus.Int(); + } + Completed(); + } + +void CMsvLocalChangeOperation::StartL(TSecureId aOwnerId, TBool aForcedUpdate) +// +// +// + { + iId = iEntry.Id(); + iParent = iEntry.Parent(); + // check if this is actually a deletion + if (iEntry.Deleted() && iEntry.PcSyncCount()==0) + { + iDelete = CMsvDelete::NewL(iMsvServer); + iWorkSelection1 = new(ELeave)CMsvEntrySelection; + iWorkSelection2 = new(ELeave)CMsvEntrySelection; + iDelete->StartL(iEntry.Id(), *iWorkSelection1, *iWorkSelection2, iStatus, ETrue); + SetActive(); + return; + } + + // otherwise just changing it + TInt error = KErrNone; + error = iMsvServer.IndexAdapter().LockEntry(iId); + if (error==KErrNone) + { + error = iMsvServer.ChangeEntry(iEntry, aOwnerId, aForcedUpdate); + iMsvServer.IndexAdapter().ReleaseEntry(iId); // error ignored + } + + if (error==KErrNone) + iProgress().iNumberCompleted++; + else + { + iProgress().iNumberFailed++; + iProgress().iError = error; + } + Completed(); + } + + +void CMsvLocalChangeOperation::Completed() +// +// +// + { + if (iProgress().iError==KErrNone) + iMsvServer.NotifyChanged(iDelete==NULL ? EMsvEntriesChanged : EMsvEntriesDeleted, iId, iParent); + SetState(EMsvOperationCompleted); + iMessage.Complete(KErrNone); + } + + +//********************************** +// CMsvLocalCreateOperation +//********************************** + +CMsvLocalCreateOperation::CMsvLocalCreateOperation(const RMessage2& aMessage, TMsvOp aId, const TMsvEntry& aEntry, CMsvServer& aMsvServer) +: CMsvLocalOperation(aMessage, aId, aMsvServer), iEntry(aEntry) + { + __DECLARE_NAME(_S("CMsvLocalCreateOperation")); + // set up the progress + iProgress().iType = TMsvLocalOperationProgress::ELocalNew; + iProgress().iTotalNumberOfEntries = 1; + CActiveScheduler::Add(this); + } + + +CMsvLocalCreateOperation::~CMsvLocalCreateOperation() + {} + +void CMsvLocalCreateOperation::DoCancel() + {} + +void CMsvLocalCreateOperation::RunL() + {} + +void CMsvLocalCreateOperation::Start(TSecureId aOwnerId) + { + TMsvEntry entry = iEntry; + TInt error = iMsvServer.AddEntry(entry, aOwnerId, ETrue); + + if (error) + { + iProgress().iNumberFailed++; + iProgress().iError = error; + } + else + { + iProgress().iNumberCompleted++; + iProgress().iId = entry.Id(); + iMsvServer.NotifyChanged(EMsvEntriesCreated, entry.Id(), entry.Parent()); + } + + SetState(EMsvOperationCompleted); + iMessage.Complete(KErrNone); + } + +//********************************** +// CMsvChangeDriveOperation +//********************************** +CMsvChangeDriveOperation::CMsvChangeDriveOperation(const RMessage2& aMessage, TMsvOp aId, TInt aDrive, CMsvServer& aServer) +: CMsvServerOperation(aMessage, aId, KUidMsvLocalServiceMtm, KMsvLocalServiceIndexEntryId, -1), iDrive(aDrive), iServer(aServer) + { + CActiveScheduler::Add(this); + } + +CMsvChangeDriveOperation::~CMsvChangeDriveOperation() + { + Cancel(); + } + +const TDesC8& CMsvChangeDriveOperation::Progress() + { + if (iServer.NewContext()) + iProgress() = iServer.NewContext()->Progress(); + + return iProgress; + } + +void CMsvChangeDriveOperation::DoCancel() + { + if (iServer.NewContext()) + iServer.NewContext()->Cancel(); + + iProgress().iError = KErrCancel; + Completed(); + } + +void CMsvChangeDriveOperation::RunL() + { + Completed(); + } + +void CMsvChangeDriveOperation::Completed() + { + // Get progress + if (iServer.NewContext()) + { + iProgress() = iServer.NewContext()->Progress(); + + // If an error occurs we have to delete the new context + iServer.DeleteNewContext(); + } + else + iProgress() = iServer.Context().Progress(); + + SetState(EMsvOperationCompleted); + iMessage.Complete(KErrNone); + } + +TInt CMsvChangeDriveOperation::Start() + { + TInt error = iServer.ChangeDrive(iDrive, &iStatus); + if (!error) + SetActive(); + return error; + } +