messagingfw/msgsrvnstore/server/src/MSVDELET.CPP
changeset 0 8e480a14352b
child 22 d2c4c66342f3
equal deleted inserted replaced
-1:000000000000 0:8e480a14352b
       
     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 
       
    17 #include <e32base.h>
       
    18 
       
    19 #include "MSVIDS.H"
       
    20 
       
    21 #include "MSVDELET.H"
       
    22 #include "MSVSERV.H"
       
    23 #include "MSVPANIC.H"
       
    24 #include "MSVUTILS.H"
       
    25 #include "msvindexadapter.h"
       
    26 #include "msventryfreepool.h"
       
    27 
       
    28 // static
       
    29 CMsvDelete* CMsvDelete::NewL(CMsvServer& aServer)
       
    30 //
       
    31 //
       
    32 //
       
    33 	{
       
    34 	CMsvDelete* self = new(ELeave) CMsvDelete(aServer);
       
    35 	CleanupStack::PushL(self);
       
    36 	self->ConstructL();
       
    37 	CleanupStack::Pop();
       
    38 	return self;
       
    39 	}
       
    40 
       
    41 
       
    42 CMsvDelete::CMsvDelete(CMsvServer& aServer)
       
    43 : CActive(EPriorityStandard), iServer(aServer), iLockedIndex(-2)
       
    44 //
       
    45 //
       
    46 //
       
    47 	{
       
    48 	}
       
    49 
       
    50 
       
    51 void CMsvDelete::ConstructL()
       
    52 //
       
    53 //
       
    54 //
       
    55 	{
       
    56 	iFileMan = CFileMan::NewL(iServer.FileSession());
       
    57 	iDescendents = new(ELeave)CMsvEntrySelection;
       
    58 	CActiveScheduler::Add(this);
       
    59 	}
       
    60 
       
    61 
       
    62 CMsvDelete::~CMsvDelete()
       
    63 //
       
    64 //
       
    65 //
       
    66 	{
       
    67 	Cancel();
       
    68 	delete iDescendents;
       
    69 	delete iFileMan;
       
    70 	iDeleteArray.Close();
       
    71 	}
       
    72 
       
    73 void CMsvDelete::StartL(TMsvId aId, CMsvEntrySelection& aDeletedEntries, CMsvEntrySelection& aMovedEntries, TRequestStatus& aObserverStatus, TBool aPCSyncOverride)
       
    74 //
       
    75 //
       
    76 //
       
    77 	{
       
    78 	DoStartL(aId, aDeletedEntries, aMovedEntries, aPCSyncOverride);
       
    79 
       
    80 	iStatus = KRequestPending;
       
    81 	TRequestStatus* st=&iStatus;
       
    82 	User::RequestComplete(st, KErrNone);
       
    83 	SetActive();
       
    84 	//
       
    85 	iObserverStatus = &aObserverStatus;
       
    86 	*iObserverStatus = KRequestPending;
       
    87 	}
       
    88 
       
    89 void CMsvDelete::StartL(TMsvId aId, CMsvEntrySelection& aDeletedEntries, CMsvEntrySelection& aMovedEntries, TBool aPCSyncOverride)
       
    90 //
       
    91 //
       
    92 //
       
    93 	{	
       
    94 	DoStartL(aId, aDeletedEntries, aMovedEntries, aPCSyncOverride);
       
    95 
       
    96 	// the state machine from RunL
       
    97 	while (iState!=ECompleted)
       
    98 		{
       
    99 		switch (iState)
       
   100 			{
       
   101 			case ECheck:
       
   102 				TRAP(iError, CheckEntriesL());
       
   103 				if (iError)
       
   104 					iState=ECompleted;
       
   105 				break;
       
   106 			case EFiles:
       
   107 				TRAPD(leave, DeleteFilesL());
       
   108 				if (leave)
       
   109 					{
       
   110 					iError=leave;
       
   111 					iState=ECompleted;
       
   112 					}
       
   113 				break;
       
   114 			case EIndex:
       
   115 				DeleteAllIndexEntries();
       
   116 				iState=ECompleted;
       
   117 				break;
       
   118 			case EIndexIndividually:
       
   119 				DeleteIndividualIndexEntries();
       
   120 				iState=ECompleted;
       
   121 				break;
       
   122 			default:
       
   123 				__ASSERT_DEBUG(EFalse, PanicServer(EMsvDeleteBadState2));
       
   124 			}
       
   125 		}
       
   126 
       
   127 	// completion code
       
   128 	iDeletionIndex=0;
       
   129 
       
   130 	User::LeaveIfError(iError);
       
   131 	}
       
   132 
       
   133 void CMsvDelete::DoStartL(TMsvId aId, CMsvEntrySelection& aDeletedEntries, CMsvEntrySelection& aMovedEntries, TBool aPCSyncOverride)
       
   134 //
       
   135 //
       
   136 //
       
   137 	{
       
   138 	// Fail now if the index says it's not available
       
   139 	User::LeaveIfError(iServer.IndexAdapter().ErrorState());
       
   140 	iId = aId;
       
   141 	iPCSyncOverride = aPCSyncOverride;
       
   142 
       
   143 	// Let's not support deletion of entries from non-current drive.
       
   144 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   145 	if(GetDriveId(iId) != KCurrentDriveId)
       
   146 		{
       
   147 		User::Leave(KErrNotSupported);
       
   148 		}
       
   149 #endif
       
   150 
       
   151 	// get the expanded selection
       
   152 	iDescendents->Reset();
       
   153 	iDescendents->AppendL(iId);
       
   154 	User::LeaveIfError(iServer.IndexAdapter().ExpandSelectionRecursively(*iDescendents));
       
   155 	// make sure all deleted entries can be stored
       
   156 	iDeletedEntries = &aDeletedEntries;
       
   157 	iDeletedEntries->SetReserveL(iDescendents->Count());
       
   158 	iMovedEntries = &aMovedEntries;
       
   159 	iMovedEntries->SetReserveL(iDescendents->Count());
       
   160 
       
   161 	// check if the entry is a service then set up PC override
       
   162 	TMsvEntry* entry;
       
   163 	User::LeaveIfError(iServer.IndexAdapter().GetEntry(aId, entry));
       
   164 	if (entry->iType==KUidMsvServiceEntry)
       
   165 		iPCSyncOverride=ETrue;
       
   166 
       
   167 	iState = ECheck;
       
   168 	}
       
   169 
       
   170 void CMsvDelete::DoCancel()
       
   171 //
       
   172 //
       
   173 //
       
   174 	{
       
   175 	// need to remove the index entries for any already deleted
       
   176 	if (iState==EFiles || iState==EIndex || iState==EIndexIndividually)
       
   177 		iPCSynced ? DeleteIndividualIndexEntries() : DeleteAllIndexEntries();
       
   178 	Complete(KErrCancel);
       
   179 	}
       
   180 
       
   181 
       
   182 
       
   183 void CMsvDelete::RunL()
       
   184 //
       
   185 //
       
   186 //
       
   187 	{
       
   188 	TInt error = iStatus.Int();
       
   189 	if (error==KErrNone)
       
   190 		TRAP(error, DoRunL());
       
   191 	if (error)
       
   192 		Complete(error);
       
   193 	}
       
   194 
       
   195 
       
   196 void CMsvDelete::DoRunL()
       
   197 //
       
   198 //
       
   199 //
       
   200 	{
       
   201 	switch (iState)
       
   202 		{
       
   203 		case EFiles:
       
   204 			DeleteFilesL();
       
   205 			break;
       
   206 		case ECheck:
       
   207 			CheckEntriesL();
       
   208 			break;
       
   209 		case EIndex:
       
   210 			DeleteAllIndexEntries();
       
   211 			Complete(iError);
       
   212 			return;
       
   213 		case EIndexIndividually:
       
   214 			DeleteIndividualIndexEntries();
       
   215 			Complete(iError);
       
   216 			return;
       
   217 		default:
       
   218 			__ASSERT_DEBUG(EFalse, PanicServer(EMsvDeleteBadState));
       
   219 		}
       
   220 	iStatus = KRequestPending;
       
   221 	TRequestStatus* st=&iStatus;
       
   222 	User::RequestComplete(st, KErrNone);
       
   223 	SetActive();
       
   224 	}
       
   225 
       
   226 
       
   227 void CMsvDelete::CheckEntriesL()
       
   228 //
       
   229 //
       
   230 //
       
   231 	{
       
   232 	iLockedIndex = iDescendents->Count();
       
   233 	while (iLockedIndex)
       
   234 		{
       
   235 		TMsvId id = iDescendents->At(iLockedIndex-1);
       
   236 
       
   237 		// lock the entry
       
   238 		User::LeaveIfError(iServer.IndexAdapter().IsEntryOrStoreLocked(id));
       
   239 		iLockedIndex--;
       
   240 
       
   241 		// check noone is reading the store (reading the store now doesn't
       
   242 		// keep the file open, therefore we can't rely on checking the file to stop
       
   243 		// deleting while reading
       
   244 		TBool reading=EFalse;
       
   245 		User::LeaveIfError(iServer.IndexAdapter().IsStoreReadingLocked(id,reading));
       
   246 		if(reading) User::Leave(KErrInUse);
       
   247 
       
   248 
       
   249 		// get the entry
       
   250 		TMsvEntry entry;
       
   251 		User::LeaveIfError(iServer.IndexAdapter().GetEntryNoCache(id, &entry));
       
   252 		TMsvDelete deleteEntry(entry.Id(), entry.Owner(), entry.PcSyncCount(), entry.iType, entry.Complete());
       
   253 		iDeleteArray.AppendL(deleteEntry);
       
   254 
       
   255 		// check if any entries have been synced and not been overridden
       
   256 		if (!iPCSyncOverride && entry.PcSyncCount())
       
   257 			iPCSynced=ETrue;
       
   258 
       
   259 		// cannot delete standard folders
       
   260 		if (entry.StandardFolder())
       
   261 			User::Leave(KErrAccessDenied);
       
   262 
       
   263 		// check the store
       
   264 		TFileName filename;
       
   265 		iServer.GetEntryName(id, filename, EFalse);
       
   266 		TBool open;
       
   267 		TInt error = iServer.FileSession().IsFileOpen(filename, open);
       
   268 		if (error!=KErrNone && error!=KErrNotFound && error!=KErrPathNotFound)
       
   269 			User::Leave(error);
       
   270 		if (error==KErrNone && open)
       
   271 			User::Leave(KErrInUse);
       
   272 
       
   273 		// check any files
       
   274 		CDir* dir;
       
   275 		error = iServer.GetFileDirectoryListing(id, filename, dir);
       
   276 		if (error==KErrNone)
       
   277 			{
       
   278 			CleanupStack::PushL(dir);
       
   279 			User::LeaveIfError(iServer.FileSession().SetSessionPath(filename));
       
   280 			TInt fCount=dir->Count();
       
   281 			if (fCount--)
       
   282 				{
       
   283 				TBool open;
       
   284 				TInt error = iServer.FileSession().IsFileOpen((*dir)[fCount].iName, open);
       
   285 				if (error!=KErrNone && error!=KErrNotFound && error!=KErrPathNotFound)
       
   286 					User::Leave(error);
       
   287 				if (error==KErrNone && open)
       
   288 					User::Leave(KErrInUse);
       
   289 				if ((*dir)[fCount].IsReadOnly())
       
   290 					User::LeaveIfError(iServer.FileSession().SetAtt((*dir)[fCount].iName, 0, KEntryAttReadOnly));
       
   291 				}
       
   292 			CleanupStack::PopAndDestroy(); // dir
       
   293 			}
       
   294 		else if (error!=KErrPathNotFound)
       
   295 			User::Leave(error);
       
   296 		}
       
   297 	iState = EFiles;
       
   298 	}
       
   299 
       
   300 
       
   301 void CMsvDelete::DeleteFilesL()
       
   302 //
       
   303 //
       
   304 //
       
   305 	{
       
   306 	TFileName filename;
       
   307 	TMsvId id = iDescendents->At(iDeletionIndex++);
       
   308 
       
   309 	// delete the binary files
       
   310 	CDir* dir=NULL;
       
   311 	TBool partiallyDeleted=EFalse;
       
   312 	TInt error = iServer.GetFileDirectoryListing(id, filename, dir);
       
   313 	if (error==KErrNone)
       
   314 		{
       
   315 		User::LeaveIfError(iServer.FileSession().SetSessionPath(filename));
       
   316 		// remove any files
       
   317 		TInt fCount=dir->Count();
       
   318 		while (fCount--)
       
   319 			{
       
   320 			error = iServer.FileSession().Delete((*dir)[fCount].iName);
       
   321 			if (error==KErrNone)
       
   322 				partiallyDeleted=ETrue;
       
   323 			else if (error!=KErrNotFound && error!=KErrPathNotFound)
       
   324 				goto failed;
       
   325 			}
       
   326 
       
   327 		// remove the directory
       
   328 		error = iServer.FileSession().RmDir(filename);
       
   329 		if (error==KErrNone)
       
   330 			partiallyDeleted=ETrue;
       
   331 		else if (error!=KErrNotFound && error!=KErrPathNotFound)
       
   332 			goto failed;
       
   333 		}
       
   334 	else if (error!=KErrPathNotFound && error!=KErrNotFound)
       
   335 		goto failed;
       
   336 
       
   337 	// delete the store
       
   338 	iServer.GetEntryName(id, filename, EFalse); // error ignore as entry exists
       
   339 	error = iServer.FileSession().Delete(filename);
       
   340 	// Try to delete the (single digit) parent folder if it is empty. E.g.: "...\00001001_S\9\"
       
   341 	iServer.FileSession().RmDir(filename); // ignore error
       
   342 	if (error==KErrNone)
       
   343 		partiallyDeleted=ETrue;
       
   344 	else if (error!=KErrNotFound && error!=KErrPathNotFound)
       
   345 		goto failed;
       
   346 
       
   347 
       
   348 	filename.Append(KMsvUtilsNewExtension);  // try and make sure that a temporary store file
       
   349 	iServer.FileSession().Delete(filename);  // hasn't been left behind by CMsvCachedStore
       
   350 	                                         // but ignore the error as we can't do anything about it
       
   351 
       
   352 	// for the last entry, check if it a service and move to next state
       
   353 	if (iDeletionIndex==iDescendents->Count())
       
   354 		{
       
   355 		// get the entry and check whether it is a service
       
   356 		TBool serviceType =EFalse;
       
   357 		TInt deleteArrayCount = iDeleteArray.Count();
       
   358 		for(TInt i =0; i < deleteArrayCount; ++i)
       
   359 			{
       
   360 			if(iDeleteArray[i].iEntryId == id)
       
   361 				{
       
   362 				if(iDeleteArray[i].iType == KUidMsvServiceEntry)
       
   363 					{
       
   364 					serviceType = ETrue;
       
   365 					}
       
   366 				break;	
       
   367 				}
       
   368 			}	
       
   369 		if(serviceType)
       
   370 			{
       
   371 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   372 			iServer.Context().MessageFolder(GetDriveId(id), filename);
       
   373 			MsvUtils::ConstructEntryName(UnmaskTMsvId(id), id, filename, MsvUtils::EPath);
       
   374 #else
       
   375 			filename = iServer.Context().MessageFolder();
       
   376 			MsvUtils::ConstructEntryName(id, id, filename, MsvUtils::EPath);
       
   377 #endif
       
   378 			error = iFileMan->RmDir(filename);
       
   379 			if (error && error!=KErrPathNotFound && error!=KErrNotFound)
       
   380 				goto failed;
       
   381 			}
       
   382 		// we have completed all the deletion, move onto next state
       
   383 		iState = iPCSynced ? EIndexIndividually : EIndex;
       
   384 		}
       
   385 
       
   386 	// deletion was successful
       
   387 	iDeletedEntries->AppendL(id); // will not leave, space has been reserved
       
   388 	iMovedEntries->AppendL(id);   // will not leave, space has been reserved
       
   389 	delete dir;
       
   390 	return;
       
   391 
       
   392 failed:
       
   393 	if (partiallyDeleted)
       
   394 		{
       
   395 		TMsvEntry* entry=NULL;
       
   396 		TBool complete =EFalse;
       
   397 		for(TInt i =0; i< iDeleteArray.Count(); ++i)
       
   398 			{
       
   399 			if(iDeleteArray[i].iEntryId == id)
       
   400 				{
       
   401 				if(iDeleteArray[i].iIsComplete)
       
   402 					{
       
   403 					iServer.IndexAdapter().GetEntry(id, entry);
       
   404 					if(entry)
       
   405 						{
       
   406 						complete = ETrue;
       
   407 						}
       
   408 					}
       
   409 				break;	
       
   410 				}
       
   411 			}
       
   412 			
       
   413 		if(complete)
       
   414 			{
       
   415 			// mark as imcomplete
       
   416 			TMsvEntry icmpEntry=*entry;
       
   417 			icmpEntry.SetComplete(EFalse);
       
   418 			iServer.IndexAdapter().LockEntry(id);
       
   419 			iServer.IndexAdapter().ChangeEntry(icmpEntry, KMsvServerId, EFalse); // ignore error
       
   420 			iServer.IndexAdapter().ReleaseEntry(id);
       
   421 			}
       
   422 		}
       
   423 
       
   424 	// we have failed, move onto next state
       
   425 	iState = iPCSynced ? EIndexIndividually : EIndex;
       
   426 	iError=error;
       
   427 	delete dir;
       
   428 	}
       
   429 
       
   430 
       
   431 
       
   432 void CMsvDelete::DeleteAllIndexEntries()
       
   433 //
       
   434 //
       
   435 //
       
   436 	{
       
   437 	iMovedEntries->Reset();
       
   438 
       
   439 	if (iDeletedEntries->Count()==0)
       
   440 		return;
       
   441 
       
   442 	// delete the entries
       
   443 	TInt error = KErrNone;
       
   444 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   445 	TMsvEntry* entry = NULL;
       
   446 	TInt deleteIndex = 0;
       
   447 	while(deleteIndex < iDeletedEntries->Count())
       
   448 		{
       
   449 		iServer.IndexAdapter().GetEntry(iDeletedEntries->At(deleteIndex), entry);
       
   450 		if(entry==NULL)			
       
   451 			{
       
   452 			iDeletedEntries->Delete(deleteIndex);
       
   453 			continue;
       
   454 			}
       
   455 		
       
   456 		// If there's a DB store, delete any header entries associated with the entry.
       
   457 		TRAP(error, iServer.MessageDBAdapter().DeleteHeaderEntryL(entry->iMtm, entry->iId));
       
   458 		if(KErrNotFound == error) // Ignore entry not found case
       
   459 			error = KErrNone;
       
   460 	
       
   461 		if(error)
       
   462 			iDeletedEntries->Delete(deleteIndex);
       
   463 		else
       
   464 			++deleteIndex;
       
   465 		}
       
   466 #endif
       
   467 	if(!error) // Looks awkward inside the macro above..
       
   468 		error = iServer.IndexAdapter().DeleteSelectionUsingTransaction(*iDeletedEntries);
       
   469 
       
   470 	if (error && iError==KErrNone)
       
   471 		iError=error;
       
   472 	}
       
   473 
       
   474 
       
   475 void CMsvDelete::DeleteIndividualIndexEntries()
       
   476 //
       
   477 //
       
   478 //
       
   479 	{
       
   480 	if (iDeletedEntries->Count()==0)
       
   481 		return;
       
   482 
       
   483 	TInt moveIndex=0;
       
   484 	TInt deleteIndex=0;
       
   485 	iServer.IndexAdapter().BeginTransaction();
       
   486 	
       
   487 	while(deleteIndex < iDeletedEntries->Count())
       
   488 		{
       
   489 		// get the entry
       
   490 		TMsvEntry* entry=NULL;
       
   491  	    iServer.IndexAdapter().GetEntry(iDeletedEntries->At(deleteIndex), entry);
       
   492 		if(entry==NULL)			
       
   493 			{
       
   494 			iDeletedEntries->Delete(deleteIndex);
       
   495 			iMovedEntries->Delete(moveIndex);
       
   496 			continue;
       
   497 			}
       
   498 
       
   499 		TInt error = KErrNone;
       
   500 		if(!entry->Owner())
       
   501 			{
       
   502 			// either delete the entry, or move it to the deleted folder
       
   503 			if(entry->PcSyncCount()==0)
       
   504 				{ // Deleting the entry..
       
   505 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   506 				// If there's a DB store, delete any header entries associated with the entry.
       
   507 				TRAP(error, iServer.MessageDBAdapter().DeleteHeaderEntryL(entry->iMtm, entry->iId));
       
   508 				if(KErrNotFound == error) // Ignore entry not found case
       
   509 					error = KErrNone;
       
   510 #endif
       
   511 				if(!error) // Looks awkward inside the macro above..
       
   512 					error = iServer.IndexAdapter().ForceDeleteEntry(entry->Id());
       
   513 				
       
   514 				if (error)
       
   515 					iDeletedEntries->Delete(deleteIndex);
       
   516 				else
       
   517 					deleteIndex++;
       
   518 				iMovedEntries->Delete(moveIndex);
       
   519 				}
       
   520 			else
       
   521 				{ // Moving the entry..
       
   522 				TMsvEntry deletedEntry(*entry);
       
   523 				// this should be removed and CMsvDelete made a friend of TMsvEntry
       
   524 				deletedEntry.iDetails.Set(TPtrC());
       
   525 				deletedEntry.iDescription.Set(TPtrC());
       
   526 				deletedEntry.SetDeleted(ETrue);
       
   527 				deletedEntry.SetVisible(EFalse);
       
   528 				deletedEntry.SetParent(KMsvDeletedEntryFolderEntryId);
       
   529 
       
   530 				TMsvId backUpEntryId = entry->Id();
       
   531 				iServer.IndexAdapter().LockEntry(backUpEntryId);
       
   532 				error = iServer.IndexAdapter().ChangeEntry(deletedEntry, KMsvServerId, EFalse);
       
   533 				iServer.IndexAdapter().ReleaseEntry(backUpEntryId);
       
   534 				if (error)
       
   535 					iMovedEntries->Delete(moveIndex);
       
   536 				else
       
   537 					moveIndex++;
       
   538 				iDeletedEntries->Delete(deleteIndex);
       
   539 				}
       
   540 			}
       
   541 		else
       
   542 			error = KErrAccessDenied;
       
   543 
       
   544 		if (error && iError==KErrNone)
       
   545 			iError=error;
       
   546 		}
       
   547 	
       
   548 	iServer.IndexAdapter().CommitTransaction();
       
   549 	}
       
   550 
       
   551 
       
   552 
       
   553 void CMsvDelete::Complete(TInt aError)
       
   554 //
       
   555 //
       
   556 //
       
   557 	{
       
   558 	User::RequestComplete(iObserverStatus, aError);
       
   559 	iState=ECompleted;
       
   560 	iDeletionIndex=0;
       
   561 	}