messagingfw/msgsrvnstore/server/src/MSVMOVE.CPP
changeset 22 bde600d88860
parent 0 8e480a14352b
equal deleted inserted replaced
21:08008ce8a6df 22:bde600d88860
       
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <e32base.h>
       
    17 
       
    18 #include "MSVIDS.H"
       
    19 
       
    20 #include "MSVMOVE.H"
       
    21 #include "MSVSERV.H"
       
    22 #include "MSVPANIC.H"
       
    23 #include "MSVUTILS.H"
       
    24 #include "msvindexadapter.h"
       
    25 
       
    26 const TInt KFileWildCard='*';
       
    27 
       
    28 //**********************************
       
    29 // CMsvMove
       
    30 //**********************************
       
    31 
       
    32 // static
       
    33 CMsvMove* CMsvMove::NewL(CMsvServer& aServer)
       
    34 //
       
    35 //
       
    36 //
       
    37 	{
       
    38 	CMsvMove* self = new(ELeave) CMsvMove(aServer);
       
    39 	CleanupStack::PushL(self);
       
    40 	self->ConstructL();
       
    41 	CleanupStack::Pop();
       
    42 	return self;
       
    43 	}
       
    44 
       
    45 
       
    46 CMsvMove::CMsvMove(CMsvServer& aServer)
       
    47 : CActive(EPriorityStandard), iServer(aServer), iLockedIndex(-2)
       
    48 //
       
    49 //
       
    50 //
       
    51 	{}
       
    52 
       
    53 
       
    54 CMsvMove::~CMsvMove()
       
    55 //
       
    56 //
       
    57 //
       
    58 	{
       
    59 	Cancel();
       
    60 	Reset();
       
    61 	delete iFileMan;
       
    62 	delete iDescendents;
       
    63 	}
       
    64 
       
    65 
       
    66 void CMsvMove::Reset()
       
    67 //
       
    68 // NOTE called by d'tor
       
    69 //
       
    70 	{
       
    71 	if (iDescendents && iLockedIndex!=-2)
       
    72 		{
       
    73 		TInt count = iDescendents->Count();
       
    74 		while (count-- > iLockedIndex)
       
    75 			{
       
    76 			iServer.IndexAdapter().ReleaseEntryAndStore(iDescendents->At(count));
       
    77 			}
       
    78 
       
    79 		iDescendents->Reset();
       
    80 		}
       
    81 	iLockedIndex=-2;
       
    82 
       
    83 	delete iTargetPath;
       
    84 	iTargetPath=NULL;
       
    85 	}
       
    86 
       
    87 
       
    88 void CMsvMove::ConstructL()
       
    89 //
       
    90 //
       
    91 //
       
    92 	{
       
    93 	iFileMan = CFileMan::NewL(iServer.FileSession());
       
    94 	iDescendents = new(ELeave) CMsvEntrySelection;
       
    95 	CActiveScheduler::Add(this);
       
    96 	}
       
    97 
       
    98 
       
    99 void CMsvMove::RunL()
       
   100 //
       
   101 //
       
   102 //
       
   103 	{
       
   104 	TInt error = iStatus.Int();
       
   105 	if (error==KErrNone)
       
   106 		TRAP(error, DoRunL());
       
   107 	if (error)
       
   108 		{
       
   109 		CleanupFiles(iTargetService);
       
   110 		iDescendents->Reset();
       
   111 		User::RequestComplete(iObserverStatus, error);
       
   112 		}
       
   113 	}
       
   114 
       
   115 
       
   116 void CMsvMove::DoRunL()
       
   117 //
       
   118 //
       
   119 //
       
   120 	{
       
   121 	if (iState==EIndex)
       
   122 		{
       
   123         // If the entry is not a visible folder and it's visible
       
   124         // folder id is changed, the caller should update the 
       
   125 		// visible folder id of all descendents.
       
   126 		if(!iCurrentEntry->VisibleFolderFlag())
       
   127 			{
       
   128 	        User::LeaveIfError(iServer.IndexAdapter().MoveEntry(iSourceId, iTargetId, iDescendents));   
       
   129             }
       
   130 	    else
       
   131 	        {
       
   132 	        User::LeaveIfError(iServer.IndexAdapter().MoveEntry(iSourceId, iTargetId)); 
       
   133 	        }
       
   134 		
       
   135 		CleanupFiles(iSourceService);
       
   136 		iServer.IndexAdapter().GetEntry(iSourceId, iCurrentEntry); // error ignored as entry exists
       
   137 		iDescendents->Reset();
       
   138 		User::RequestComplete(iObserverStatus, KErrNone);
       
   139 		return;
       
   140 		}
       
   141 
       
   142 	FindNextStep();
       
   143 	StartNextStep();
       
   144 	}
       
   145 
       
   146 
       
   147 
       
   148 void CMsvMove::CleanupFiles(TMsvId aService)
       
   149 	{
       
   150 	// delete the unwanted copies
       
   151 	if (iSourceService!=iTargetService)
       
   152 		{
       
   153 		TInt count=iDescendents->Count();
       
   154 		while (count--)
       
   155 			{
       
   156 			TFileName filename(iServer.Context().MessageFolder());
       
   157 			TMsvId id = iDescendents->At(count);
       
   158 			// BFs
       
   159 			MsvUtils::ConstructEntryName(aService, id, filename, MsvUtils::EFolder);
       
   160 			iFileMan->Delete(filename, CFileMan::ERecurse); // error ignored
       
   161 			// BF
       
   162 			iServer.FileSession().RmDir(filename); // error ignored
       
   163 			// Store
       
   164 			filename = iServer.Context().MessageFolder();
       
   165 			MsvUtils::ConstructEntryName(aService, id, filename, MsvUtils::EStore);
       
   166 			iFileMan->Delete(filename); // error ignored
       
   167 			}
       
   168 		}
       
   169 
       
   170 	// release the locks
       
   171 	TInt count = iDescendents->Count();
       
   172 	while (count--)
       
   173 		{
       
   174 		iServer.IndexAdapter().ReleaseEntryAndStore(iDescendents->At(count)); // error ignored
       
   175 		}
       
   176 
       
   177 	iLockedIndex=-2;
       
   178 	}
       
   179 
       
   180 
       
   181 void CMsvMove::DoCancel()
       
   182 //
       
   183 // CANNOT cancel the fileman operation - so we just have to wait for it to complete normally
       
   184 //
       
   185 	{
       
   186 	User::RequestComplete(iObserverStatus, KErrCancel);
       
   187 	}
       
   188 
       
   189 
       
   190 void CMsvMove::StartL(TMsvId aId, TMsvId aTarget, TRequestStatus& aObserverStatus)
       
   191 //
       
   192 //
       
   193 //
       
   194 	{
       
   195 	// Fail now if the index says it's not available
       
   196 	User::LeaveIfError(iServer.IndexAdapter().ErrorState());
       
   197 	Reset();
       
   198 
       
   199 	// check the source and target exists and which service they are under
       
   200 	User::LeaveIfError(iServer.IndexAdapter().OwningService(aId, iSourceService));
       
   201 	User::LeaveIfError(iServer.IndexAdapter().OwningService(aTarget, iTargetService));
       
   202 
       
   203 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   204 	// Movement of entries across drives not supported.
       
   205 	if(GetDriveId(aId) != GetDriveId(aTarget))
       
   206 		{
       
   207 		User::Leave(KErrNotSupported);
       
   208 		}
       
   209 #endif		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   210 
       
   211 	// get the index entry
       
   212 	iSourceId = aId;
       
   213 	iServer.IndexAdapter().GetEntry(iSourceId, iCurrentEntry); // error ignored as entry exists
       
   214 	iParentId = iCurrentEntry->Parent();
       
   215 	iTargetId = aTarget;
       
   216 	iDescendents->AppendL(iSourceId);
       
   217 	iNextDescendent=1;
       
   218 
       
   219 	__ASSERT_DEBUG(iCurrentEntry->Parent()!=iTargetId, PanicServer(EMsvMtmMovingToSameParent));
       
   220 
       
   221 	// check if the entry has children
       
   222 	if (iCurrentEntry->Owner())
       
   223 		{
       
   224 		// check for moving into a descendent
       
   225 		TBool descendent;
       
   226 		iServer.IndexAdapter().IsADescendent(aId, aTarget, descendent); // error ignored as both entry exists
       
   227 		if (descendent)
       
   228 			User::Leave(KErrArgument);
       
   229 
       
   230 		// get id of all the descendents
       
   231 		User::LeaveIfError(iServer.IndexAdapter().ExpandSelectionRecursively(*iDescendents));
       
   232 		}
       
   233 
       
   234 	// check all the entries can be moved
       
   235 	CheckEntriesL();
       
   236 
       
   237 	// determine whether the store/files actually need copying
       
   238 	iState = (iSourceService==iTargetService ? EIndex : EFolder);
       
   239 
       
   240 	// set up the file copying
       
   241 	if (iState!=EIndex)
       
   242 		{
       
   243 		TFileName targetPath(iServer.Context().MessageFolder());
       
   244 		MsvUtils::ConstructEntryName(iTargetService, iTargetService, targetPath, MsvUtils::EPath);
       
   245 
       
   246 		iTargetPath = targetPath.AllocL();
       
   247 		iServer.FileSession().MkDirAll(targetPath);
       
   248 		User::LeaveIfError(iServer.IndexAdapter().GetEntry(iDescendents->At(0), iCurrentEntry));
       
   249 
       
   250 		// make sure the first step is valid
       
   251 		TInt result = MsvUtils::HasDirectory(iServer.FileSession(), iServer.Context().MessageFolder(), iSourceService, iCurrentEntry->Id());
       
   252 		User::LeaveIfError(result);
       
   253 
       
   254 		if (!result)
       
   255 			FindNextStep();
       
   256 		}
       
   257 
       
   258 	StartNextStep();
       
   259 
       
   260 	iObserverStatus = &aObserverStatus;
       
   261 	*iObserverStatus = KRequestPending;
       
   262 	}
       
   263 
       
   264 
       
   265 void CMsvMove::FindNextStep()
       
   266 //
       
   267 //
       
   268 //
       
   269 	{
       
   270 	__ASSERT_DEBUG(iState!=EIndex, PanicServer(EMsvIncorrectStateInFindNextStep));
       
   271 
       
   272 	FOREVER
       
   273 		{
       
   274 		// we have copied the files, check if then entry has a store
       
   275 		if (iState==EFolder && MsvUtils::HasStore(iServer.FileSession(), iServer.Context().MessageFolder(), iSourceService, iCurrentEntry->Id()))
       
   276 			{
       
   277 			iState=EStore;
       
   278 			break;
       
   279 			}
       
   280 		TInt count = iDescendents->Count();
       
   281 
       
   282 		// are there any entries left to check
       
   283 		if (iNextDescendent==count)
       
   284 			{
       
   285 			iState=EIndex;
       
   286 			break;
       
   287 			}
       
   288 
       
   289 		// find the next descendent which still exists
       
   290 		FOREVER
       
   291 			{
       
   292 			TBool error = EFalse;
       
   293 			error = iServer.IndexAdapter().GetEntry(iDescendents->At(iNextDescendent++), iCurrentEntry);
       
   294 			if (error==KErrNone)
       
   295 				{
       
   296 				break;
       
   297 				}
       
   298 			}
       
   299 
       
   300 			iState = EFolder;
       
   301 			if (MsvUtils::HasDirectory(iServer.FileSession(), iServer.Context().MessageFolder(), iSourceService, iCurrentEntry->Id()))
       
   302 				break;
       
   303 			
       
   304 		}
       
   305 	}
       
   306 
       
   307 
       
   308 void CMsvMove::StartNextStep()
       
   309 //
       
   310 //
       
   311 //
       
   312 	{
       
   313 	TInt error;
       
   314 	switch (iState)
       
   315 		{
       
   316 		case EFolder:
       
   317 			error = SetupFileCopy();
       
   318 			break;
       
   319 		case EStore:
       
   320 			error = SetupStoreCopy();
       
   321 			break;
       
   322 		default:
       
   323 			error=KErrNone;
       
   324 		}
       
   325 
       
   326 	if (iStatus!=KRequestPending)
       
   327 		{
       
   328 		// either the store/file copy has failed or the state is EIndex
       
   329 		iStatus=KRequestPending;
       
   330 		TRequestStatus* st = &iStatus;
       
   331 		User::RequestComplete(st, error);
       
   332 		}
       
   333 
       
   334 	SetActive();
       
   335 	}
       
   336 
       
   337 
       
   338 void CMsvMove::CheckEntriesL()
       
   339 //
       
   340 //
       
   341 //
       
   342 	{
       
   343 	iLockedIndex = iDescendents->Count();
       
   344 	while (iLockedIndex)
       
   345 		{
       
   346 		TMsvId id = iDescendents->At(iLockedIndex-1);
       
   347 
       
   348 		// lock the entry
       
   349 		User::LeaveIfError(iServer.IndexAdapter().LockEntryAndStore(id));
       
   350 		iLockedIndex--;
       
   351 
       
   352 		// check noone is reading the store (reading the store now doesn't
       
   353 		// keep the file open, therefore we can't rely on checking the file to stop
       
   354 		// deleting while reading
       
   355 		TBool reading=EFalse;
       
   356 		User::LeaveIfError(iServer.IndexAdapter().IsStoreReadingLocked(id,reading));
       
   357 		if(reading) User::Leave(KErrInUse);
       
   358 
       
   359 		// get the entry
       
   360 		TMsvEntry* entry;
       
   361 		User::LeaveIfError(iServer.IndexAdapter().GetEntry(id, entry));
       
   362 		// check the store
       
   363 		TFileName filename;
       
   364 		iServer.GetEntryName(id, filename, EFalse);
       
   365 		TBool open;
       
   366 		TInt error = iServer.FileSession().IsFileOpen(filename, open);
       
   367 		if (error != KErrNotFound && error!=KErrPathNotFound)
       
   368 			{
       
   369 			if (error != KErrNone)
       
   370 				User::Leave(error);
       
   371 			if (open)
       
   372 				User::Leave(KErrInUse);
       
   373 			}
       
   374 
       
   375 		// check any files
       
   376 		CDir* dir;
       
   377 		error = iServer.GetFileDirectoryListing(id, filename, dir);
       
   378 		if (error == KErrNone)
       
   379 			{
       
   380 			CleanupStack::PushL(dir);
       
   381 			User::LeaveIfError(iServer.FileSession().SetSessionPath(filename));
       
   382 			TInt fCount=dir->Count();
       
   383 			if (fCount--)
       
   384 				{
       
   385 				TBool open;
       
   386 				User::LeaveIfError(iServer.FileSession().IsFileOpen((*dir)[fCount].iName, open));
       
   387 				if (open)
       
   388 					User::Leave(KErrInUse);
       
   389 				}
       
   390 			CleanupStack::PopAndDestroy(); // dir
       
   391 			}
       
   392 		else if (error != KErrPathNotFound)
       
   393 			User::Leave(error);
       
   394 		}
       
   395 	}
       
   396 
       
   397 
       
   398 TInt CMsvMove::SetupStoreCopy()
       
   399 //
       
   400 //
       
   401 //
       
   402 	{
       
   403 	TFileName storeName;
       
   404 	iServer.GetEntryName(iCurrentEntry->Id(), storeName, EFalse);
       
   405 
       
   406 	TFileName targetPath(*iTargetPath);
       
   407 	TBuf<1> dir;
       
   408 	dir.NumFixedWidth(iCurrentEntry->Id()&0xf, EHex, 1);
       
   409 	targetPath.Append(dir);
       
   410 	_LIT(KDirSep,"\\");
       
   411 	targetPath.Append(KDirSep);
       
   412 	iServer.FileSession().MkDirAll(targetPath); // ignore errors, if it failed to create the directory the next line will fail
       
   413 	return iFileMan->Copy(storeName, targetPath, CFileMan::EOverWrite, iStatus);
       
   414 	}
       
   415 
       
   416 
       
   417 TInt CMsvMove::SetupFileCopy()
       
   418 //
       
   419 //
       
   420 //
       
   421 	{
       
   422 	// construct source directory
       
   423 	TFileName sourceFileDirectory;
       
   424 	iServer.GetEntryName(iCurrentEntry->Id(), sourceFileDirectory, ETrue);
       
   425 	sourceFileDirectory.Append(KFileWildCard);
       
   426 	// construct target directory
       
   427 	TFileName targetFileDirectory(*iTargetPath);
       
   428 	TBuf<KFileNameFixedWidth> dir;
       
   429 	dir.NumFixedWidth(iCurrentEntry->Id()&0xf, EHex, 1);
       
   430 	targetFileDirectory.Append(dir);
       
   431 	_LIT(KDirSep,"\\");
       
   432 	targetFileDirectory.Append(KDirSep);
       
   433 	dir.NumFixedWidth(iCurrentEntry->Id(), EHex, KFileNameFixedWidth);
       
   434 	targetFileDirectory.Append(dir);
       
   435 	targetFileDirectory.Append(KMsvBinaryFolderExt);
       
   436 	// setup the copy
       
   437 	return iFileMan->Copy(sourceFileDirectory, targetFileDirectory, CFileMan::EOverWrite|CFileMan::ERecurse, iStatus);
       
   438 	}
       
   439 
       
   440 
       
   441 
       
   442 void CMsvMove::StartL(TMsvId aId, TMsvId aTarget)
       
   443 //
       
   444 //
       
   445 //
       
   446 	{
       
   447 	// Fail now if the index says it's not available
       
   448 	User::LeaveIfError(iServer.IndexAdapter().ErrorState());
       
   449 
       
   450 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   451 	// Movement of entries across drives not supported.
       
   452 	if(GetDriveId(aId) != GetDriveId(aTarget))
       
   453 		{
       
   454 		User::Leave(KErrNotSupported);
       
   455 		}
       
   456 #endif		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   457 
       
   458 	// check the spource and target exists and which service they are under
       
   459 	User::LeaveIfError(iServer.IndexAdapter().OwningService(aId, iSourceService));
       
   460 	User::LeaveIfError(iServer.IndexAdapter().OwningService(aTarget, iTargetService));
       
   461 	__ASSERT_ALWAYS(iSourceService==iTargetService, PanicServer(EMsvMovingentryAccrossServices));
       
   462 
       
   463 	// get the index entry
       
   464 	iSourceId = aId;
       
   465 	iServer.IndexAdapter().GetEntry(iSourceId, iCurrentEntry); // error ignored as entry exists
       
   466 	iParentId = iCurrentEntry->Parent();
       
   467 	iTargetId = aTarget;
       
   468 
       
   469 	iDescendents->Reset();
       
   470 	iDescendents->AppendL(iSourceId);
       
   471 	iNextDescendent=1;
       
   472 
       
   473 	__ASSERT_DEBUG(iCurrentEntry->Parent()!=iTargetId, PanicServer(EMsvMtmMovingToSameParent));
       
   474 
       
   475 	// check if the entry has children
       
   476 	if (iCurrentEntry->Owner())
       
   477 		{
       
   478 		// check for moving into a descendent
       
   479 		TBool descendent;
       
   480 		iServer.IndexAdapter().IsADescendent(aId, aTarget, descendent); // error ignored as both entry exists
       
   481 		if (descendent)
       
   482 			User::Leave(KErrArgument);
       
   483 
       
   484 		// get id of all the descendents
       
   485 		User::LeaveIfError(iServer.IndexAdapter().ExpandSelectionRecursively(*iDescendents));
       
   486 		}
       
   487 
       
   488 	// check all the entries can be moved
       
   489 	CheckEntriesL();
       
   490 
       
   491 	// move the entry
       
   492 	if(!iCurrentEntry->VisibleFolderFlag())
       
   493 	    {
       
   494 	    User::LeaveIfError(iServer.IndexAdapter().MoveEntry(iSourceId, iTargetId, iDescendents));   
       
   495 	    }
       
   496 	else 
       
   497 	    {
       
   498 	    User::LeaveIfError(iServer.IndexAdapter().MoveEntry(iSourceId, iTargetId)); 
       
   499 	    }
       
   500 	
       
   501 	// release the locks
       
   502 	TInt count = iDescendents->Count();
       
   503 	while (count--)
       
   504 		{
       
   505 		iServer.IndexAdapter().ReleaseEntryAndStore(iDescendents->At(count)); // error ignored
       
   506 		}
       
   507 
       
   508 	iLockedIndex=-2;
       
   509 	}
       
   510 
       
   511 //**********************************
       
   512 // CMsvMoveEntries
       
   513 //**********************************
       
   514 
       
   515 // static
       
   516 CMsvMoveEntries* CMsvMoveEntries::NewL(CMsvServer& aServer)
       
   517 //
       
   518 //
       
   519 //
       
   520 	{
       
   521 	CMsvMoveEntries* self = new(ELeave) CMsvMoveEntries();
       
   522 	CleanupStack::PushL(self);
       
   523 	self->ConstructL(aServer);
       
   524 	CleanupStack::Pop();
       
   525 	return self;
       
   526 	}
       
   527 
       
   528 
       
   529 CMsvMoveEntries::CMsvMoveEntries() :
       
   530 	CMsvCopyMoveEntriesBase()
       
   531 //
       
   532 //
       
   533 //
       
   534 	{}
       
   535 
       
   536 
       
   537 CMsvMoveEntries::~CMsvMoveEntries()
       
   538 //
       
   539 //
       
   540 //
       
   541 	{
       
   542 	delete iMove;
       
   543 	}
       
   544 
       
   545 
       
   546 void CMsvMoveEntries::ConstructL(CMsvServer& aServer)
       
   547 //
       
   548 //
       
   549 //
       
   550 	{
       
   551 	iMove = CMsvMove::NewL(aServer);
       
   552 	CMsvCopyMoveEntriesBase::ConstructL();
       
   553 	}
       
   554 
       
   555 
       
   556 void CMsvMoveEntries::DoCancel()
       
   557 //
       
   558 //
       
   559 //
       
   560 	{
       
   561 	iMove->Cancel();
       
   562 	User::RequestComplete(iObserverStatus, KErrCancel);
       
   563 	}
       
   564 
       
   565 
       
   566 void CMsvMoveEntries::DoStartL(TMsvId aSourceId, TMsvId aTargetId, TRequestStatus& aObserverStatus)
       
   567 //
       
   568 //
       
   569 //
       
   570 	{
       
   571 	iMove->StartL(aSourceId, aTargetId, aObserverStatus);
       
   572 	}