messagingfw/msgsrvnstore/server/src/MSVCOPY.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 #include "MSVCOPY.H"
       
    20 #include "MSVSERV.H"
       
    21 #include "MSVUTILS.H"
       
    22 
       
    23 #include "MSVPANIC.H"
       
    24 
       
    25 #include "CCopyOneFile.h"
       
    26 #include "CCopyFiles.h"
       
    27 #include "msvindexadapter.h"
       
    28 #include "msvcacheentry.h"
       
    29 
       
    30 //**********************************
       
    31 // CMsvCopyEntry
       
    32 //**********************************
       
    33 
       
    34 // static
       
    35 CMsvCopyEntry* CMsvCopyEntry::NewL(CMsvServer& aServer)
       
    36 	{
       
    37 	CMsvCopyEntry* self = new(ELeave) CMsvCopyEntry(aServer);
       
    38 	CleanupStack::PushL(self);
       
    39 	self->ConstructL();
       
    40 	CleanupStack::Pop();
       
    41 	return self;
       
    42 	}
       
    43 
       
    44 
       
    45 CMsvCopyEntry::CMsvCopyEntry(CMsvServer& aServer)
       
    46 : CActive(EPriorityStandard), iServer(aServer)
       
    47 	{}
       
    48 
       
    49 
       
    50 CMsvCopyEntry::~CMsvCopyEntry()
       
    51 	{
       
    52 	Cancel();
       
    53 	delete iCopyOneFile;
       
    54 	delete iCopyFiles;
       
    55 	delete iFromName;
       
    56 	delete iToName;
       
    57 	}
       
    58 
       
    59 void CMsvCopyEntry::ConstructL()
       
    60 	{
       
    61 	iCopyOneFile = CCopyOneFile::NewL(iServer.FileSession());
       
    62 	iCopyFiles = CCopyFiles::NewL(iServer.FileSession());
       
    63 	iFromName= new (ELeave) TFileName;
       
    64 	iToName= new (ELeave) TFileName;
       
    65 
       
    66 	CActiveScheduler::Add(this);
       
    67 	}
       
    68 
       
    69 
       
    70 void CMsvCopyEntry::DoCancel()
       
    71 	{
       
    72 	// only one will be active but that doesn't matter
       
    73 	iCopyOneFile->Cancel();
       
    74 	iCopyFiles->Cancel();
       
    75 	Completed(KErrCancel);
       
    76 	}
       
    77 
       
    78 
       
    79 void CMsvCopyEntry::NextState()
       
    80 	{
       
    81 	switch(iState)
       
    82 		{
       
    83 		case EEntryCreated:
       
    84 			iState=ECopyingStore;
       
    85 			break;
       
    86 		case ECopyingStore:
       
    87 			iState=ECopyingFolder;
       
    88 			break;
       
    89 		case ECopyingFolder:
       
    90 			iState=ECompleted;
       
    91 			break;
       
    92 		default:
       
    93 			__ASSERT_DEBUG(EFalse,PanicServer(EMsvCopyEntryFailureBadState));
       
    94 			iState=ECompleted;
       
    95 			break;
       
    96 		}
       
    97 	}
       
    98 
       
    99 
       
   100 void CMsvCopyEntry::RunL()
       
   101 	{
       
   102 	TInt error=iStatus.Int();
       
   103 	if(error==KErrNone)
       
   104 		{
       
   105 		NextState();
       
   106 
       
   107 		switch(iState)
       
   108 			{
       
   109 			case ECopyingStore:
       
   110 				CopyStoreFile();
       
   111 				break;
       
   112 			case ECopyingFolder:
       
   113 				CopyFolder();
       
   114 				break;
       
   115 			case ECompleted:
       
   116 				Completed(KErrNone);
       
   117 				break;
       
   118 			default:
       
   119 				__ASSERT_DEBUG(EFalse,PanicServer(EMsvCopyEntryFailureBadState));
       
   120 				Completed(KErrNone);
       
   121 				break;
       
   122 			}
       
   123 		}
       
   124 	else
       
   125 		Completed(error);
       
   126 	}
       
   127 
       
   128 
       
   129 void CMsvCopyEntry::CopyStoreFile()
       
   130 	{
       
   131 	iServer.GetEntryName(iOrigEntryId, *iFromName, EFalse);
       
   132 	TUint unused;
       
   133 	TInt err = iServer.FileSession().Att(*iFromName, unused);
       
   134 	if (err == KErrNotFound || err == KErrPathNotFound)
       
   135 		{
       
   136 		TRequestStatus* status = &iStatus;
       
   137 		TInt ret = KErrNone;
       
   138 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   139 		// We know that there's no entry in the file store. Let's see if this
       
   140 		// really is an error or if there's an entry in the DB store.
       
   141 		TRAPD(dbErr, iServer.MessageDBAdapter().CopyHeaderEntryL(iOrigEntry->iMtm, iOrigEntryId, iNewEntry->Id()));
       
   142 		if(KErrNotFound == dbErr) // The entry didn't have a header table entry.
       
   143 			dbErr = KErrNone;
       
   144 		ret = dbErr;
       
   145 #endif
       
   146 		User::RequestComplete(status, ret);
       
   147 		}
       
   148 	else
       
   149 		{
       
   150 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   151 		// There is an entry for iOrigEntry in the file store. Copy header
       
   152 		// table entries if any.
       
   153 		TRAPD(dbErr, iServer.MessageDBAdapter().CopyHeaderEntryL(iOrigEntry->iMtm, iOrigEntryId, iNewEntry->Id()));
       
   154 		if(KErrNotFound == dbErr) // The entry didn't have a header table entry.
       
   155 			dbErr = KErrNone;
       
   156 		
       
   157 		if(dbErr) // There was infact an error thrown from the DB - self-complete with that.
       
   158 			{
       
   159 			TRequestStatus *status=&iStatus;
       
   160 			User::RequestComplete(status,dbErr);
       
   161 			SetActive();
       
   162 			return;
       
   163 			}
       
   164 		// There was no error thrown from the DB. Go on to copy file store entries.
       
   165 #endif
       
   166 		iServer.GetEntryName(iNewEntry->Id(), *iToName, EFalse);
       
   167 		TInt error=iServer.FileSession().MkDirAll(*iToName);
       
   168 		if(error!=KErrNone && error != KErrAlreadyExists)
       
   169 			{
       
   170 			TRequestStatus *status=&iStatus;
       
   171 			User::RequestComplete(status,error);
       
   172 			}
       
   173 		else
       
   174 			{
       
   175 			iCopyOneFile->Copy(*iFromName,*iToName,iStatus);
       
   176 			}
       
   177 		}
       
   178 	SetActive();
       
   179 	}
       
   180 
       
   181 
       
   182 void CMsvCopyEntry::CopyFolder()
       
   183 	{
       
   184 	TMsvId service;
       
   185 	iServer.IndexAdapter().OwningService(iOrigEntryId, service); // error ignored because we know the original exists
       
   186 	TInt result = MsvUtils::HasDirectory(iServer.FileSession(), iServer.Context().MessageFolder(), service, iOrigEntryId);
       
   187 	if (result < 0)
       
   188 		Completed(result);
       
   189 	else if(result)
       
   190 		{
       
   191 		iServer.GetEntryName(iOrigEntryId, *iFromName, ETrue);
       
   192 		iServer.GetEntryName(iNewEntry->Id(), *iToName, ETrue);
       
   193 		iCopyFiles->CopyDir(*iFromName,*iToName,iStatus);
       
   194 		SetActive();
       
   195 		}
       
   196 	else
       
   197 		{
       
   198 		TRequestStatus *status=&iStatus;
       
   199 		User::RequestComplete(status,KErrNone);
       
   200 		SetActive();
       
   201 		}
       
   202 	}
       
   203 
       
   204 
       
   205 void CMsvCopyEntry::StartL(TMsvId aOrigEntryId, TMsvId aTargetId, TRequestStatus& aObserverStatus)
       
   206 //
       
   207 //
       
   208 //
       
   209 	{
       
   210 	// Fail now if the index says it's not available
       
   211 	User::LeaveIfError(iServer.IndexAdapter().ErrorState());
       
   212 	__ASSERT_DEBUG(!IsActive() && (iState==ENotYetStarted || iState==ECompleted), PanicServer(EMsvActiveCopyEntryReset));
       
   213 	iState = ENotYetStarted;
       
   214 	iOrigEntryId = aOrigEntryId;
       
   215 
       
   216 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   217 	// Copying of entries across drives not supported.
       
   218 	if(GetDriveId(aOrigEntryId) != GetDriveId(aTargetId))
       
   219 		{
       
   220 		User::Leave(KErrNotSupported);
       
   221 		}
       
   222 #endif		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   223 
       
   224 	// get the complete index entry to copy
       
   225 	TMsvEntry* entryPtr;
       
   226 	TSecureId ownerId;
       
   227 
       
   228 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   229 	User::LeaveIfError(iServer.IndexAdapter().GetEntry(iOrigEntryId, iOrigEntry, ownerId));
       
   230 	entryPtr = iOrigEntry;
       
   231 #else	
       
   232 	User::LeaveIfError(iServer.IndexAdapter().GetEntry(iOrigEntryId, entryPtr, ownerId));
       
   233 #endif
       
   234 
       
   235 	// create a new entry with the new parent, and add the new entry to the index
       
   236 	TMsvEntry newEntry = *entryPtr;
       
   237 	newEntry.SetParent(aTargetId);
       
   238 	User::LeaveIfError(iServer.IndexAdapter().AddEntry(newEntry, ownerId, ETrue));
       
   239 
       
   240 	// get the new entry from  the index
       
   241 	iServer.IndexAdapter().GetEntry(newEntry.Id(), iNewEntry); // will not fail, the entry exists
       
   242 	iState = EEntryCreated;
       
   243 
       
   244 	iObserverStatus = &aObserverStatus;
       
   245 	*iObserverStatus = KRequestPending;
       
   246 
       
   247 	TRequestStatus *status=&iStatus;
       
   248 	User::RequestComplete(status,KErrNone);
       
   249 	SetActive();
       
   250 	}
       
   251 
       
   252 
       
   253 void CMsvCopyEntry::Completed(TInt aError)
       
   254 	{
       
   255 	// remove the entry if we failed
       
   256 	if(aError!=KErrNone && iState!=ENotYetStarted)
       
   257 		iServer.RemoveEntry(iNewEntry->Id());
       
   258 
       
   259 	// inform the observer
       
   260 	User::RequestComplete(iObserverStatus, aError);
       
   261 	}
       
   262 
       
   263 
       
   264 //**********************************
       
   265 // CMsvCopy
       
   266 //**********************************
       
   267 
       
   268 // static
       
   269 CMsvCopy* CMsvCopy::NewL(CMsvServer& aServer)
       
   270 //
       
   271 //
       
   272 //
       
   273 	{
       
   274 	CMsvCopy* self = new(ELeave) CMsvCopy(aServer);
       
   275 	CleanupStack::PushL(self);
       
   276 	self->ConstructL();
       
   277 	CleanupStack::Pop();
       
   278 	return self;
       
   279 	}
       
   280 
       
   281 
       
   282 CMsvCopy::CMsvCopy(CMsvServer& aServer)
       
   283 : CActive(EPriorityStandard), iServer(aServer)
       
   284 //
       
   285 //
       
   286 //
       
   287 	{}
       
   288 
       
   289 
       
   290 CMsvCopy::~CMsvCopy()
       
   291 //
       
   292 //
       
   293 //
       
   294 	{
       
   295 	Cancel();
       
   296 	delete iRecursionList;
       
   297 	delete iFailedEntryParents;
       
   298 	delete iCopyEntry;
       
   299 	}
       
   300 
       
   301 
       
   302 void CMsvCopy::ConstructL()
       
   303 //
       
   304 //
       
   305 //
       
   306 	{
       
   307 	iRecursionList = new(ELeave) CMsvEntrySelection;
       
   308 	iFailedEntryParents = new(ELeave) CMsvEntrySelection;
       
   309 	iCopyEntry = CMsvCopyEntry::NewL(iServer);
       
   310 	CActiveScheduler::Add(this);
       
   311 	}
       
   312 
       
   313 
       
   314 void CMsvCopy::DoCancel()
       
   315 //
       
   316 //
       
   317 //
       
   318 	{
       
   319 	iCopyEntry->Cancel();
       
   320 	Completed();
       
   321 	}
       
   322 
       
   323 
       
   324 void CMsvCopy::StartL(TMsvId aOrigEntryId, TMsvId aTargetId, TRequestStatus& aObserverStatus, TBool aDescendentCopying)
       
   325 //
       
   326 //
       
   327 //
       
   328 	{
       
   329 	// Fail now if the index says it's not available
       
   330 	User::LeaveIfError(iServer.IndexAdapter().ErrorState());
       
   331 	iFailedEntryParents->Reset();
       
   332 	iDescendentCopying = aDescendentCopying;
       
   333 	iDescendentId = KMsvNullIndexEntryId;
       
   334 
       
   335 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   336 	// Copying of entries across drives not supported.
       
   337 	if(GetDriveId(aOrigEntryId) != GetDriveId(aTargetId))
       
   338 		{
       
   339 		User::Leave(KErrNotSupported);
       
   340 		}
       
   341 #endif		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   342 
       
   343 	// check the target exists
       
   344 	TBool entryExists = EFalse;
       
   345 	entryExists = iServer.IndexAdapter().EntryExists(aTargetId);
       
   346 	if (!entryExists)
       
   347 		User::Leave(KErrNotFound);
       
   348 	iOrigTargetId = aTargetId;
       
   349 
       
   350 	// get the index entry
       
   351 	iOrigSourceId = aOrigEntryId;
       
   352 	TMsvEntry* entryPtr;
       
   353 	User::LeaveIfError(iServer.IndexAdapter().GetEntry(iOrigSourceId, entryPtr));
       
   354 	iFailedEntryParents->AppendL(iOrigSourceId);
       
   355 
       
   356 	// check the entries can be copied
       
   357 	iServer.IndexAdapter().ExpandSelectionRecursively(*iFailedEntryParents);
       
   358 	User::LeaveIfError(iServer.CheckEntries(*iFailedEntryParents));
       
   359 	iFailedEntryParents->ResizeL(0); // the memory is not freed, so all the entries can be added again
       
   360 
       
   361 	// set the recursion variables
       
   362 	iError = KErrNone;
       
   363 	iTopLevelId = KMsvNullIndexEntryId;
       
   364 	iTempSourceId = iOrigSourceId;
       
   365 	iTempTargetId = iOrigTargetId;
       
   366 
       
   367 	// start the recursive copy
       
   368 	iCopyEntry->StartL(iOrigSourceId, iOrigTargetId, iStatus);
       
   369 	SetActive();
       
   370 
       
   371 	iObserverStatus = &aObserverStatus;
       
   372 	*iObserverStatus = KRequestPending;
       
   373 	}
       
   374 
       
   375 
       
   376 void CMsvCopy::RunL()
       
   377 //
       
   378 //
       
   379 //
       
   380 	{
       
   381 	// was this the top level
       
   382 	TBool topLevel = (iTopLevelId == KMsvNullIndexEntryId);
       
   383 	if (topLevel)
       
   384 		{
       
   385 		if (iStatus!=KErrNone)
       
   386 			{
       
   387 			User::RequestComplete(iObserverStatus, iStatus.Int());
       
   388 			return;
       
   389 			}
       
   390 		iTopLevelId = iCopyEntry->NewEntryId();
       
   391 		if (iDescendentCopying && iDescendentId==KMsvNullIndexEntryId)
       
   392 			iDescendentId = iTopLevelId;
       
   393 		}
       
   394 
       
   395 	// copy next entry
       
   396 	TRAPD(leave, DoRunL(topLevel));
       
   397 	if (leave)
       
   398 		{
       
   399 		// system error failure rather than couldn't copy a locked entry, so completed
       
   400 		if (iFailedEntryParents->Find(iTempTargetId)==KErrNotFound)
       
   401 			iFailedEntryParents->AppendL(iTempTargetId); // will not fail as space has been reserved
       
   402 		if (iError==KErrNone)
       
   403 			iError=leave;
       
   404 		Completed();
       
   405 		}
       
   406 	}
       
   407 
       
   408 
       
   409 void CMsvCopy::DoRunL(TBool aTopLevel)
       
   410 //
       
   411 //
       
   412 //
       
   413 	{
       
   414 	// record the success/failure of the copy
       
   415 	TMsvId newEntryId = KMsvNullIndexEntryId;
       
   416 	TBool  failed = (iStatus!=KErrNone);
       
   417 	if (failed)
       
   418 		{
       
   419 		if (iError==KErrNone)
       
   420 			iError = iStatus.Int();
       
   421 		iFailedEntryParents->AppendL(iTempTargetId); // a child of this entry was not copied
       
   422 		}
       
   423 	else
       
   424 		newEntryId = iCopyEntry->NewEntryId();
       
   425 
       
   426 	// get the  entry
       
   427 	
       
   428 	CMsvCacheEntry* sEntry;
       
   429 	User::LeaveIfError(iServer.IndexAdapter().GetInternalEntry(iTempSourceId, sEntry));
       
   430 
       
   431 	TMsvId firstSiblingId;
       
   432     if(!aTopLevel && iServer.IndexAdapter().GetNextSiblingL(iTempSourceId,sEntry->Entry().Parent(),firstSiblingId)) 
       
   433     	{
       
   434     	iRecursionList->AppendL(firstSiblingId);
       
   435         iRecursionList->AppendL(iTempTargetId);
       
   436     	}
       
   437   
       
   438   	TMsvId firstChildId;
       
   439   	if (!failed && iServer.IndexAdapter().GetFirstChildIdL(iTempSourceId,firstChildId)
       
   440   		&& (!iDescendentCopying || firstChildId<iDescendentId))
       
   441   		{
       
   442         iRecursionList->AppendL(firstChildId);
       
   443         iRecursionList->AppendL(newEntryId);
       
   444         }
       
   445      
       
   446 	if (iRecursionList->Count()==0)
       
   447 		{
       
   448 		// no more to copy
       
   449 		Completed();
       
   450 		return;
       
   451 		}
       
   452 	// get the next one to copy
       
   453 	iTempSourceId = iRecursionList->At(0);
       
   454 	iTempTargetId = iRecursionList->At(1);
       
   455 	iRecursionList->Delete(0,2);
       
   456 
       
   457 	// start the copy
       
   458 	iCopyEntry->StartL(iTempSourceId, iTempTargetId, iStatus);
       
   459 	SetActive();
       
   460 	}
       
   461 
       
   462 
       
   463 void CMsvCopy::Completed()
       
   464 //
       
   465 //
       
   466 //
       
   467 	{
       
   468 	if (iError)
       
   469 		{
       
   470 		if (iDeleteAllOnFailure)
       
   471 			iServer.RemoveEntry(iTopLevelId);
       
   472 		else
       
   473 			{
       
   474 			__ASSERT_DEBUG(iFailedEntryParents->Count(), PanicServer(EMsvCopyErrorButNoIds));
       
   475 			// cleanup the code
       
   476 			TInt index=iFailedEntryParents->Count();
       
   477 			while (index--)
       
   478 				{
       
   479 				TMsvId id = iFailedEntryParents->At(index);
       
   480 				TBool entryExists = EFalse;
       
   481 				entryExists = iServer.IndexAdapter().EntryExists(id);
       
   482 				if (!entryExists)
       
   483 					break;
       
   484 
       
   485 				// recurse back up tree to find the top entry or folder/service
       
   486 				TMsvEntry* entry;
       
   487 				TMsvEntry* parent;
       
   488 				iServer.IndexAdapter().GetEntry(id, entry); // errror ignored as entry exists
       
   489 				iServer.IndexAdapter().GetEntry(entry->Parent(), parent); // errror ignored as entry exists
       
   490 				while (entry->Id()!=iTopLevelId && (parent->iType!=KUidMsvFolderEntry || parent->iType!=KUidMsvServiceEntry))
       
   491 					{
       
   492 					entry = parent;
       
   493 					iServer.IndexAdapter().GetEntry(entry->Parent(), parent); // error ignored as entry exists
       
   494 					}
       
   495 				// remove the entries
       
   496 				iServer.RemoveEntry(entry->Id());
       
   497 				}
       
   498 			}
       
   499 		}
       
   500 
       
   501 	// inform the observer
       
   502 	User::RequestComplete(iObserverStatus, iError);
       
   503 	}
       
   504 
       
   505 //**********************************
       
   506 // CMsvCopyEntries
       
   507 //**********************************
       
   508 
       
   509 // static
       
   510 CMsvCopyEntries* CMsvCopyEntries::NewL(CMsvServer& aServer)
       
   511 //
       
   512 //
       
   513 //
       
   514 	{
       
   515 	CMsvCopyEntries* self = new(ELeave) CMsvCopyEntries();
       
   516 	CleanupStack::PushL(self);
       
   517 	self->ConstructL(aServer);
       
   518 	CleanupStack::Pop();
       
   519 	return self;
       
   520 	}
       
   521 
       
   522 
       
   523 CMsvCopyEntries::CMsvCopyEntries() :
       
   524 	CMsvCopyMoveEntriesBase()
       
   525 //
       
   526 //
       
   527 //
       
   528 	{}
       
   529 
       
   530 
       
   531 CMsvCopyEntries::~CMsvCopyEntries()
       
   532 //
       
   533 //
       
   534 //
       
   535 	{
       
   536 	delete iCopy;
       
   537 	delete iNewEntries;
       
   538 	}
       
   539 
       
   540 
       
   541 void CMsvCopyEntries::ConstructL(CMsvServer& aServer)
       
   542 //
       
   543 //
       
   544 //
       
   545 	{
       
   546 	iCopy = CMsvCopy::NewL(aServer);
       
   547 	iCopy->DeleteAllOnFailure();
       
   548 	iNewEntries = new(ELeave) CMsvEntrySelection;
       
   549 
       
   550 	CMsvCopyMoveEntriesBase::ConstructL();
       
   551 	}
       
   552 
       
   553 
       
   554 void CMsvCopyEntries::DoCancel()
       
   555 //
       
   556 //
       
   557 //
       
   558 	{
       
   559 	iCopy->Cancel();
       
   560 	User::RequestComplete(iObserverStatus, KErrCancel);
       
   561 	}
       
   562 
       
   563 
       
   564 void CMsvCopyEntries::DoStartL(TMsvId aSourceId, TMsvId aTargetId, TRequestStatus& aObserverStatus)
       
   565 //
       
   566 //
       
   567 //
       
   568 	{
       
   569 	// Reserve space for new entry id
       
   570 	iNewEntries->SetReserveL(CompletedIds().Count() + 1);
       
   571 
       
   572 	// Perform the copy
       
   573 	iCopy->StartL(aSourceId, aTargetId, aObserverStatus, ETrue);
       
   574 	}
       
   575 
       
   576 
       
   577 void CMsvCopyEntries::RunL()
       
   578 	{
       
   579 	// If no error occured remember the new entry's id
       
   580 	if (iStatus == KErrNone)
       
   581 		iNewEntries->AppendL(iCopy->NewEntryId());
       
   582 
       
   583 	CMsvCopyMoveEntriesBase::RunL();
       
   584 	}