--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/msgsrvnstore/server/src/MSVMOVE.CPP Fri Jun 04 10:32:16 2010 +0100
@@ -0,0 +1,572 @@
+// 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 <e32base.h>
+
+#include "MSVIDS.H"
+
+#include "MSVMOVE.H"
+#include "MSVSERV.H"
+#include "MSVPANIC.H"
+#include "MSVUTILS.H"
+#include "msvindexadapter.h"
+
+const TInt KFileWildCard='*';
+
+//**********************************
+// CMsvMove
+//**********************************
+
+// static
+CMsvMove* CMsvMove::NewL(CMsvServer& aServer)
+//
+//
+//
+ {
+ CMsvMove* self = new(ELeave) CMsvMove(aServer);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+
+CMsvMove::CMsvMove(CMsvServer& aServer)
+: CActive(EPriorityStandard), iServer(aServer), iLockedIndex(-2)
+//
+//
+//
+ {}
+
+
+CMsvMove::~CMsvMove()
+//
+//
+//
+ {
+ Cancel();
+ Reset();
+ delete iFileMan;
+ delete iDescendents;
+ }
+
+
+void CMsvMove::Reset()
+//
+// NOTE called by d'tor
+//
+ {
+ if (iDescendents && iLockedIndex!=-2)
+ {
+ TInt count = iDescendents->Count();
+ while (count-- > iLockedIndex)
+ {
+ iServer.IndexAdapter().ReleaseEntryAndStore(iDescendents->At(count));
+ }
+
+ iDescendents->Reset();
+ }
+ iLockedIndex=-2;
+
+ delete iTargetPath;
+ iTargetPath=NULL;
+ }
+
+
+void CMsvMove::ConstructL()
+//
+//
+//
+ {
+ iFileMan = CFileMan::NewL(iServer.FileSession());
+ iDescendents = new(ELeave) CMsvEntrySelection;
+ CActiveScheduler::Add(this);
+ }
+
+
+void CMsvMove::RunL()
+//
+//
+//
+ {
+ TInt error = iStatus.Int();
+ if (error==KErrNone)
+ TRAP(error, DoRunL());
+ if (error)
+ {
+ CleanupFiles(iTargetService);
+ iDescendents->Reset();
+ User::RequestComplete(iObserverStatus, error);
+ }
+ }
+
+
+void CMsvMove::DoRunL()
+//
+//
+//
+ {
+ if (iState==EIndex)
+ {
+ // If the entry is not a visible folder and it's visible
+ // folder id is changed, the caller should update the
+ // visible folder id of all descendents.
+ if(!iCurrentEntry->VisibleFolderFlag())
+ {
+ User::LeaveIfError(iServer.IndexAdapter().MoveEntry(iSourceId, iTargetId, iDescendents));
+ }
+ else
+ {
+ User::LeaveIfError(iServer.IndexAdapter().MoveEntry(iSourceId, iTargetId));
+ }
+
+ CleanupFiles(iSourceService);
+ iServer.IndexAdapter().GetEntry(iSourceId, iCurrentEntry); // error ignored as entry exists
+ iDescendents->Reset();
+ User::RequestComplete(iObserverStatus, KErrNone);
+ return;
+ }
+
+ FindNextStep();
+ StartNextStep();
+ }
+
+
+
+void CMsvMove::CleanupFiles(TMsvId aService)
+ {
+ // delete the unwanted copies
+ if (iSourceService!=iTargetService)
+ {
+ TInt count=iDescendents->Count();
+ while (count--)
+ {
+ TFileName filename(iServer.Context().MessageFolder());
+ TMsvId id = iDescendents->At(count);
+ // BFs
+ MsvUtils::ConstructEntryName(aService, id, filename, MsvUtils::EFolder);
+ iFileMan->Delete(filename, CFileMan::ERecurse); // error ignored
+ // BF
+ iServer.FileSession().RmDir(filename); // error ignored
+ // Store
+ filename = iServer.Context().MessageFolder();
+ MsvUtils::ConstructEntryName(aService, id, filename, MsvUtils::EStore);
+ iFileMan->Delete(filename); // error ignored
+ }
+ }
+
+ // release the locks
+ TInt count = iDescendents->Count();
+ while (count--)
+ {
+ iServer.IndexAdapter().ReleaseEntryAndStore(iDescendents->At(count)); // error ignored
+ }
+
+ iLockedIndex=-2;
+ }
+
+
+void CMsvMove::DoCancel()
+//
+// CANNOT cancel the fileman operation - so we just have to wait for it to complete normally
+//
+ {
+ User::RequestComplete(iObserverStatus, KErrCancel);
+ }
+
+
+void CMsvMove::StartL(TMsvId aId, TMsvId aTarget, TRequestStatus& aObserverStatus)
+//
+//
+//
+ {
+ // Fail now if the index says it's not available
+ User::LeaveIfError(iServer.IndexAdapter().ErrorState());
+ Reset();
+
+ // check the source and target exists and which service they are under
+ User::LeaveIfError(iServer.IndexAdapter().OwningService(aId, iSourceService));
+ User::LeaveIfError(iServer.IndexAdapter().OwningService(aTarget, iTargetService));
+
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+ // Movement of entries across drives not supported.
+ if(GetDriveId(aId) != GetDriveId(aTarget))
+ {
+ User::Leave(KErrNotSupported);
+ }
+#endif // #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+
+ // get the index entry
+ iSourceId = aId;
+ iServer.IndexAdapter().GetEntry(iSourceId, iCurrentEntry); // error ignored as entry exists
+ iParentId = iCurrentEntry->Parent();
+ iTargetId = aTarget;
+ iDescendents->AppendL(iSourceId);
+ iNextDescendent=1;
+
+ __ASSERT_DEBUG(iCurrentEntry->Parent()!=iTargetId, PanicServer(EMsvMtmMovingToSameParent));
+
+ // check if the entry has children
+ if (iCurrentEntry->Owner())
+ {
+ // check for moving into a descendent
+ TBool descendent;
+ iServer.IndexAdapter().IsADescendent(aId, aTarget, descendent); // error ignored as both entry exists
+ if (descendent)
+ User::Leave(KErrArgument);
+
+ // get id of all the descendents
+ User::LeaveIfError(iServer.IndexAdapter().ExpandSelectionRecursively(*iDescendents));
+ }
+
+ // check all the entries can be moved
+ CheckEntriesL();
+
+ // determine whether the store/files actually need copying
+ iState = (iSourceService==iTargetService ? EIndex : EFolder);
+
+ // set up the file copying
+ if (iState!=EIndex)
+ {
+ TFileName targetPath(iServer.Context().MessageFolder());
+ MsvUtils::ConstructEntryName(iTargetService, iTargetService, targetPath, MsvUtils::EPath);
+
+ iTargetPath = targetPath.AllocL();
+ iServer.FileSession().MkDirAll(targetPath);
+ User::LeaveIfError(iServer.IndexAdapter().GetEntry(iDescendents->At(0), iCurrentEntry));
+
+ // make sure the first step is valid
+ TInt result = MsvUtils::HasDirectory(iServer.FileSession(), iServer.Context().MessageFolder(), iSourceService, iCurrentEntry->Id());
+ User::LeaveIfError(result);
+
+ if (!result)
+ FindNextStep();
+ }
+
+ StartNextStep();
+
+ iObserverStatus = &aObserverStatus;
+ *iObserverStatus = KRequestPending;
+ }
+
+
+void CMsvMove::FindNextStep()
+//
+//
+//
+ {
+ __ASSERT_DEBUG(iState!=EIndex, PanicServer(EMsvIncorrectStateInFindNextStep));
+
+ FOREVER
+ {
+ // we have copied the files, check if then entry has a store
+ if (iState==EFolder && MsvUtils::HasStore(iServer.FileSession(), iServer.Context().MessageFolder(), iSourceService, iCurrentEntry->Id()))
+ {
+ iState=EStore;
+ break;
+ }
+ TInt count = iDescendents->Count();
+
+ // are there any entries left to check
+ if (iNextDescendent==count)
+ {
+ iState=EIndex;
+ break;
+ }
+
+ // find the next descendent which still exists
+ FOREVER
+ {
+ TBool error = EFalse;
+ error = iServer.IndexAdapter().GetEntry(iDescendents->At(iNextDescendent++), iCurrentEntry);
+ if (error==KErrNone)
+ {
+ break;
+ }
+ }
+
+ iState = EFolder;
+ if (MsvUtils::HasDirectory(iServer.FileSession(), iServer.Context().MessageFolder(), iSourceService, iCurrentEntry->Id()))
+ break;
+
+ }
+ }
+
+
+void CMsvMove::StartNextStep()
+//
+//
+//
+ {
+ TInt error;
+ switch (iState)
+ {
+ case EFolder:
+ error = SetupFileCopy();
+ break;
+ case EStore:
+ error = SetupStoreCopy();
+ break;
+ default:
+ error=KErrNone;
+ }
+
+ if (iStatus!=KRequestPending)
+ {
+ // either the store/file copy has failed or the state is EIndex
+ iStatus=KRequestPending;
+ TRequestStatus* st = &iStatus;
+ User::RequestComplete(st, error);
+ }
+
+ SetActive();
+ }
+
+
+void CMsvMove::CheckEntriesL()
+//
+//
+//
+ {
+ iLockedIndex = iDescendents->Count();
+ while (iLockedIndex)
+ {
+ TMsvId id = iDescendents->At(iLockedIndex-1);
+
+ // lock the entry
+ User::LeaveIfError(iServer.IndexAdapter().LockEntryAndStore(id));
+ iLockedIndex--;
+
+ // check noone is reading the store (reading the store now doesn't
+ // keep the file open, therefore we can't rely on checking the file to stop
+ // deleting while reading
+ TBool reading=EFalse;
+ User::LeaveIfError(iServer.IndexAdapter().IsStoreReadingLocked(id,reading));
+ if(reading) User::Leave(KErrInUse);
+
+ // get the entry
+ TMsvEntry* entry;
+ User::LeaveIfError(iServer.IndexAdapter().GetEntry(id, entry));
+ // check the store
+ TFileName filename;
+ iServer.GetEntryName(id, filename, EFalse);
+ TBool open;
+ TInt error = iServer.FileSession().IsFileOpen(filename, open);
+ if (error != KErrNotFound && error!=KErrPathNotFound)
+ {
+ if (error != KErrNone)
+ User::Leave(error);
+ if (open)
+ User::Leave(KErrInUse);
+ }
+
+ // check any files
+ CDir* dir;
+ error = iServer.GetFileDirectoryListing(id, filename, dir);
+ if (error == KErrNone)
+ {
+ CleanupStack::PushL(dir);
+ User::LeaveIfError(iServer.FileSession().SetSessionPath(filename));
+ TInt fCount=dir->Count();
+ if (fCount--)
+ {
+ TBool open;
+ User::LeaveIfError(iServer.FileSession().IsFileOpen((*dir)[fCount].iName, open));
+ if (open)
+ User::Leave(KErrInUse);
+ }
+ CleanupStack::PopAndDestroy(); // dir
+ }
+ else if (error != KErrPathNotFound)
+ User::Leave(error);
+ }
+ }
+
+
+TInt CMsvMove::SetupStoreCopy()
+//
+//
+//
+ {
+ TFileName storeName;
+ iServer.GetEntryName(iCurrentEntry->Id(), storeName, EFalse);
+
+ TFileName targetPath(*iTargetPath);
+ TBuf<1> dir;
+ dir.NumFixedWidth(iCurrentEntry->Id()&0xf, EHex, 1);
+ targetPath.Append(dir);
+ _LIT(KDirSep,"\\");
+ targetPath.Append(KDirSep);
+ iServer.FileSession().MkDirAll(targetPath); // ignore errors, if it failed to create the directory the next line will fail
+ return iFileMan->Copy(storeName, targetPath, CFileMan::EOverWrite, iStatus);
+ }
+
+
+TInt CMsvMove::SetupFileCopy()
+//
+//
+//
+ {
+ // construct source directory
+ TFileName sourceFileDirectory;
+ iServer.GetEntryName(iCurrentEntry->Id(), sourceFileDirectory, ETrue);
+ sourceFileDirectory.Append(KFileWildCard);
+ // construct target directory
+ TFileName targetFileDirectory(*iTargetPath);
+ TBuf<KFileNameFixedWidth> dir;
+ dir.NumFixedWidth(iCurrentEntry->Id()&0xf, EHex, 1);
+ targetFileDirectory.Append(dir);
+ _LIT(KDirSep,"\\");
+ targetFileDirectory.Append(KDirSep);
+ dir.NumFixedWidth(iCurrentEntry->Id(), EHex, KFileNameFixedWidth);
+ targetFileDirectory.Append(dir);
+ targetFileDirectory.Append(KMsvBinaryFolderExt);
+ // setup the copy
+ return iFileMan->Copy(sourceFileDirectory, targetFileDirectory, CFileMan::EOverWrite|CFileMan::ERecurse, iStatus);
+ }
+
+
+
+void CMsvMove::StartL(TMsvId aId, TMsvId aTarget)
+//
+//
+//
+ {
+ // Fail now if the index says it's not available
+ User::LeaveIfError(iServer.IndexAdapter().ErrorState());
+
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+ // Movement of entries across drives not supported.
+ if(GetDriveId(aId) != GetDriveId(aTarget))
+ {
+ User::Leave(KErrNotSupported);
+ }
+#endif // #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+
+ // check the spource and target exists and which service they are under
+ User::LeaveIfError(iServer.IndexAdapter().OwningService(aId, iSourceService));
+ User::LeaveIfError(iServer.IndexAdapter().OwningService(aTarget, iTargetService));
+ __ASSERT_ALWAYS(iSourceService==iTargetService, PanicServer(EMsvMovingentryAccrossServices));
+
+ // get the index entry
+ iSourceId = aId;
+ iServer.IndexAdapter().GetEntry(iSourceId, iCurrentEntry); // error ignored as entry exists
+ iParentId = iCurrentEntry->Parent();
+ iTargetId = aTarget;
+
+ iDescendents->Reset();
+ iDescendents->AppendL(iSourceId);
+ iNextDescendent=1;
+
+ __ASSERT_DEBUG(iCurrentEntry->Parent()!=iTargetId, PanicServer(EMsvMtmMovingToSameParent));
+
+ // check if the entry has children
+ if (iCurrentEntry->Owner())
+ {
+ // check for moving into a descendent
+ TBool descendent;
+ iServer.IndexAdapter().IsADescendent(aId, aTarget, descendent); // error ignored as both entry exists
+ if (descendent)
+ User::Leave(KErrArgument);
+
+ // get id of all the descendents
+ User::LeaveIfError(iServer.IndexAdapter().ExpandSelectionRecursively(*iDescendents));
+ }
+
+ // check all the entries can be moved
+ CheckEntriesL();
+
+ // move the entry
+ if(!iCurrentEntry->VisibleFolderFlag())
+ {
+ User::LeaveIfError(iServer.IndexAdapter().MoveEntry(iSourceId, iTargetId, iDescendents));
+ }
+ else
+ {
+ User::LeaveIfError(iServer.IndexAdapter().MoveEntry(iSourceId, iTargetId));
+ }
+
+ // release the locks
+ TInt count = iDescendents->Count();
+ while (count--)
+ {
+ iServer.IndexAdapter().ReleaseEntryAndStore(iDescendents->At(count)); // error ignored
+ }
+
+ iLockedIndex=-2;
+ }
+
+//**********************************
+// CMsvMoveEntries
+//**********************************
+
+// static
+CMsvMoveEntries* CMsvMoveEntries::NewL(CMsvServer& aServer)
+//
+//
+//
+ {
+ CMsvMoveEntries* self = new(ELeave) CMsvMoveEntries();
+ CleanupStack::PushL(self);
+ self->ConstructL(aServer);
+ CleanupStack::Pop();
+ return self;
+ }
+
+
+CMsvMoveEntries::CMsvMoveEntries() :
+ CMsvCopyMoveEntriesBase()
+//
+//
+//
+ {}
+
+
+CMsvMoveEntries::~CMsvMoveEntries()
+//
+//
+//
+ {
+ delete iMove;
+ }
+
+
+void CMsvMoveEntries::ConstructL(CMsvServer& aServer)
+//
+//
+//
+ {
+ iMove = CMsvMove::NewL(aServer);
+ CMsvCopyMoveEntriesBase::ConstructL();
+ }
+
+
+void CMsvMoveEntries::DoCancel()
+//
+//
+//
+ {
+ iMove->Cancel();
+ User::RequestComplete(iObserverStatus, KErrCancel);
+ }
+
+
+void CMsvMoveEntries::DoStartL(TMsvId aSourceId, TMsvId aTargetId, TRequestStatus& aObserverStatus)
+//
+//
+//
+ {
+ iMove->StartL(aSourceId, aTargetId, aObserverStatus);
+ }