messagingfw/msgsrvnstore/server/src/msvindexadapter.cpp
changeset 22 bde600d88860
child 35 f8ad95794a08
child 40 320ec5cd0227
equal deleted inserted replaced
21:08008ce8a6df 22:bde600d88860
       
     1 // Copyright (c) 2007-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 #ifdef _DEBUG
       
    17 #undef _NO_SERVER_LOGGING_
       
    18 #endif
       
    19 
       
    20 /**
       
    21  * User Includes
       
    22  */
       
    23 #include "MSVSERV.H"
       
    24 #include "MSVARRAY.H"
       
    25 #include "msvdbadapter.h"
       
    26 #include "msvcacheentry.h"
       
    27 #include "msvindexadapter.h"
       
    28 #include "msventryfreepool.h"
       
    29 #include "msvcachevisiblefolder.h"
       
    30 #include "msvsearchsortdeltacache.h"
       
    31 #include "msvsearchsortcachemanager.h"
       
    32 
       
    33 /**
       
    34  *System Includes
       
    35  */
       
    36 #include <msvuids.h>
       
    37 #include <msvstd.h>
       
    38 
       
    39 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS 
       
    40 #include "msvconsts.h"
       
    41 #endif
       
    42 
       
    43 /**
       
    44  * MACRO DEFINITIONS
       
    45  */
       
    46 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
    47 	#define INITIAL_NUM_ENTRIES 10
       
    48 #else
       
    49 	#define INITIAL_NUM_ENTRIES 13
       
    50 #endif
       
    51 
       
    52 /**
       
    53  * CONSTANT DEFINITIONS
       
    54  */
       
    55 const TInt KMsvMtmListGranularity=8;
       
    56 const TInt KMsvChangeAttributesListGranularity=32;
       
    57 
       
    58 
       
    59 
       
    60 /**
       
    61  * FUNCTION DEFINITIONS
       
    62  */
       
    63 
       
    64 
       
    65 
       
    66 /**
       
    67  * CMsvIndexAdapter()
       
    68  */
       
    69 CMsvIndexAdapter::CMsvIndexAdapter(CMsvServer& aServer)
       
    70     :CActive(EPriorityStandard), iServer(aServer), iFolderListHeader(CMsvCacheVisibleFolder::iOffset)
       
    71 	{	
       
    72 	CActiveScheduler::Add(this);		
       
    73 	}
       
    74 
       
    75 
       
    76 
       
    77 
       
    78 /**
       
    79  * ~CMsvIndexAdapter()
       
    80  */
       
    81 CMsvIndexAdapter::~CMsvIndexAdapter()
       
    82 	{
       
    83 
       
    84 #ifndef _NO_SERVER_LOGGING_
       
    85 	iServer.Log(_L("Destroying CMsvIndexAdapter object."));
       
    86 #endif
       
    87 	
       
    88 	Cancel();
       
    89 	
       
    90 	// 1. Close the database.
       
    91 #ifndef _NO_SERVER_LOGGING_
       
    92 	iServer.Log(_L("Closing the database."));
       
    93 #endif
       
    94 	if(iDbAdapter != NULL)
       
    95 		delete iDbAdapter;
       
    96 
       
    97 	// 2. Delete Cache.
       
    98 #ifndef _NO_SERVER_LOGGING_
       
    99 	iServer.Log(_L("Destroying Cache."));
       
   100 #endif
       
   101 	
       
   102 	CMsvCacheVisibleFolder* folderNode = NULL;
       
   103 	TDblQueIter<CMsvCacheVisibleFolder> dqIter(iFolderListHeader);
       
   104 
       
   105     dqIter.SetToFirst();
       
   106     while ((folderNode = dqIter++) != NULL)
       
   107         {
       
   108         folderNode->iDlink.Deque();
       
   109         delete folderNode;
       
   110         }
       
   111     
       
   112     iFreePoolInstance->ReleaseEntry(iRootEntry);
       
   113     iRootEntry = NULL;
       
   114 
       
   115     // 3. Delete internal data structure.
       
   116     iNonCommittedAddedEntryList.ResetAndDestroy();
       
   117     iNonCommittedChangedEntryList.Reset();
       
   118     iNonCommittedAddedEntryList.Close();
       
   119 	iNonCommittedChangedEntryList.Close();
       
   120     
       
   121     // 4. Flush extra memory in entry freepool.
       
   122     if(iFreePoolInstance != NULL)
       
   123     	{
       
   124     	iFreePoolInstance->FlushExcessMemory();	
       
   125     	}
       
   126 	
       
   127 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   128 	// Added for 557.
       
   129 	iMaxMsvIdList.Close();
       
   130 #endif
       
   131 
       
   132 	delete iIdle;
       
   133 	}
       
   134 
       
   135 
       
   136 
       
   137 
       
   138 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   139 /**
       
   140  * NewL()
       
   141  * @return The newly created index adapter object.
       
   142  * 
       
   143  * Function added as part of PREQ 557.
       
   144  * It returns an instance of CMsvIndexAdapter class. 
       
   145  */
       
   146 CMsvIndexAdapter* CMsvIndexAdapter::NewL(CMsvServer& aServer)
       
   147 	{
       
   148 	CMsvIndexAdapter *self = new(ELeave) CMsvIndexAdapter(aServer);
       
   149 	CleanupStack::PushL(self);
       
   150 	
       
   151 	self->ConstructL();
       
   152 	
       
   153 	CleanupStack::Pop();
       
   154 	return self;
       
   155 	}
       
   156 
       
   157 
       
   158 
       
   159 
       
   160 /**
       
   161  * ConstructL()
       
   162  * 
       
   163  * Function added as part of PREQ 557.
       
   164  * The function is called from NewL().
       
   165  * 1. Create the DB adapter object.
       
   166  * 2. Initialize freepool object.
       
   167  * 3. Create the root entry in cache.
       
   168  * 4. Browse through the preferred drive list.
       
   169  *    i. For each drive in the preferred drive list the function 
       
   170  *       assigns a unique drive-id (0< Id <8).
       
   171  *	 ii. Attach the DB to the primary database.
       
   172  *  iii. Update the maxId of the database to MaxId table.
       
   173  *   iv. If the database is not compatible or corrupt, update the 
       
   174  *       appropriate drive status in CMsvServer data structure.
       
   175  *    v. Fetch children of root entry and Local-Service entry from the DB to the cache.      
       
   176  */
       
   177 void CMsvIndexAdapter::ConstructL()
       
   178 	{
       
   179 #ifndef _NO_SERVER_LOGGING_
       
   180 	iServer.Log(_L("Inside ConstructL()..."));
       
   181 #endif
       
   182 	
       
   183 	// Create database adapter object.
       
   184 	iDbAdapter = CMsvDBAdapter::NewL();
       
   185 		
       
   186 #ifndef _NO_SERVER_LOGGING_
       
   187 	iServer.Log(_L("The database object is created succesfully."));
       
   188 #endif
       
   189 	
       
   190 	iProgress.iCompleted = 0;
       
   191 	iProgress.iTotal = iProgress.iRemaining = INITIAL_NUM_ENTRIES;
       
   192 	
       
   193 	// Initialize freepool object.
       
   194 	iFreePoolInstance = CMsvEntryFreePool::Instance();
       
   195 	iFreePoolInstance->SetEssentialParam(&iFolderListHeader, this);
       
   196 	
       
   197 	// Drive id zero will be synonym of KCurrentDriveId. Drive
       
   198 	// id of a drive (including current) drive will never be zero.
       
   199 	// Drive of the current drive will always by KCurrentDriveId.
       
   200 	TUint driveId = KCurrentDriveId;
       
   201 
       
   202 	// Since driveId starts from 1, the first 
       
   203 	// entry in iMaxMsvIdList is not used.
       
   204 	// Enter a dummy entry in location zero.
       
   205 	iMaxMsvIdList.InsertL(0, 0);
       
   206 	
       
   207 	iProgress.iCompleted++;
       
   208 	iProgress.iRemaining--;
       
   209 	iProgress.iId = KMsvRootIndexEntryId;
       
   210 	
       
   211 	// For each drive in the preferred drive list, perform followings...
       
   212 	// 1. Check if a valid message store is available.
       
   213 	// 2. If not, skip the drive.
       
   214 	// 3. Assign a new drive Id to the drive and
       
   215 	//    update the entry in preferred drive list.
       
   216 	// 4. Attach the drive database to the primary DB.
       
   217 	// 5. Update the max Id list.
       
   218 	// 6. For current drive, fetch the children of root entry into cache.
       
   219 	// 7. Fetch children of localService into cache.
       
   220 	CMsvPreferredDriveList *driveList = CMsvPreferredDriveList::GetDriveList();
       
   221 	TUint curDriveIndex = driveList->CurrentDriveIndex();
       
   222 	for(TInt index=curDriveIndex; index<driveList->Count(); index++)
       
   223 		{
       
   224 		TMsvPreferredDrive driveEntry;
       
   225 		driveList->DriveInfoL(index, driveEntry);
       
   226 		
       
   227 		if(EMsvMessageStoreAvailableStatus == driveEntry.status)
       
   228 			{
       
   229 			// Assign a unique drive-id.
       
   230 			driveList->UpdateDriveIdL(index, driveId);
       
   231 			
       
   232 			// Attach the database.
       
   233 			TMsvId maxId;
       
   234 			iDbAdapter->AttachDBL(driveEntry.driveNum, driveId, maxId);
       
   235 			
       
   236 			// Insert the max Id in the list.
       
   237 			iMaxMsvIdList.InsertL( ((maxId >= MaskTMsvId(driveId, KFirstFreeEntryId))? (maxId+1): MaskTMsvId(driveId, KFirstFreeEntryId)), driveId);
       
   238 			driveId++;
       
   239 			}
       
   240 		iProgress.iCompleted++;
       
   241 		iProgress.iRemaining--;
       
   242 		}
       
   243 
       
   244 	iFirstFreeDriveId = (driveId%8)? (driveId%8): 2;
       
   245 
       
   246 	// Initializing remaining entries in MaxMsvId list.
       
   247 	for(TInt index=driveId; index<8; index++)
       
   248 		{
       
   249 		iMaxMsvIdList.InsertL(NULL, index);
       
   250 		}
       
   251 	
       
   252 	// For current drive fetch children of root entries also.
       
   253 	RPointerArray<CMsvCacheEntry> childEntryList;
       
   254 	CleanupClosePushL(childEntryList);	
       
   255 	// Create root entry node in the cache. A root folder node will never 
       
   256 	// be swapped out of cache. The children of root entry will be the 
       
   257 	// children of root entry in the current drive.
       
   258 	// Root id is masked to set the driveId in the folder node.
       
   259 	iRootNode = CMsvCacheVisibleFolder::NewL(MaskTMsvId(KCurrentDriveId, KMsvRootIndexEntryId));
       
   260 	iFolderListHeader.AddFirst(*iRootNode);
       
   261 	iRootNode->SetComplete(ETrue);
       
   262 	iDbAdapter->GetChildrenL(KMsvRootIndexEntryId, childEntryList);
       
   263 	iRootNode->AddEntryListL(childEntryList, ETrue);
       
   264 	childEntryList.Reset();
       
   265 	
       
   266 	// Fetch child of LocalServices.
       
   267 	CMsvCacheVisibleFolder* localServiceFolder = CMsvCacheVisibleFolder::NewL(MaskTMsvId(KCurrentDriveId, KMsvLocalServiceIndexEntryId));
       
   268 	iFolderListHeader.AddFirst(*localServiceFolder);
       
   269 	iDbAdapter->GetChildrenL(KMsvLocalServiceIndexEntryId, childEntryList);
       
   270 	localServiceFolder->AddEntryListL(childEntryList, ETrue);
       
   271 	CleanupStack::PopAndDestroy(1);   //childEntryList
       
   272 		
       
   273 	// Create root entry.
       
   274 	iRootEntry = iFreePoolInstance->EntryL(); //taking it from the freepool.
       
   275 	iRootEntry->Entry().iType = KUidMsvRootEntry;
       
   276 	iRootEntry->Entry().iDate.UniversalTime();
       
   277 	iRootEntry->Entry().SetId(KMsvRootIndexEntryId);
       
   278 	iRootEntry->Entry().SetParent(KErrNotFound);
       
   279 	iRootEntry->Entry().SetOwner(ETrue);
       
   280 	iRootEntry->Entry().iSize = 0;
       
   281 	
       
   282 	// Update progress
       
   283 	iProgress.iCompleted = iProgress.iTotal;
       
   284 	iProgress.iRemaining = 0;
       
   285 	iProgress.iId = KMsvRootIndexEntryId;
       
   286 
       
   287 #ifndef _NO_SERVER_LOGGING_
       
   288 	iServer.Log(_L("Cache initialized succesfully."));
       
   289 #endif
       
   290 	
       
   291 	iIdle = CIdle::NewL(CActive::EPriorityIdle);
       
   292 	CompleteSelf();
       
   293 	}
       
   294 
       
   295 
       
   296 
       
   297 /**
       
   298 GetInPreparationIds
       
   299 */
       
   300 void CMsvIndexAdapter::GetInPreparationIds(CMsvEntrySelection& aSelection, TUint aDriveId /*DEFAULT = 0 */)
       
   301 	{
       
   302 	if(iDbAdapter)
       
   303 		{
       
   304 		TRAP_IGNORE(iDbAdapter->GetInPreparationIdL(aSelection, aDriveId));
       
   305 		}
       
   306 	}
       
   307 
       
   308 
       
   309 #else		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   310 
       
   311 
       
   312 /**
       
   313  * NewL()
       
   314  * @param TFileName: DB File Name.
       
   315  * @return The newly created index adapter.
       
   316  * 
       
   317  * It returns an instance of CMsvIndexAdapter class. 
       
   318  */
       
   319 CMsvIndexAdapter* CMsvIndexAdapter::NewL(CMsvServer& aServer, const TFileName& aDbFileName)
       
   320 	{
       
   321 	CMsvIndexAdapter *self = new(ELeave) CMsvIndexAdapter(aServer);
       
   322 	CleanupStack::PushL(self);
       
   323 	
       
   324 	self->ConstructNewL(aDbFileName);
       
   325 	
       
   326 	CleanupStack::Pop();
       
   327 	return self;
       
   328 	}
       
   329 
       
   330 
       
   331 
       
   332 
       
   333 /**
       
   334  * OpenL()
       
   335  * @param TFileName: DB File Name.
       
   336  * @return The newly created index adapter.
       
   337  * 
       
   338  * It returns an instance of CMsvIndexAdapter class. 
       
   339  */
       
   340 CMsvIndexAdapter* CMsvIndexAdapter::OpenL(CMsvServer& aServer, const TFileName& aDbFileName)
       
   341 	{
       
   342 	CMsvIndexAdapter *self = new(ELeave) CMsvIndexAdapter(aServer);
       
   343 	CleanupStack::PushL(self);
       
   344 	
       
   345 	self->ConstructOpenL(aDbFileName);
       
   346 	
       
   347 	CleanupStack::Pop();
       
   348 	return self;
       
   349 	}
       
   350 
       
   351 
       
   352 
       
   353 
       
   354 /**
       
   355  * ConstructNewL()
       
   356  * 
       
   357  * The function is called from NewL().
       
   358  * 1. Check if a database with the passed name already exists.
       
   359  * 1.1. If yes, open the database.
       
   360  * 1.2. If no, create a new database with the same name.
       
   361  * 2. Creates entry cache.
       
   362  * 3. If a new database is created, create root entry also.
       
   363  */
       
   364 void CMsvIndexAdapter::ConstructNewL(const TFileName& aDbFileName)
       
   365 	{
       
   366 #ifndef _NO_SERVER_LOGGING_
       
   367 	iServer.Log(_L("Creating CMsvIndexAdapter instance..."));
       
   368 #endif
       
   369 	
       
   370 	// Delete the database first, if it already exists.
       
   371 	CMsvDBAdapter::DeleteDB(aDbFileName);
       
   372 	
       
   373 	// Get the instance of free pool.
       
   374 	iFreePoolInstance = CMsvEntryFreePool::Instance();
       
   375 
       
   376 	// Create the new database with the same name.
       
   377 	// If this leaves, nothing can be done and let NewL() leave.
       
   378 	iDbAdapter = CMsvDBAdapter::NewL(aDbFileName);
       
   379 #ifndef _NO_SERVER_LOGGING_
       
   380 	iServer.Log(_L("A new database %s is created..."), &aDbFileName);
       
   381 #endif
       
   382 	
       
   383 	iProgress.iTotal = iProgress.iRemaining = 1; //root
       
   384 	// Create root entry. 
       
   385 	CreateInitialSetOfEntriesL();
       
   386 	
       
   387 
       
   388 #ifndef _NO_SERVER_LOGGING_
       
   389 //	iServer.Log(_L("Cache initialized succesfully."));
       
   390 #endif
       
   391 	
       
   392 	iNextCreateId = KFirstFreeEntryId;
       
   393 	iIdle = CIdle::NewL(CActive::EPriorityIdle);
       
   394 	CompleteSelf();
       
   395 	}
       
   396 		
       
   397 
       
   398 
       
   399 
       
   400 	
       
   401 /**
       
   402  * ConstructOpenL()
       
   403  * 
       
   404  * The function is called from NewL().
       
   405  * 1. Check if a database with the passed name already exists.
       
   406  * 1.1. If yes, open the database.
       
   407  * 1.2. If no, create a new database with the same name.
       
   408  * 2. Creates entry cache.
       
   409  * 3. If a new database is created, it then read message resource file 
       
   410  *    and creates entry as mentioned in cache and database.
       
   411  */
       
   412 void CMsvIndexAdapter::ConstructOpenL(const TFileName& aDbFileName)
       
   413 	{
       
   414 #ifndef _NO_SERVER_LOGGING_
       
   415 	iServer.Log(_L("Creating CMsvIndexAdapter instance..."));
       
   416 #endif
       
   417 	
       
   418 	// Get the instance of free pool
       
   419 	iFreePoolInstance = CMsvEntryFreePool::Instance();
       
   420 
       
   421 	// Open the database.
       
   422 	iDbAdapter = CMsvDBAdapter::OpenL(aDbFileName);
       
   423 	
       
   424 #ifndef _NO_SERVER_LOGGING_
       
   425 	iServer.Log(_L("Opening database %s is succesful."), &aDbFileName);
       
   426 #endif
       
   427 		
       
   428 	iProgress.iTotal = iProgress.iRemaining = INITIAL_NUM_ENTRIES;	
       
   429 	CreateInitialCacheL();
       
   430 
       
   431 #ifndef _NO_SERVER_LOGGING_
       
   432 	iServer.Log(_L("Cache initialized succesfully."));
       
   433 #endif
       
   434 
       
   435 	TMsvId tmpNextId = NULL;
       
   436 	iDbAdapter->GetMaxTMsvIdL(tmpNextId);
       
   437 	iNextCreateId = (tmpNextId >= KFirstFreeEntryId)? (tmpNextId+1) : KFirstFreeEntryId;
       
   438 	
       
   439 	iIdle = CIdle::NewL(CActive::EPriorityIdle);
       
   440 	CompleteSelf();
       
   441 	}
       
   442 	
       
   443 
       
   444 
       
   445 
       
   446 /**
       
   447  * CreateInitialSetOfEntries()
       
   448  * 
       
   449  * The function is called from ConstructL(), whenever a new DB is created.
       
   450  * The function creates root entry into database and cache.
       
   451  */
       
   452 void CMsvIndexAdapter::CreateInitialSetOfEntriesL()
       
   453 	{
       
   454 	
       
   455 #ifndef _NO_SERVER_LOGGING_
       
   456 	iServer.Log(_L("Inside CreateInitialSetOfEntriesL(): Creating standard entries for new DB."));
       
   457 #endif
       
   458 	
       
   459 	// 1. Initialize the instance of free pool.
       
   460 	iFreePoolInstance->SetEssentialParam(&iFolderListHeader, this);
       
   461 		
       
   462 	// 2. Creating root entry into database.
       
   463 	iRootEntry = iFreePoolInstance->EntryL(); //taking it from the freepool.
       
   464 	iRootEntry->Entry().iType = KUidMsvRootEntry;
       
   465 	iRootEntry->Entry().iDate.UniversalTime();
       
   466 	iRootEntry->Entry().SetId(KMsvRootIndexEntryId);
       
   467 	iRootEntry->Entry().SetParent(KErrNotFound);
       
   468 	iRootEntry->Entry().iSize = 0;
       
   469 	
       
   470 	TMsvId visibleFolderId = KMsvRootIndexEntryId;
       
   471 	iDbAdapter->CreateEntryL(iRootEntry->Entry(), visibleFolderId);
       
   472 	
       
   473 	// 3. Add root entry to cache as well
       
   474 	CMsvCacheVisibleFolder* rootFolder = CMsvCacheVisibleFolder::NewL(KMsvRootIndexEntryId);
       
   475 	iFolderListHeader.AddFirst(*rootFolder);
       
   476 	rootFolder->SetComplete(ETrue);
       
   477 	
       
   478 	// Update progress
       
   479 	iProgress.iCompleted++;
       
   480 	iProgress.iRemaining--;
       
   481 	iProgress.iId = KMsvRootIndexEntryId;
       
   482 	}
       
   483 
       
   484 
       
   485 
       
   486 
       
   487 
       
   488 /**
       
   489  * CreateInitialCache()
       
   490  * 
       
   491  * The function is called from NewL(), whenever an existing DB is opened.
       
   492  * It creates the intial cache. It creates root entry in cache and fetches
       
   493  * child of root from DB and push them into cache. It then fetches child
       
   494  * entries of LocalServices and push them too into cache. 
       
   495  * 
       
   496  * >>>> The function can be enhanced to load children of additional folders
       
   497  * to cache along with the above standard folders. These additional folders 
       
   498  * can be mentioned by licensees in msgs.ini file.
       
   499  */
       
   500 void CMsvIndexAdapter::CreateInitialCacheL()
       
   501 	{
       
   502 #ifndef _NO_SERVER_LOGGING_
       
   503 	iServer.Log(_L("Inside CreateInitialCache(): Initializing Cache."));
       
   504 #endif
       
   505 
       
   506 	//1. Initialize the instance of free pool.
       
   507 	iFreePoolInstance->SetEssentialParam(&iFolderListHeader, this);
       
   508 	
       
   509 	// 2. Add root entry to cache.
       
   510 	CMsvCacheVisibleFolder* rootFolder = CMsvCacheVisibleFolder::NewL(KMsvRootIndexEntryId);
       
   511 	iFolderListHeader.AddFirst(*rootFolder);
       
   512 	// 2.1 Update progress
       
   513 	iProgress.iCompleted++;
       
   514 	iProgress.iRemaining--;
       
   515 	iProgress.iId = KMsvRootIndexEntryId;
       
   516 	
       
   517 	// 3. Fetch child of root entries from DB.
       
   518 	RPointerArray<CMsvCacheEntry> childrenOfRoot;
       
   519 	iDbAdapter->GetChildrenL(KMsvRootIndexEntryId, childrenOfRoot);
       
   520 
       
   521 	// 3.1 Get the root entry from DB.
       
   522 	CMsvCacheEntry *rootEntry = NULL;
       
   523 	TMsvId visibleFolder = NULL;
       
   524 	iDbAdapter->GetEntryL(KMsvRootIndexEntryId, rootEntry, visibleFolder);
       
   525 	// 3.2 Copy the TMsvEntry of root from CMsvCacheEntry.
       
   526 	//Mem::Copy(&iRootEntry->Entry(), &rootEntry->Entry(), sizeof(TMsvEntry));
       
   527 	iRootEntry = rootEntry;
       
   528 	// 3.3 Release the cache entry back to the freepool.
       
   529 	//iFreePoolInstance->ReleaseEntry(rootEntry);	
       
   530 	
       
   531 	// 4. Add children to cache.
       
   532 	rootFolder->AddEntryListL(childrenOfRoot, ETrue);
       
   533 	// 4.1 Update progress
       
   534 	iProgress.iCompleted += 4;
       
   535 	iProgress.iRemaining -= 4;
       
   536 	iProgress.iId = KMsvLocalServiceIndexEntryId;
       
   537 	
       
   538 	// 5. Set the visible folder as complete
       
   539 	rootFolder->SetComplete(ETrue);
       
   540 	
       
   541 	
       
   542 	// 6. Fetch child of LocalServices
       
   543 	childrenOfRoot.Reset();
       
   544 	iDbAdapter->GetChildrenL(KMsvLocalServiceIndexEntryId, childrenOfRoot);
       
   545 	
       
   546 	CMsvCacheVisibleFolder* localFolder = CMsvCacheVisibleFolder::NewL(KMsvLocalServiceIndexEntryId);
       
   547 	iFolderListHeader.AddFirst(*localFolder);
       
   548 		
       
   549 	// 7. Add children to cache.
       
   550 	localFolder->AddEntryListL(childrenOfRoot);
       
   551 	// 7.1 Update progress
       
   552 	iProgress.iCompleted = iProgress.iTotal;
       
   553 	iProgress.iRemaining = 0;
       
   554 	iProgress.iId = KMsvGlobalInBoxIndexEntryId;
       
   555 	
       
   556 	// 8. Set the visible folder as complete
       
   557 	localFolder->SetComplete(ETrue);
       
   558 	childrenOfRoot.Close();
       
   559 	}
       
   560 	
       
   561 
       
   562 
       
   563 /**
       
   564 GetInPreparationIds
       
   565 */
       
   566 void CMsvIndexAdapter::GetInPreparationIds(CMsvEntrySelection& aSelection)
       
   567 	{
       
   568 	if(iDbAdapter)
       
   569 		{
       
   570 		TRAP_IGNORE(iDbAdapter->GetInPreparationIdL(aSelection));
       
   571 		}	
       
   572 	}
       
   573 
       
   574 
       
   575 #endif 		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   576 
       
   577 
       
   578 /**
       
   579  *CompleteSelf
       
   580  *This will make sure that Runl is called.
       
   581  */
       
   582 void CMsvIndexAdapter::CompleteSelf()
       
   583 	{
       
   584 	iStatus=KRequestPending;
       
   585 	SetActive();
       
   586 	TRequestStatus* st=&iStatus;
       
   587 	User::RequestComplete(st, KErrNone);
       
   588 	}
       
   589 
       
   590 
       
   591 
       
   592 /**
       
   593  * RunL()
       
   594  */
       
   595 void CMsvIndexAdapter::RunL()
       
   596 	{
       
   597 	// Set the state for the background state machine.
       
   598 	iBackgroundOperationState = ERemoveDeletedEntries;
       
   599 	iBackgroundOperationPerformed = 0;
       
   600 	}
       
   601 	
       
   602 
       
   603 
       
   604 
       
   605 /**
       
   606  * DoCancel()
       
   607  */
       
   608 void CMsvIndexAdapter::DoCancel()
       
   609 	{
       
   610 	iIdle->Cancel();	
       
   611 	}
       
   612 
       
   613 
       
   614 
       
   615 
       
   616 /**
       
   617  * AddEntry()
       
   618  */
       
   619 TInt CMsvIndexAdapter::AddEntry(TMsvEntry& aEntry, TSecureId aOwnerId, TBool aAutoAssignId)
       
   620 	{
       
   621 	TRAPD(err, DoAddEntryL(aEntry, aOwnerId, aAutoAssignId));
       
   622 	return err;
       
   623 	}
       
   624 
       
   625 
       
   626 /**
       
   627  * AddEntryNoCommit()
       
   628  */
       
   629 TInt CMsvIndexAdapter::AddEntryNoCommit(TMsvEntry& aEntry, TSecureId aOwnerId, TBool aAutoAssignId)
       
   630 	{
       
   631 	if(iDbAdapter)
       
   632 		{
       
   633 		TRAP_IGNORE(iDbAdapter->BeginTransactionL());
       
   634 		}
       
   635 	else
       
   636 		{
       
   637 		return ErrorState();
       
   638 		}
       
   639 	TRAPD(err, DoAddEntryL(aEntry, aOwnerId, aAutoAssignId, EFalse));
       
   640 	if(err)
       
   641 		{
       
   642 		RollbackAdditions();
       
   643 		}
       
   644 	return err;
       
   645 	}
       
   646 
       
   647 
       
   648 
       
   649 /**
       
   650  * DoAddEntryL()
       
   651  * 
       
   652  * Add the entry to the index and then the file. 
       
   653  * If either fails the function leaves. Creates 
       
   654  * its own copy of TMsvEntry (SetEntryL() code). 
       
   655  * This can be optimized further.
       
   656  */
       
   657 void CMsvIndexAdapter::DoAddEntryL(TMsvEntry& aEntry, TSecureId aOwnerId, TBool aAutoAssignId, TBool aCommitToDb)
       
   658 	{
       
   659 	// Leave if the message store is not currently available.
       
   660     User::LeaveIfError(iErrorState);
       
   661     
       
   662 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   663 	// get and set the unique id
       
   664 	if (aAutoAssignId)
       
   665 		{
       
   666 		aEntry.SetId(NextId(GetDriveId(aEntry.Parent())));
       
   667 		}
       
   668 
       
   669 	if (aEntry.iType == KUidMsvServiceEntry)
       
   670 		{
       
   671 		if(KMsvLocalServiceIndexEntryId == UnmaskTMsvId(aEntry.iId))
       
   672 			{
       
   673 			aEntry.iServiceId = KMsvLocalServiceIndexEntryId;
       
   674 			}
       
   675 		else
       
   676 			{
       
   677 			aEntry.iServiceId = aEntry.Id();
       
   678 			}
       
   679 		}
       
   680 #else		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   681 	if (aAutoAssignId)
       
   682 		{
       
   683 		aEntry.SetId(NextId());
       
   684 		}
       
   685 
       
   686 	if (aEntry.iType == KUidMsvServiceEntry)
       
   687 		{
       
   688 		aEntry.iServiceId = aEntry.Id();
       
   689 		}
       
   690 #endif		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   691 
       
   692 	CMsvCacheEntry* parentEntry = NULL;
       
   693 	FindEntryL(aEntry.Parent(), parentEntry);
       
   694 
       
   695 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   696 	if(UnmaskTMsvId(aEntry.iId) == KMsvDeletedEntryFolderEntryId)
       
   697 		{
       
   698 		aEntry.SetVisibleFolderFlag(ETrue);
       
   699 		}
       
   700 	else	
       
   701 #endif
       
   702 		{		
       
   703 		// If entry is set to visible while creation, then set the visible folder
       
   704 		// flag to ETrue, this will not change for the lifetime of an TMsvEntry.
       
   705 		if(parentEntry->Entry().VisibleFolderFlag())
       
   706 			{
       
   707 			if( (aEntry.Visible()) && 
       
   708 			    (aEntry.iType == KUidMsvFolderEntry || aEntry.iType == KUidMsvServiceEntry)
       
   709 			  )
       
   710 				{
       
   711 				aEntry.SetVisibleFolderFlag(ETrue);
       
   712 				}
       
   713 			else
       
   714 				{
       
   715 				aEntry.SetVisibleFolderFlag(EFalse);
       
   716 				}				
       
   717 			}
       
   718 		else
       
   719 			{
       
   720 			aEntry.SetVisibleFolderFlag(EFalse);
       
   721 			}
       
   722 		}
       
   723 		
       
   724 	aEntry.SetOwner(EFalse);
       
   725 	TMsvId visibleFolderId;
       
   726 	if(!GetVisibleFolderId(aEntry.Parent(), visibleFolderId))
       
   727 		{
       
   728 		User::Leave(KErrNotFound);
       
   729 		}
       
   730     
       
   731 	// Add entry to cache.      
       
   732     CMsvCacheEntry* newCacheEntry = NULL;   
       
   733     newCacheEntry = iFreePoolInstance->EntryL();
       
   734     // Set the owner ID of the entry - the SID of the owning process.
       
   735     newCacheEntry->SetEntryOwnerId(aOwnerId);
       
   736     
       
   737     CMsvCacheVisibleFolder* visibleFolder = NULL;
       
   738     TRAPD(err, newCacheEntry->SetEntryL(aEntry);
       
   739                visibleFolder = AddEntryToCacheL(visibleFolderId, newCacheEntry);
       
   740          );
       
   741     if(err)
       
   742         {
       
   743         iFreePoolInstance->ReleaseEntryWithoutTransaction(newCacheEntry);
       
   744         User::Leave(err);
       
   745         }
       
   746 
       
   747 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   748     TRAP(err,
       
   749             if(aCommitToDb)
       
   750                 iDbAdapter->BeginTransactionL();
       
   751             iDbAdapter->CreateEntryL(aEntry, visibleFolderId);
       
   752             // Set the owner flag of parent entry if not already done.
       
   753             // For standard entry created from indexContext, parent Id will not be masked.
       
   754             iDbAdapter->UpdateOwnerStatusL(MaskTMsvId(GetDriveId(aEntry.iId), aEntry.Parent()), parentEntry->Entry(), ETrue);
       
   755             if(aCommitToDb)
       
   756                 iDbAdapter->CommitTransactionL();
       
   757         );
       
   758 #else
       
   759     TRAP(err,
       
   760             if(aCommitToDb)
       
   761                 iDbAdapter->BeginTransactionL();
       
   762             iDbAdapter->CreateEntryL(aEntry, visibleFolderId);
       
   763             // Set the owner flag of parent entry if not already done.
       
   764             // For standard entry created from indexContext, parent Id will not be masked.
       
   765             iDbAdapter->UpdateOwnerStatusL(aEntry.Parent(), parentEntry->Entry(), ETrue);
       
   766             if(aCommitToDb)
       
   767                 iDbAdapter->CommitTransactionL();
       
   768         );
       
   769 #endif  
       
   770     if(err & KSqlErrConstraint != err)
       
   771         {
       
   772         if(aCommitToDb)
       
   773             iDbAdapter->RollbackTransactionL();
       
   774         // This will not leave...
       
   775         TRAP_IGNORE(visibleFolder->DeleteEntryL(newCacheEntry->GetId()));
       
   776         User::Leave(err);
       
   777         }	
       
   778 	parentEntry->Entry().SetOwner(ETrue);
       
   779 
       
   780 	if(!aCommitToDb)
       
   781 		{
       
   782 		// Add entry to the list of non-committed entries.
       
   783 		CNonCommittedAddedEntries* nonCommittedAddedEntries = new(ELeave)CNonCommittedAddedEntries(visibleFolderId, newCacheEntry);
       
   784 		CleanupStack::PushL(nonCommittedAddedEntries);
       
   785 		iNonCommittedAddedEntryList.AppendL(nonCommittedAddedEntries);
       
   786 		CleanupStack::Pop(nonCommittedAddedEntries);
       
   787 		}
       
   788 
       
   789 	if(aEntry.iType.iUid == KUidMsvMessageEntryValue && CMSvSearchSortCacheManager::Instance()->iManagerEntry != NULL)
       
   790 		{	
       
   791 		TMsgType aType(ENewMsg);
       
   792 		if(CMSvSearchSortCacheManager::Instance()->iManagerEntry->Count()>0)
       
   793 			{
       
   794 			CMsvSearchSortDeltaCache::Instance()->EntryInDeltaCache(aEntry.Id(),aType);
       
   795 			}
       
   796 		}	
       
   797 	}
       
   798 	
       
   799 	
       
   800 
       
   801 
       
   802 /**
       
   803  * GetVisibleFolderId()
       
   804  * 
       
   805  * Returns ETrue, if the parent entry exists. Otherwise returns EFalse.
       
   806  * IN: Parent Id of the entry, whose immediate visible folder has to be found.
       
   807  * OUT: Visible folder Id.
       
   808  */
       
   809 TBool CMsvIndexAdapter::GetVisibleFolderId(TMsvId aParentId, TMsvId& aVisibleFolderId)
       
   810 	{
       
   811 	// If the entry is either a root entry (parent=KErrNotFound) or 
       
   812 	// child of root entry its visibleFolderId will be root entry itself.
       
   813 	if((KErrNotFound == aParentId) || (KMsvRootIndexEntryId == aParentId))
       
   814 		{
       
   815 		aVisibleFolderId = KMsvRootIndexEntryId;
       
   816 		return ETrue;
       
   817 		}
       
   818 	
       
   819 	// Get the visible flag of parent entry.
       
   820 	
       
   821 	// If parent entry is visible, then immediateVisibleFolder of child
       
   822 	// should be parent Id. And if it is invisible then child's immediateVisibleFolder 
       
   823 	// should be same as parent's immediateVisibleFolder.
       
   824 	// First check in cache.
       
   825 	if(!iFolderListHeader.IsEmpty())
       
   826 		{
       
   827 		CMsvCacheVisibleFolder* folderNode = NULL;
       
   828 		TDblQueIter<CMsvCacheVisibleFolder> dqIter(iFolderListHeader);
       
   829 		dqIter.SetToFirst(); 
       
   830 		while((folderNode = dqIter++)!=NULL)
       
   831 			{
       
   832 			// Check if the current folder node is parent.
       
   833 			if( aParentId == folderNode->GetFolderId() )
       
   834 				{
       
   835 				aVisibleFolderId = aParentId;
       
   836 				return ETrue;
       
   837 				}
       
   838 			}
       
   839 		dqIter.SetToFirst(); 
       
   840 		CMsvCacheEntry* entry;
       
   841 		while((folderNode = dqIter++)!=NULL)
       
   842 			{
       
   843 			// Check if the current folder node is parent.
       
   844 			if(folderNode->GetEntry(aParentId, entry))
       
   845 				{
       
   846 				if(entry->Entry().VisibleFolderFlag())
       
   847 					{
       
   848 					aVisibleFolderId = aParentId;
       
   849 					}
       
   850 				else
       
   851 					{
       
   852 					//If the visible folder is not the parent, then
       
   853 					//the current folder must be the visible folder,
       
   854 					//as otherwise the parent would have been under another
       
   855 					//folder node.
       
   856 					aVisibleFolderId = folderNode->GetFolderId();
       
   857 					}
       
   858 				return ETrue;
       
   859 				}
       
   860 			}
       
   861 		}
       
   862 	
       
   863 	// Entry cannot be found in cache,
       
   864 	// Now search in DB.
       
   865 	TInt err = KErrNone;
       
   866 	if(iDbAdapter)
       
   867 		{
       
   868 		TRAP(err, iDbAdapter->GetVisibleFolderIdL(aParentId, aVisibleFolderId));
       
   869 		}
       
   870 	else
       
   871 		{
       
   872 		return EFalse;
       
   873 		}
       
   874 	if(KErrNone == err)
       
   875 		{
       
   876 		return ETrue; 		
       
   877 		}
       
   878 	return EFalse;		
       
   879 	}
       
   880 
       
   881 
       
   882 
       
   883 
       
   884 
       
   885 /**
       
   886  * DeleteEntry()
       
   887  */
       
   888 TInt CMsvIndexAdapter::DeleteEntry(TMsvId aId)
       
   889 	{
       
   890 	CMsvEntrySelection* selection = NULL;
       
   891 	
       
   892 	TRAPD(error, selection = new(ELeave)CMsvEntrySelection; selection->AppendL(aId););
       
   893 	if(KErrNone == error)
       
   894 		{
       
   895 		error = DeleteSelection(*selection);
       
   896 		}
       
   897 
       
   898 	TMsgType aType(EDeletedMsg);
       
   899 	if(CMSvSearchSortCacheManager::Instance()->iManagerEntry->Count()>0 && error == KErrNone)
       
   900 		{
       
   901 		CMsvSearchSortDeltaCache::Instance()->EntryInDeltaCache(aId,aType);
       
   902 		}
       
   903 
       
   904 	delete selection;
       
   905 	return error;
       
   906 	}
       
   907 
       
   908 
       
   909 
       
   910 
       
   911 
       
   912 /**
       
   913  * DeleteSelection
       
   914  * Deletes a selection of entries.
       
   915  *
       
   916  * @param aSelection Selection of TMsvIds of the entries to be deleted
       
   917  * @return TInt System-wide error code.
       
   918  */
       
   919 TInt CMsvIndexAdapter::DeleteSelection(const CMsvEntrySelection& aSelection)
       
   920 	{
       
   921 	TInt count = aSelection.Count();
       
   922 
       
   923 	if(!iDbAdapter)
       
   924 		{
       
   925 		return ErrorState();
       
   926 		}
       
   927 	// Only start a transaction if there are more than 1 entries to be deleted.
       
   928 	if(count > 1)
       
   929 		{
       
   930 		TRAP_IGNORE(iDbAdapter->BeginTransactionL());		
       
   931 		}
       
   932 	// If the transaction is opened, deleted
       
   933 	// entry will be released temporarily.
       
   934 	iFreePoolInstance->BeginTransaction();
       
   935 	TInt error = KErrNone;
       
   936 	TRAP(error, DoDeleteSelectionL(aSelection));
       
   937 	if (error)
       
   938 		{
       
   939 		if(count > 1)
       
   940 			{
       
   941 			TRAP_IGNORE(iDbAdapter->RollbackTransactionL());
       
   942 			}
       
   943 		iFreePoolInstance->RollbackTransaction();
       
   944 		}
       
   945 	else
       
   946 		{
       
   947 		if(count > 1)
       
   948 			{
       
   949 			TRAP_IGNORE(iDbAdapter->CommitTransactionL());
       
   950 			}	
       
   951 		iFreePoolInstance->CommitTransaction();
       
   952 		}
       
   953 	return error;
       
   954 	}
       
   955 
       
   956 
       
   957 
       
   958 
       
   959 
       
   960 /**
       
   961  * DoDeleteSelectionL
       
   962  */
       
   963 void CMsvIndexAdapter::DoDeleteSelectionL(const CMsvEntrySelection& aSelection)
       
   964 	{
       
   965 	User::LeaveIfError(iErrorState);
       
   966 	CMsvCacheVisibleFolder* folderNode = NULL;
       
   967 	TDblQueIter<CMsvCacheVisibleFolder> dqIter(iFolderListHeader);
       
   968 	const TInt count = aSelection.Count();
       
   969 	if(count <= 0)
       
   970 		{
       
   971 		return;
       
   972 		}
       
   973 	
       
   974 	CMsvCacheEntry* entry = NULL;
       
   975 	TBool releaseEntry = FindEntryL(aSelection.At(0), entry, EFalse);
       
   976 	TMsvId parentId = entry->Entry().Parent();
       
   977 	if(releaseEntry)
       
   978 		{
       
   979 		iFreePoolInstance->ReleaseEntry(entry, ETrue);
       
   980 		}
       
   981 	CMsvEntrySelection* children = new(ELeave)CMsvEntrySelection;
       
   982 	CleanupStack::PushL(children);
       
   983 	
       
   984 	for (TInt index=0; index<count; ++index)
       
   985 		{
       
   986 		dqIter.SetToFirst(); 
       
   987 		TBool found = EFalse;
       
   988 		while((folderNode = dqIter++)!=NULL)
       
   989 			{
       
   990 			TRAPD(err, folderNode->DeleteEntryL(aSelection.At(index)));	
       
   991 			if(err != KErrNotFound && err != KErrNone)
       
   992 				{
       
   993 				User::Leave(err);
       
   994 				}
       
   995 			 else if(err == KErrNone)	
       
   996 			 	{
       
   997 			 	found = ETrue;
       
   998 			 	break;
       
   999 			 	}
       
  1000 			}
       
  1001 		if(!found)
       
  1002 			{
       
  1003 			if(iDbAdapter)
       
  1004 				{
       
  1005 				if(iDbAdapter->EntryExistsL(aSelection.At(index)))
       
  1006 					{
       
  1007 					User::Leave(KErrAccessDenied);
       
  1008 					}
       
  1009 				}
       
  1010 			else
       
  1011 				{
       
  1012 				User::Leave(ErrorState());	
       
  1013 				}
       
  1014 			User::Leave(KErrNotFound);
       
  1015 			}
       
  1016 		
       
  1017 		if(iDbAdapter)
       
  1018 			{
       
  1019 			iDbAdapter->DeleteEntryL(aSelection.At(index));
       
  1020 			}
       
  1021 		else
       
  1022 			{
       
  1023 			User::Leave(ErrorState());	
       
  1024 			}
       
  1025 		}
       
  1026 	//Find the parent entry in cache and check for any children.
       
  1027 	//If there are no more children under the parent, then
       
  1028 	//reset the owner flag in cache and database.
       
  1029 	TRAPD(err, releaseEntry = FindEntryL(parentId, entry, EFalse));
       
  1030 	//If parent was also deleted then nothing left to do.
       
  1031 	if(err == KErrNotFound)
       
  1032 		{
       
  1033 		CleanupStack::PopAndDestroy(); //children
       
  1034 		return;
       
  1035 		}
       
  1036 	TRAP(err, 
       
  1037 		GetChildrenIdL(parentId, *children);
       
  1038 		if(0 == children->Count() && entry->Entry().Owner())
       
  1039 			{
       
  1040 			if(iDbAdapter)
       
  1041 				{
       
  1042 				iDbAdapter->UpdateOwnerStatusL(parentId, entry->Entry(), EFalse);		
       
  1043 				}
       
  1044 			else
       
  1045 				{
       
  1046 				User::Leave(ErrorState());
       
  1047 				}
       
  1048 			entry->Entry().SetOwner(EFalse);
       
  1049 			}
       
  1050 		);
       
  1051 	// Release the entry, since it is not added to cache.
       
  1052 	if(releaseEntry)
       
  1053 		{
       
  1054 		iFreePoolInstance->ReleaseEntry(entry, ETrue);
       
  1055 		}
       
  1056 	User::LeaveIfError(err);
       
  1057 	CleanupStack::PopAndDestroy(); //children
       
  1058 	}
       
  1059 
       
  1060 
       
  1061 
       
  1062 
       
  1063 
       
  1064 /**
       
  1065  * ExpandSelectionRecursively()
       
  1066  * Expands a selection to include all the descendents of the entries. They are order
       
  1067  * in such a way that they can be deleted in order, children first
       
  1068  *
       
  1069  * @param aSelection CMsvEntrySelection, which contains the TMsvIds of the entry passed.
       
  1070  * @return TInt System wide error code.
       
  1071  */
       
  1072 TInt CMsvIndexAdapter::ExpandSelectionRecursively(CMsvEntrySelection& aSelection)
       
  1073 	{
       
  1074 	TInt error = KErrNone;
       
  1075 	iOrigEntryPos=0;
       
  1076 	iRecursionSelection=&aSelection;
       
  1077 	TInt count = aSelection.Count();
       
  1078 	while (iOrigEntryPos < count)
       
  1079 		{
       
  1080 		TMsvId entryId = aSelection.At(iOrigEntryPos);
       
  1081 		if( !EntryExists(entryId) )
       
  1082 			{
       
  1083 			error = KErrNotFound;
       
  1084 			aSelection.Delete(iOrigEntryPos);
       
  1085 			}
       
  1086 		else
       
  1087 			{
       
  1088 			// if the entry has children
       
  1089 			CMsvEntrySelection* children = NULL;
       
  1090 			TRAPD(err, children = new (ELeave)CMsvEntrySelection);
       
  1091 			if(KErrNone != err)
       
  1092 				{
       
  1093 				return err;
       
  1094 				}
       
  1095 			TInt leave = KErrNone;
       
  1096 			TRAP(leave, GetChildrenIdL(entryId, *children));
       
  1097 			if(KErrNone != leave)
       
  1098 				{
       
  1099 				delete children;
       
  1100 				return leave;				
       
  1101 				}
       
  1102 			TInt count = children->Count();
       
  1103 			for(TInt index=0; index<count; ++index)
       
  1104 				{
       
  1105 				iRecursionIndex = iOrigEntryPos;
       
  1106 				TRAP(leave, DoExpandSelectionRecursivelyL(children->At(index)));
       
  1107 				if(KErrNone != leave)
       
  1108 					{
       
  1109 					delete children;
       
  1110 					return leave;
       
  1111 					}
       
  1112 				}
       
  1113 			delete children;	
       
  1114 			++iOrigEntryPos;
       
  1115 			}
       
  1116 		}
       
  1117 	return error;
       
  1118 	}
       
  1119 
       
  1120 
       
  1121 
       
  1122 
       
  1123 
       
  1124 /**
       
  1125  * DoExpandSelectionRecursivelyL
       
  1126  * Expands a selection to include all the descendents of the entry with TMsvId aId. 
       
  1127  *
       
  1128  * @param aId TMsvId of the entire
       
  1129  * @return void
       
  1130  */
       
  1131 void CMsvIndexAdapter::DoExpandSelectionRecursivelyL(TMsvId aId)
       
  1132 	{
       
  1133 	// include this entry
       
  1134 	iRecursionSelection->InsertL(iRecursionIndex,aId);
       
  1135 	iOrigEntryPos++;
       
  1136 	
       
  1137 	// if aEntry has children
       
  1138 	CMsvEntrySelection* children = new (ELeave)CMsvEntrySelection;
       
  1139 	CleanupStack::PushL(children);
       
  1140 	
       
  1141 	GetChildrenIdL(aId, *children);
       
  1142 	
       
  1143 	TInt count = children->Count();
       
  1144 	for(TInt index=0; index<count; ++index)
       
  1145 		{
       
  1146 		DoExpandSelectionRecursivelyL(children->At(index));
       
  1147 		}
       
  1148 	
       
  1149 	CleanupStack::PopAndDestroy(1, children);	//children
       
  1150 	}
       
  1151 
       
  1152 
       
  1153 
       
  1154 /**
       
  1155  * GetChildrenId()
       
  1156  * @param TMsvId: Id os the parent.
       
  1157  * @param CMsvEntrySelection: List of child Ids.
       
  1158  * 
       
  1159  * This function should be used only by ExpandSelectionRecursively()
       
  1160  * and DoExpandSelectionRecursivelyL().
       
  1161  * --- 557 ---
       
  1162  * If aId is an standard id ensure that it is masked. If the aId is
       
  1163  * not masked the function will return children from current drive.
       
  1164  */
       
  1165 void CMsvIndexAdapter::GetChildrenIdL(TMsvId aId, CMsvEntrySelection& aSelection)
       
  1166 	{
       
  1167 	CMsvCacheVisibleFolder* folderNode = NULL;	
       
  1168 	TDblQueIter<CMsvCacheVisibleFolder> dqIter(iFolderListHeader);
       
  1169 
       
  1170 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1171 	if(IsStandardId(aId))
       
  1172 		{
       
  1173 		TUint driveId = GetDriveId(aId);
       
  1174 		TMsvId unmaskedId = UnmaskTMsvId(aId);
       
  1175 		
       
  1176 		dqIter.SetToFirst();	
       
  1177 		// Look for the entry in cache.
       
  1178 		if(!iFolderListHeader.IsEmpty())
       
  1179 			{
       
  1180 			while(NULL != (folderNode = dqIter++))
       
  1181 				{
       
  1182 				if((unmaskedId == folderNode->GetFolderId()) && (driveId == folderNode->GetDrive()))
       
  1183 					{
       
  1184 					if(!folderNode->GetChildrenIdL(aSelection))
       
  1185 						{
       
  1186 						if(iDbAdapter)
       
  1187 							{
       
  1188 							iDbAdapter->GetChildrenIdL(aId, aSelection);
       
  1189 							}
       
  1190 						else
       
  1191 							{
       
  1192 							User::Leave(ErrorState());
       
  1193 							}
       
  1194 						}
       
  1195 					return;
       
  1196 					}
       
  1197 				}
       
  1198 			}
       
  1199 		if(iDbAdapter)
       
  1200 			{
       
  1201 			iDbAdapter->GetChildrenIdL(aId, aSelection);
       
  1202 			}
       
  1203 		else
       
  1204 			{
       
  1205 			User::Leave(ErrorState());
       
  1206 			}
       
  1207 		return;
       
  1208 		}
       
  1209 #endif		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1210 
       
  1211 	dqIter.SetToFirst();	
       
  1212 	// Look for the entry in cache.
       
  1213 	if(!iFolderListHeader.IsEmpty())
       
  1214 		{
       
  1215 		// Check if aId is one of the visible folder,
       
  1216 		// already present in the cache.
       
  1217 		while(NULL != (folderNode = dqIter++))
       
  1218 			{
       
  1219 			if(aId == folderNode->GetFolderId())
       
  1220 				{
       
  1221 				// Fetch children. Returns EFalse if unable
       
  1222 				// to get them.
       
  1223 				if(!folderNode->GetChildrenIdL(aSelection))
       
  1224 					{
       
  1225 					if(iDbAdapter)
       
  1226 						{
       
  1227 						// Childrens not fetched. Get them from DB.
       
  1228 						iDbAdapter->GetChildrenIdL(aId, aSelection);
       
  1229 						}
       
  1230 					else
       
  1231 						{
       
  1232 						User::Leave(ErrorState());	
       
  1233 						}
       
  1234 					}
       
  1235 				return;
       
  1236 				}
       
  1237 			}
       
  1238 
       
  1239 		// Entry is not present in the visibleFolder list.
       
  1240 		CMsvCacheEntry* entry = NULL;
       
  1241 		if(FindEntryInCache(aId, entry))
       
  1242 			{
       
  1243 			if(NULL != entry->ChildIdArray())
       
  1244 				{
       
  1245 				RArray<TMsvId>* childId = entry->ChildIdArray();
       
  1246 				TInt size = childId->Count();
       
  1247 				TInt index = 0;
       
  1248 				while(index < size)
       
  1249 					{
       
  1250 					aSelection.AppendL((*childId)[index++]);
       
  1251 					}
       
  1252 				return;	
       
  1253 				}
       
  1254 			else
       
  1255 				{
       
  1256 				if(iDbAdapter)
       
  1257 					{
       
  1258 					iDbAdapter->GetChildrenIdL(aId, aSelection);
       
  1259 					}
       
  1260 				else
       
  1261 					{
       
  1262 					User::Leave(ErrorState());	
       
  1263 					}
       
  1264 				RArray<TMsvId>* childId = new(ELeave) RArray<TMsvId>;
       
  1265 				TInt size = aSelection.Count();
       
  1266 				TInt index = 0;
       
  1267 				while(index < size)
       
  1268 					{
       
  1269 					TInt err = childId->Append(aSelection[index++]);
       
  1270 					if(KErrNone != err)
       
  1271 						{
       
  1272 						childId->Reset();
       
  1273 						childId->Close();
       
  1274 						delete childId;
       
  1275 						User::Leave(err);
       
  1276 						}
       
  1277 					}
       
  1278 				entry->SetChildIdArray(childId);
       
  1279 				return;
       
  1280 				}
       
  1281 			}
       
  1282 		}
       
  1283 	
       
  1284 	// Could not find parent entry in cache.
       
  1285 	// Check in DB now.	
       
  1286 	if(iDbAdapter)
       
  1287 		{
       
  1288 		iDbAdapter->GetChildrenIdL(aId, aSelection);
       
  1289 		}
       
  1290 	else
       
  1291 		{
       
  1292 		User::Leave(ErrorState());	
       
  1293 		}
       
  1294 	}
       
  1295 
       
  1296 
       
  1297 
       
  1298 
       
  1299 /**
       
  1300  * ChangeEntry
       
  1301  * Change the contents of a TMsvEntry. 
       
  1302  * 
       
  1303  */
       
  1304 TInt CMsvIndexAdapter::ChangeEntry(const TMsvEntry& aEntry, TSecureId aOwnerId, TBool aForcedUpdate)
       
  1305 	{
       
  1306 	TRAPD(err, DoChangeEntryL(aEntry, aOwnerId, EFalse, aForcedUpdate, ETrue));
       
  1307 	return err;
       
  1308 	}
       
  1309 
       
  1310 
       
  1311 /**
       
  1312  * ChangeEntryNoCommit
       
  1313  */
       
  1314 TInt CMsvIndexAdapter::ChangeEntryNoCommit(const TMsvEntry& aEntry, TSecureId aOwnerId, TBool aForcedUpdate)
       
  1315 	{
       
  1316 	if(!iDbAdapter)
       
  1317 		{
       
  1318 		return ErrorState();
       
  1319 		}
       
  1320 	
       
  1321 	TRAP_IGNORE(iDbAdapter->BeginTransactionL());
       
  1322 	TRAPD(err, DoChangeEntryL(aEntry, aOwnerId, EFalse, aForcedUpdate, EFalse));
       
  1323 	if(err)
       
  1324 		{
       
  1325 		RollbackChanges();
       
  1326 		}
       
  1327 	return err;
       
  1328 	}
       
  1329 	
       
  1330 
       
  1331 /**
       
  1332  * ChangeEntryInternal()
       
  1333  */
       
  1334 TInt CMsvIndexAdapter::ChangeEntryInternal(const TMsvEntry& aEntry, TSecureId aOwnerId)
       
  1335 	{
       
  1336 	TRAPD(err, DoChangeEntryL(aEntry, aOwnerId, ETrue, EFalse, ETrue));
       
  1337 	return err;
       
  1338 	}
       
  1339 
       
  1340 
       
  1341 
       
  1342 /**
       
  1343  * DoChangeEntryL
       
  1344  */	
       
  1345 void CMsvIndexAdapter::DoChangeEntryL(const TMsvEntry& aNewEntryContents, TSecureId aOwnerId, TBool aChangeStandardFolder, TBool aForcedUpdate, TBool aCommitToFile)
       
  1346     {
       
  1347     // Leave if the message store is not currently available
       
  1348     User::LeaveIfError(iErrorState);
       
  1349 
       
  1350     // 1. Handle root entry differently.
       
  1351     if(aNewEntryContents.Id() == KMsvRootIndexEntryId)
       
  1352         {
       
  1353         TMsvEntry& entry = const_cast<TMsvEntry&> (aNewEntryContents);
       
  1354         iDbAdapter->UpdateEntryL(entry, KMsvRootIndexEntryId, EFalse);
       
  1355         iRootEntry->Entry() = entry;
       
  1356         return;
       
  1357         }
       
  1358 
       
  1359     // 2. Find entry in cache.
       
  1360     CMsvCacheEntry* oldEntry = NULL;    
       
  1361     CMsvCacheVisibleFolder* oldFolderNode = NULL;
       
  1362     GetVisibleFolderDetailsL(aNewEntryContents.Id(), oldEntry, oldFolderNode);
       
  1363   
       
  1364     // 3. Validate entry.
       
  1365     // If the entry is not present in cache, it means it is not locked.
       
  1366     // Can only change a locked entry and not one marked as a standard 
       
  1367     // folder unless aChangeStandardFolder is true.
       
  1368     if( (!oldEntry->IsEntryLocked()) || (aChangeStandardFolder==EFalse && oldEntry->Entry().StandardFolder()) )
       
  1369         {
       
  1370         User::Leave(KErrAccessDenied);
       
  1371         }
       
  1372 
       
  1373     // Reserving space in changed entry list array.
       
  1374     if(!aCommitToFile)
       
  1375         {
       
  1376         iNonCommittedChangedEntryList.ReserveL(iNonCommittedChangedEntryList.Count()+1);
       
  1377         }
       
  1378 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1379     // We do not support movement of entry to a folder present in a different drive.    
       
  1380     if( oldEntry->Entry().Parent() != KErrNotFound &&   //-1 will appear to be masked. disregard this.
       
  1381         GetDriveId(aNewEntryContents.Id()) != GetDriveId(oldEntry->Entry().Parent()))
       
  1382         {
       
  1383         User::Leave(KErrNotSupported);  
       
  1384         }
       
  1385 #endif
       
  1386 
       
  1387     TMsvId oldParentId = oldEntry->Entry().Parent();
       
  1388     TMsvId oldVisibleFolderId = oldFolderNode->GetFolderId();
       
  1389 
       
  1390     // Check if the parent id is also changed.
       
  1391     CMsvCacheEntry* oldParentEntry = NULL;
       
  1392     CMsvCacheEntry* newParentEntry = NULL;
       
  1393     TBool resetOldParentOwnerFlag = EFalse;
       
  1394     CMsvEntrySelection* descendentList = NULL;
       
  1395     TMsvId newParentId = aNewEntryContents.Parent();
       
  1396     CMsvCacheVisibleFolder* newVisibleFolderNode = NULL;
       
  1397     if(oldParentId != newParentId)
       
  1398         {
       
  1399         // YES, PARENT ID IS CHANGED.
       
  1400         // These steps are similar to MoveEntry()
       
  1401         newVisibleFolderNode = DoChangeEntryPreambleL(oldEntry,
       
  1402                                                       newParentId,
       
  1403                                                       oldParentEntry,
       
  1404                                                       newParentEntry,
       
  1405                                                       oldVisibleFolderId,
       
  1406                                                       resetOldParentOwnerFlag,
       
  1407                                                       descendentList
       
  1408                                                      );
       
  1409         }   // if(oldParentId != newParentId)
       
  1410     TMsvId newVisibleFolderId = newVisibleFolderNode ? newVisibleFolderNode->GetFolderId() : oldVisibleFolderId;
       
  1411     // Update entry in cache.
       
  1412     TBool changedPrivateInfo;
       
  1413     CMsvCacheEntry* bkpEntry = NULL;
       
  1414     TRAPD(err, bkpEntry = iFreePoolInstance->EntryL();
       
  1415                bkpEntry->SetEntryL(oldEntry->Entry());
       
  1416                bkpEntry->SetEntryOwnerId(oldEntry->EntryOwnerId());
       
  1417                oldEntry->CopyEntryL(aNewEntryContents, changedPrivateInfo);
       
  1418          );
       
  1419     if(err)
       
  1420         {
       
  1421         iFreePoolInstance->ReleaseEntryWithoutTransaction(bkpEntry);
       
  1422         if(newVisibleFolderNode)
       
  1423             newVisibleFolderNode->DeleteEntryL(oldEntry->GetId());
       
  1424         User::Leave(err);
       
  1425         }
       
  1426  
       
  1427 	UpdateDates(*oldEntry, EFalse);
       
  1428 	if(aForcedUpdate || changedPrivateInfo && aOwnerId != KMsvServerId )
       
  1429         {
       
  1430         oldEntry->SetEntryOwnerId(aOwnerId);
       
  1431         }
       
  1432 
       
  1433     TRAP(err, 
       
  1434             if(aCommitToFile)
       
  1435                 iDbAdapter->BeginTransactionL();
       
  1436             // Update the actual entry
       
  1437             if(oldParentId != newParentId)
       
  1438                 {
       
  1439                 iDbAdapter->UpdateEntryL(oldEntry->Entry(), newVisibleFolderId);
       
  1440                 }
       
  1441             else
       
  1442                 {
       
  1443                 iDbAdapter->UpdateEntryL(oldEntry->Entry(), newVisibleFolderId, EFalse);
       
  1444                 }
       
  1445             // Reset old parent owner flag.
       
  1446             if(resetOldParentOwnerFlag)
       
  1447                 iDbAdapter->UpdateOwnerStatusL(oldParentId, oldParentEntry->Entry(), EFalse);
       
  1448             // Set new parent owner flag.
       
  1449             if(newParentEntry && (!newParentEntry->Entry().Owner()))
       
  1450                 iDbAdapter->UpdateOwnerStatusL(newParentId, newParentEntry->Entry(), ETrue);
       
  1451             // Update the child entries visibleFolderId in DB.
       
  1452             if(descendentList)
       
  1453                 iDbAdapter->UpdateVisibleFolderL(descendentList, newVisibleFolderId);
       
  1454             if(aCommitToFile)
       
  1455                 iDbAdapter->CommitTransactionL();
       
  1456          );
       
  1457     if(err)
       
  1458         {
       
  1459         if(aCommitToFile)
       
  1460             TRAP_IGNORE(iDbAdapter->RollbackTransactionL());
       
  1461         oldEntry->SetEntryOwnerId(bkpEntry->EntryOwnerId());
       
  1462         oldEntry->CopyEntryL(bkpEntry->Entry(), changedPrivateInfo);
       
  1463         iFreePoolInstance->ReleaseEntryWithoutTransaction(bkpEntry);
       
  1464         if(newVisibleFolderNode)    
       
  1465             newVisibleFolderNode->DeleteEntryL(oldEntry->GetId());
       
  1466         User::Leave(err);
       
  1467         }
       
  1468     // Nothing should fail after this. Ensure that 
       
  1469     // all leaving function after this does not leave.
       
  1470     if(aCommitToFile)
       
  1471         {
       
  1472         iFreePoolInstance->ReleaseEntryWithoutTransaction(bkpEntry);
       
  1473         DoChangeEntryPostamble(oldFolderNode, newVisibleFolderId, oldEntry->GetId(), descendentList, newParentEntry, oldParentEntry, resetOldParentOwnerFlag);
       
  1474         if(descendentList)
       
  1475             {
       
  1476             CleanupStack::PopAndDestroy(descendentList);
       
  1477             }
       
  1478         }   // if(aCommitToFile)
       
  1479     else
       
  1480         {
       
  1481         // Store relevant data for later commit.
       
  1482         TNonCommittedChangedEntries entryDetails(oldFolderNode, 
       
  1483                                                  newVisibleFolderNode, 
       
  1484                                                  oldEntry,
       
  1485                                                  bkpEntry,
       
  1486                                                  oldParentEntry, 
       
  1487                                                  newParentEntry,
       
  1488                                                  descendentList,
       
  1489                                                  resetOldParentOwnerFlag);
       
  1490         iNonCommittedChangedEntryList.Append(entryDetails);
       
  1491         if(descendentList)
       
  1492             CleanupStack::Pop(descendentList);
       
  1493         }
       
  1494 
       
  1495     // Update entry in SearchSort delta cache.
       
  1496     if(aNewEntryContents.iType.iUid == KUidMsvMessageEntryValue && CMSvSearchSortCacheManager::Instance()->iManagerEntry != NULL)
       
  1497         {
       
  1498         TMsgType aType(EUpdatedMsg);
       
  1499         if(CMSvSearchSortCacheManager::Instance()->iManagerEntry->Count()>0)
       
  1500             {
       
  1501             CMsvSearchSortDeltaCache::Instance()->EntryInDeltaCache(aNewEntryContents.Id(), aType);
       
  1502             }
       
  1503         }
       
  1504     }
       
  1505 
       
  1506 
       
  1507 
       
  1508 // Used only by DoChangeEntryL()
       
  1509 CMsvCacheVisibleFolder* CMsvIndexAdapter::DoChangeEntryPreambleL(CMsvCacheEntry*& aOldEntry, TMsvId aNewParentId, CMsvCacheEntry*& aOldParentEntry, CMsvCacheEntry*& aNewParentEntry, TMsvId aOldVisibleFolderId, TBool& aResetOldParentOwnerFlag, CMsvEntrySelection*& aDescendentList)
       
  1510     {
       
  1511     // YES, PARENT ID IS CHANGED.
       
  1512     // These steps are similar to MoveEntry()
       
  1513     TBool des;
       
  1514     IsADescendent(aOldEntry->Entry().Id(), aNewParentId, des);
       
  1515     if (des)
       
  1516         {
       
  1517         User::Leave(KErrArgument);
       
  1518         }
       
  1519    
       
  1520     // Fetch the parent entries.    
       
  1521     FindEntryL(aOldEntry->Entry().Parent(), aOldParentEntry);
       
  1522     FindEntryL(aNewParentId, aNewParentEntry);
       
  1523 
       
  1524     // Check if the owner flag of the old parent needs to be reset.    
       
  1525     CMsvEntrySelection* children = new(ELeave)CMsvEntrySelection;
       
  1526     CleanupStack::PushL(children);
       
  1527     GetChildrenIdL(aOldEntry->Entry().Parent(), *children);
       
  1528     if(1 == children->Count() && aOldParentEntry->Entry().Owner())
       
  1529         {
       
  1530         aResetOldParentOwnerFlag = ETrue;
       
  1531         }
       
  1532     CleanupStack::PopAndDestroy(); //children
       
  1533     
       
  1534     // If required, pre-allocate memory for child array of newParentEntry.
       
  1535     if(aNewParentEntry->ChildIdArray())
       
  1536         {
       
  1537         // This to ensure that future append does not fail.
       
  1538         aNewParentEntry->ChildIdArray()->ReserveL(aNewParentEntry->ChildIdArray()->Count() + 1);
       
  1539         }
       
  1540 
       
  1541     // Find the visibleFolder of new parent. 
       
  1542     TMsvId newVisibleFolderId = NULL;
       
  1543     if(!GetVisibleFolderId(aNewParentId, newVisibleFolderId))
       
  1544          {
       
  1545          User::Leave(KErrNotFound);
       
  1546          }
       
  1547 
       
  1548     // Check if the visible folders are different.
       
  1549     CMsvCacheVisibleFolder* newVisibleFolderNode = NULL;
       
  1550     if(aOldVisibleFolderId != newVisibleFolderId)
       
  1551         {
       
  1552         // If the visible folders are different, check if
       
  1553         // child entries also needs to be moved.
       
  1554         if(!aOldEntry->Entry().VisibleFolderFlag())
       
  1555             {
       
  1556             // If yes, create a descendent list of the entry.
       
  1557             aDescendentList = new(ELeave) CMsvEntrySelection;
       
  1558             CleanupStack::PushL(aDescendentList);
       
  1559             aDescendentList->AppendL(aOldEntry->GetId());
       
  1560             User::LeaveIfError(ExpandSelectionRecursively(*aDescendentList));
       
  1561             }
       
  1562         
       
  1563         // Add duplicate entry under new visible folder. Removing 
       
  1564         // entry from old visible folder is done later.
       
  1565         CMsvCacheEntry* newCacheEntry = iFreePoolInstance->EntryL();
       
  1566         TRAPD(err, newCacheEntry->DupNDestroyL(aOldEntry);
       
  1567                    newVisibleFolderNode = AddEntryToCacheL(newVisibleFolderId, newCacheEntry);
       
  1568              );
       
  1569         if(err)
       
  1570             {
       
  1571             iFreePoolInstance->ReleaseEntryWithoutTransaction(newCacheEntry);
       
  1572             User::Leave(err);
       
  1573             }
       
  1574         aOldEntry = newCacheEntry;
       
  1575         }   // if(oldVisibleFolderId != newVisibleFolderId)    }
       
  1576     return newVisibleFolderNode;
       
  1577     }
       
  1578 
       
  1579 
       
  1580 
       
  1581 // Used only by DoChangeEntryL()
       
  1582 void CMsvIndexAdapter::DoChangeEntryPostamble(CMsvCacheVisibleFolder* aOldFolderNode, TMsvId aNewVisibleFolderId, TMsvId aEntryId, CMsvEntrySelection* aDescendentList, CMsvCacheEntry* aNewParentEntry, CMsvCacheEntry* aOldParentEntry, TBool aResetOldParentOwnerFlag)
       
  1583     {
       
  1584      // Removing entry from old visible folder.
       
  1585      if(aOldFolderNode->GetFolderId() != aNewVisibleFolderId)
       
  1586          {
       
  1587          // Will never leave.
       
  1588          //aOldFolderNode->DeleteEntryL(oldEntry->GetId());
       
  1589          TRAP_IGNORE(aOldFolderNode->DeleteEntryL(aEntryId));
       
  1590          }
       
  1591      
       
  1592      // Removing child entries from old visible folder.
       
  1593      if(aDescendentList)
       
  1594          {
       
  1595          for(TInt index=(aDescendentList->Count()-2); index>=0; index--)
       
  1596              {
       
  1597              // Can leave with KErrNotFound.
       
  1598              TRAP_IGNORE(aOldFolderNode->DeleteEntryL(aDescendentList->At(index)));
       
  1599              }         
       
  1600          }
       
  1601     
       
  1602      // Add child id to new parent child array.
       
  1603      if(aNewParentEntry && aNewParentEntry->ChildIdArray())
       
  1604          {
       
  1605          // This will not leave, as memory is already reserved.
       
  1606          TRAP_IGNORE(aNewParentEntry->ChildIdArray()->AppendL(aEntryId));
       
  1607          }
       
  1608      
       
  1609      // Remove child from old parent's child array.
       
  1610      if(aOldParentEntry)
       
  1611          {
       
  1612          RArray<TMsvId>* oldParentChildArr = aOldParentEntry->ChildIdArray();
       
  1613          if(oldParentChildArr)
       
  1614              {
       
  1615              TInt pos = oldParentChildArr->Find(aEntryId);
       
  1616              if(pos != KErrNotFound)
       
  1617                  {
       
  1618                  oldParentChildArr->Remove(pos);
       
  1619                  }
       
  1620              }
       
  1621          }
       
  1622     
       
  1623      // Update owner flag of parent entries.
       
  1624      if(aResetOldParentOwnerFlag)
       
  1625          {
       
  1626          aOldParentEntry->Entry().SetOwner(EFalse);
       
  1627          }
       
  1628      if(aNewParentEntry)
       
  1629          {
       
  1630          aNewParentEntry->Entry().SetOwner(ETrue);
       
  1631          }
       
  1632  }
       
  1633  
       
  1634  
       
  1635  
       
  1636  
       
  1637 /**
       
  1638  * GetEntry()
       
  1639  */
       
  1640 TInt CMsvIndexAdapter::GetEntry(TMsvId aId, TMsvEntry*& aEntry) 
       
  1641 	{
       
  1642 	TSecureId dummy;
       
  1643 	return GetEntry(aId, aEntry, dummy);
       
  1644 	}
       
  1645 
       
  1646 
       
  1647 
       
  1648 /**
       
  1649  * GetEntryNoCache()
       
  1650  * If aAddToCache is EFalse, entry will not be added to cache,
       
  1651  * if the entry is fetched from DB. The user of this function
       
  1652  * should ensure that it releses the memory occupied by entry
       
  1653  * to the freepool.
       
  1654  */
       
  1655 TInt CMsvIndexAdapter::GetEntryNoCache(TMsvId aId, TMsvEntry* aEntry)
       
  1656 	{
       
  1657 	if(KMsvRootIndexEntryId == aId)
       
  1658 		{
       
  1659 		*aEntry = iRootEntry->Entry();				
       
  1660 		return KErrNone;
       
  1661 		}
       
  1662 
       
  1663 	TBool aIsDanglingEntry = EFalse;
       
  1664 	CMsvCacheEntry* serverEntry=NULL;
       
  1665 	TRAPD(err, aIsDanglingEntry = FindEntryL(aId, serverEntry, EFalse));
       
  1666 
       
  1667 	if (err == KErrNone)
       
  1668 		{
       
  1669 		*aEntry = serverEntry->Entry();
       
  1670 		// If entry is not present in cache,
       
  1671 		// it should be handled carefully.
       
  1672 		if(aIsDanglingEntry)
       
  1673 			{
       
  1674 			// Release CMsvCacheEntry to freepool.
       
  1675 			iFreePoolInstance->ReleaseEntry(serverEntry, ETrue);
       
  1676 			}		
       
  1677 		return KErrNone;	
       
  1678 		}
       
  1679 	else
       
  1680 		{
       
  1681 		return KErrNotFound;
       
  1682 		}
       
  1683 	}
       
  1684 
       
  1685 
       
  1686 
       
  1687 	
       
  1688 /**
       
  1689  * GetEntry()
       
  1690  */
       
  1691 TInt CMsvIndexAdapter::GetEntry(TMsvId aId, TMsvEntry*& aEntry, TSecureId& aOwnerId) 
       
  1692 	{
       
  1693 	if(KMsvRootIndexEntryId == aId)
       
  1694 		{
       
  1695 		aEntry = &iRootEntry->Entry();
       
  1696 		aOwnerId = 0;
       
  1697 		return KErrNone;
       
  1698 		}
       
  1699 
       
  1700 	CMsvCacheEntry* serverEntry=NULL;
       
  1701 	TRAPD(err, FindEntryL(aId, serverEntry));	
       
  1702 
       
  1703 	if (err == KErrNone)
       
  1704 		{
       
  1705 		aEntry = &serverEntry->Entry();
       
  1706 		aOwnerId = serverEntry->EntryOwnerId();
       
  1707 		return KErrNone;	
       
  1708 		}
       
  1709 	else
       
  1710 		{
       
  1711 		return KErrNotFound;
       
  1712 		}
       
  1713 	}
       
  1714 	
       
  1715 
       
  1716 
       
  1717 /**
       
  1718  * FindEntryInCache()
       
  1719  * @param aId: Entry Id.
       
  1720  * @return aEntry: CMsvCacheEntry
       
  1721  * @return bool: ETrue if entry found, otherwise EFalse.
       
  1722  * 
       
  1723  * Find an entry only in cache and return the entry.
       
  1724  */
       
  1725 TBool CMsvIndexAdapter::FindEntryInCache(TMsvId aId, CMsvCacheEntry*& aEntry) 
       
  1726 	{
       
  1727 	if(KMsvRootIndexEntryId == aId)
       
  1728 		{
       
  1729 		aEntry = iRootEntry;
       
  1730 		return ETrue;
       
  1731 		}
       
  1732 
       
  1733 	// If cache is not empty.
       
  1734 	if(!iFolderListHeader.IsEmpty())
       
  1735 		{
       
  1736 		CMsvCacheVisibleFolder* folderNode = NULL;
       
  1737 		TDblQueIter<CMsvCacheVisibleFolder> dqIter(iFolderListHeader);
       
  1738 		dqIter.SetToFirst(); 
       
  1739 		
       
  1740 		while((folderNode = dqIter++)!=NULL)
       
  1741 			{
       
  1742 			if(folderNode->GetEntry(aId, aEntry))
       
  1743 				{
       
  1744 				return ETrue;
       
  1745 				}
       
  1746 			}
       
  1747 		}
       
  1748 	aEntry = NULL;
       
  1749 	return EFalse;
       
  1750 	}
       
  1751 
       
  1752 
       
  1753 
       
  1754 /**
       
  1755  * FindEntryL()
       
  1756  * 
       
  1757  * WARNING:
       
  1758  * Returns CMsvCacheEntry which is still owned by Cache. so aEntry should
       
  1759  * never be deleted by the caller.
       
  1760  *
       
  1761  * If the entry is fetched from DB and not added to cache, the function 
       
  1762  * returns ETrue, indicating that aEntry should be release to the freepool
       
  1763  * by the caller.
       
  1764  */
       
  1765 TBool CMsvIndexAdapter::FindEntryL(TMsvId aId, CMsvCacheEntry*& aEntry, TBool aAddToCache /*DEFAULT=ETrue */)
       
  1766 	{
       
  1767 	// First search the entry in cache, 
       
  1768 	if(FindEntryInCache(aId, aEntry))
       
  1769 		{
       
  1770 		return EFalse;
       
  1771 		}	
       
  1772 
       
  1773 	// Entry cannot be found in cache,
       
  1774 	// Now search in DB.
       
  1775 	TMsvId visibleEntryId;
       
  1776 	if(iDbAdapter)
       
  1777 		{
       
  1778 		iDbAdapter->GetEntryL(aId, aEntry, visibleEntryId);
       
  1779 		}
       
  1780 	else
       
  1781 		{
       
  1782 		User::Leave(ErrorState());	
       
  1783 		}
       
  1784 
       
  1785 	if(aAddToCache)	
       
  1786 		{
       
  1787 		// Add entry to cache.
       
  1788 		AddEntryToCacheL(visibleEntryId, aEntry);	
       
  1789 		}
       
  1790 	else
       
  1791 		{
       
  1792 		// If the entry is not added to cache, we need not start 
       
  1793 		// the background operation. We can return ETrue saying
       
  1794 		// entry is dangling and needs to be freed.
       
  1795 		return ETrue;
       
  1796 		}
       
  1797 	if (!iIdle->IsActive())
       
  1798 		{
       
  1799 		iIdle->Start(TCallBack(BackGroundOperations, this));
       
  1800 		}
       
  1801 	return EFalse;
       
  1802 	}
       
  1803 
       
  1804 
       
  1805 
       
  1806 
       
  1807 /**
       
  1808  * AddEntryNoVisibleL()
       
  1809  */
       
  1810 void CMsvIndexAdapter::AddEntryNoVisibleL(CMsvCacheEntry* aEntry)
       
  1811 	{
       
  1812 	TMsvId visibleFolder;
       
  1813 	if(GetVisibleFolderId(aEntry->Entry().Parent(), visibleFolder))	
       
  1814 		{
       
  1815 		AddEntryToCacheL(visibleFolder, aEntry);
       
  1816 		}
       
  1817 	}
       
  1818 
       
  1819 
       
  1820 
       
  1821 /**
       
  1822  * AddEntryToCacheL()
       
  1823  */
       
  1824 CMsvCacheVisibleFolder* CMsvIndexAdapter::AddEntryToCacheL(TMsvId aVisibleEntryId, CMsvCacheEntry* aEntry)
       
  1825 	{
       
  1826 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1827 	TUint driveId = GetDriveId(aEntry->GetId());
       
  1828 	if(IsStandardId(aEntry->GetId()))
       
  1829 		{
       
  1830 		aEntry->Entry().SetId(UnmaskTMsvId(aEntry->GetId()));
       
  1831 		}
       
  1832 #endif
       
  1833 	// First search the visibleEntry in cache, 
       
  1834 	// if cache is not empty...
       
  1835 	if(!iFolderListHeader.IsEmpty())
       
  1836 		{
       
  1837 		CMsvCacheVisibleFolder* folderNode = NULL;
       
  1838 		TDblQueIter<CMsvCacheVisibleFolder> dqIter(iFolderListHeader);
       
  1839 		dqIter.SetToFirst();
       
  1840 		
       
  1841 		while((folderNode =  dqIter++)!=NULL)
       
  1842 			{
       
  1843 			TMsvId folderId = folderNode->GetFolderId();
       
  1844 			if(aVisibleEntryId == folderId)
       
  1845 				{
       
  1846 				// Visible folder exists.
       
  1847 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1848 				// For standard entries also check for driveId.
       
  1849 				if(IsStandardId(aVisibleEntryId))
       
  1850 					{
       
  1851 					if(driveId == folderNode->GetDrive())
       
  1852 						{
       
  1853 						folderNode->AddEntryL(aEntry);
       
  1854 						return folderNode;
       
  1855 						}
       
  1856 					}
       
  1857 				else
       
  1858 #endif
       
  1859 					{
       
  1860 					// Add entry to this folder.
       
  1861 					folderNode->AddEntryL(aEntry);
       
  1862 					return folderNode;
       
  1863 					}
       
  1864 				}
       
  1865 			}
       
  1866 		}
       
  1867 
       
  1868 	// Visible folder not found in the folder list.
       
  1869 	// Create the visible folder and add it to the
       
  1870 	// beginning of the list.
       
  1871 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1872 	CMsvCacheVisibleFolder* newFolder = CMsvCacheVisibleFolder::NewL(MaskTMsvId(GetDriveId(aEntry->GetId()), aVisibleEntryId));
       
  1873 #else
       
  1874 	CMsvCacheVisibleFolder* newFolder = CMsvCacheVisibleFolder::NewL(aVisibleEntryId);
       
  1875 #endif
       
  1876 	iFolderListHeader.AddFirst(*newFolder);
       
  1877 	
       
  1878 	// Now add entry to the visible folder
       
  1879 	newFolder->AddEntryL(aEntry);
       
  1880 	return newFolder;
       
  1881 	}
       
  1882 	
       
  1883 
       
  1884 
       
  1885 /**
       
  1886  * GetChildrenL()
       
  1887  */
       
  1888 void CMsvIndexAdapter::GetChildrenL(TMsvId aId, CArrayPtr<const TMsvEntry>& aSelection, const TMsvSelectionOrdering& aOrdering, TUid aMtm)
       
  1889 	{
       
  1890 	TSecureId dummy = KMsvServerId.iId;
       
  1891 	GetChildrenL(aId, aSelection, aOrdering, aMtm, EFalse, dummy);
       
  1892 	}
       
  1893 
       
  1894 
       
  1895 	
       
  1896 /**
       
  1897  * GetChildrenL()
       
  1898  */
       
  1899 void CMsvIndexAdapter::GetChildrenL(TMsvId aId, CArrayPtr<const TMsvEntry>& aSelection, const TMsvSelectionOrdering& aOrdering, TUid aMtm, TBool aFilterByOwnerId, TSecureId aOwnerId)
       
  1900 	{
       
  1901 	CMsvEntryFilter* filter = CMsvEntryFilter::NewLC();
       
  1902 	filter->SetOrder(aOrdering);
       
  1903 	filter->SetSortMtm(aMtm);
       
  1904 	CMsvEntryArray* entries = DoGetChildrenL(aId, *filter, aFilterByOwnerId, aOwnerId);	
       
  1905 	CleanupStack::PushL(entries);	
       
  1906 	
       
  1907 	TInt count = entries->Count();
       
  1908 	for (TInt ii=0; ii<count; ii++)
       
  1909 		{
       
  1910 		aSelection.AppendL(entries->At(ii));
       
  1911 		}
       
  1912 	CleanupStack::PopAndDestroy(2, filter); // filter and entries
       
  1913 	}
       
  1914 
       
  1915 
       
  1916 
       
  1917 	
       
  1918 /**
       
  1919  * DoGetChildrenL
       
  1920  */	
       
  1921 CMsvEntryArray* CMsvIndexAdapter::DoGetChildrenL(TMsvId aId, const CMsvEntryFilter& aFilter, TBool aFilterByOwnerId, TSecureId aOwnerId)
       
  1922 	{
       
  1923 	// Check if entry for aId exists...
       
  1924 	CMsvCacheEntry* entry=NULL;
       
  1925 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1926 	TUint driveId = GetDriveId(aId);
       
  1927 	TMsvId unmaskedId = UnmaskTMsvId(aId);
       
  1928 	if(IsStandardId(aId))
       
  1929 		{		
       
  1930 		FindEntryL(unmaskedId, entry);
       
  1931 		}
       
  1932 	else
       
  1933 #endif
       
  1934 		{
       
  1935 		FindEntryL(aId, entry);
       
  1936 		}
       
  1937 
       
  1938 	TBool isParentAVisibleFolder = EFalse;
       
  1939 	if(entry->Entry().VisibleFolderFlag())
       
  1940 		{
       
  1941 		isParentAVisibleFolder = ETrue;
       
  1942 		}
       
  1943 
       
  1944 	CArrayFixFlat<TUid>* mtmList = new(ELeave) CArrayFixFlat<TUid>(KMsvMtmListGranularity);
       
  1945 	CleanupStack::PushL(mtmList);
       
  1946 	if (KUidMsvNullEntry != aFilter.SortMtm())
       
  1947 		{
       
  1948 		mtmList->AppendL(aFilter.SortMtm());
       
  1949 		}
       
  1950 
       
  1951 	RPointerArray<CMsvCacheEntry> selection;
       
  1952 	CleanupClosePushL(selection);
       
  1953 	
       
  1954 	CMsvCacheVisibleFolder* folderNode = NULL;	
       
  1955 	CMsvEntryArray* entries = CMsvEntryArray::NewLC(*mtmList);
       
  1956 	TDblQueIter<CMsvCacheVisibleFolder> dqIter(iFolderListHeader);
       
  1957 	
       
  1958 
       
  1959 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1960 
       
  1961 	if(IsStandardId(aId))
       
  1962 		{
       
  1963 		// Look for the entry in cache.
       
  1964 		if(!iFolderListHeader.IsEmpty())
       
  1965 			{
       
  1966 			dqIter.SetToFirst(); 
       
  1967 			// Check if aId is one of the visible folder,
       
  1968 			// already present in the cache.
       
  1969 			while(NULL != (folderNode = dqIter++))
       
  1970 				{
       
  1971 				if((folderNode->GetFolderId() == unmaskedId) && (folderNode->GetDrive() == driveId))
       
  1972 					{
       
  1973 					folderNode->GetChildrenL(aId, iDbAdapter, selection);
       
  1974 					FilterChildrenListL(aId, selection, *entries, aFilter, aFilterByOwnerId, aOwnerId);
       
  1975 					CleanupStack::Pop(entries);	// Fetch entries from stack. It will be destroyed by caller.
       
  1976 					CleanupStack::PopAndDestroy(2);
       
  1977 					return entries;
       
  1978 					}
       
  1979 				}
       
  1980 			}
       
  1981 		}
       
  1982 	else
       
  1983 		{				
       
  1984 #endif			// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1985 
       
  1986 	// Look for the entry in cache.
       
  1987 	if(!iFolderListHeader.IsEmpty())
       
  1988 		{
       
  1989 		dqIter.SetToFirst(); 
       
  1990 		// Check if aId is one of the visible folder,
       
  1991 		// already present in the cache.
       
  1992 		while(NULL != (folderNode = dqIter++))
       
  1993 			{
       
  1994 			if(aId == folderNode->GetFolderId())
       
  1995 				{
       
  1996 				if(iDbAdapter == NULL)
       
  1997 					{
       
  1998 					User::Leave(ErrorState());	
       
  1999 					}
       
  2000 				folderNode->GetChildrenL(aId, iDbAdapter, selection);
       
  2001 				FilterChildrenListL(aId, selection, *entries, aFilter, aFilterByOwnerId, aOwnerId);
       
  2002 				CleanupStack::Pop(entries);	// Fetch entries from stack. It will be destroyed by caller.
       
  2003 				CleanupStack::PopAndDestroy(2);
       
  2004 				return entries;
       
  2005 				}
       
  2006 			}
       
  2007 
       
  2008 		// If the parent is not a visible folder
       
  2009 		// check if it is child of one of the visible folder.
       
  2010 		if(EFalse == isParentAVisibleFolder)
       
  2011 			{
       
  2012 			dqIter.SetToFirst(); 
       
  2013 			while(NULL != (folderNode = dqIter++))
       
  2014 				{
       
  2015 				TBool retVal=EFalse;
       
  2016 				TRAPD(err, retVal = folderNode->GetChildrenL(aId, iDbAdapter, selection))
       
  2017 
       
  2018 				// aId not found under current visibleFolder.
       
  2019 				if(KErrNotFound == err)
       
  2020 					{
       
  2021 					continue;
       
  2022 					}
       
  2023 				
       
  2024 				// aId found under current visibleFolder.
       
  2025 				if(retVal)
       
  2026 					{
       
  2027 					// Children is fetched succesfully.
       
  2028 					FilterChildrenListL(aId, selection, *entries, aFilter, aFilterByOwnerId, aOwnerId);	
       
  2029 					CleanupStack::Pop(entries);  // Fetch entries from stack. It will be destroyed by caller.
       
  2030 					CleanupStack::PopAndDestroy(2);
       
  2031 					return entries;
       
  2032 					}
       
  2033 				else
       
  2034 					{
       
  2035 					// aId itself is a visibleFolder.
       
  2036 					isParentAVisibleFolder = ETrue;
       
  2037 					break;
       
  2038 					}
       
  2039 				}
       
  2040 			}
       
  2041 		}
       
  2042 
       
  2043 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  2044 		}
       
  2045 #endif			// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  2046 		
       
  2047 	// Could not find parent entry in cache.
       
  2048 	// Check in DB now.	
       
  2049 	TInt err = KErrNone;
       
  2050 	if(iDbAdapter)
       
  2051 		{
       
  2052 		TRAP(err, iDbAdapter->GetChildrenL(aId, selection));
       
  2053 		}
       
  2054 	else
       
  2055 		{
       
  2056 		User::Leave(ErrorState());	
       
  2057 		}
       
  2058 	if(err)
       
  2059 		{
       
  2060 		User::Leave(KErrNotFound);
       
  2061 		}
       
  2062 	FilterChildrenListL(aId, selection, *entries, aFilter, aFilterByOwnerId, aOwnerId);
       
  2063 	
       
  2064 	// Check if the entire entry list can be added to cache.
       
  2065 	// This is important in a situation when all childs of a 
       
  2066 	// folder cannot be accomodated in cache. In such scenario
       
  2067 	// only entries with higher TMsvId will be added to cache.
       
  2068 	TInt excessEntries = iFreePoolInstance->ExcessMemoryAllocated();
       
  2069 	TBool isCompleteChildren = ETrue;
       
  2070 	if(excessEntries)
       
  2071 		{
       
  2072 		isCompleteChildren = EFalse;
       
  2073 		}
       
  2074 	while(excessEntries)
       
  2075 		{
       
  2076 		if(selection.Count())
       
  2077 			{
       
  2078 			iFreePoolInstance->RecordExcessMemoryL(selection[0]);
       
  2079 			selection.Remove(0);
       
  2080 			}
       
  2081 		--excessEntries;
       
  2082 		}		
       
  2083 
       
  2084 	// Add children to cache.
       
  2085 	TMsvId visibleFolderId;
       
  2086 	if(!isParentAVisibleFolder)
       
  2087 		{
       
  2088 		if(!GetVisibleFolderId(aId, visibleFolderId))
       
  2089 			{
       
  2090 			User::Leave(KErrNotFound);
       
  2091 			}
       
  2092 		}
       
  2093 	else
       
  2094 		{
       
  2095 		visibleFolderId = aId;
       
  2096 		}
       
  2097 	
       
  2098 	TBool isEntryAdded = EFalse;		
       
  2099 	dqIter.SetToFirst();
       
  2100 	while((folderNode = dqIter++)!=NULL)
       
  2101 		{
       
  2102 		if(visibleFolderId == folderNode->GetFolderId())
       
  2103 			{
       
  2104 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  2105 			if(IsStandardId(visibleFolderId))
       
  2106 				{
       
  2107 				if(GetDriveId(aId) == folderNode->GetDrive())
       
  2108 					{
       
  2109 					isEntryAdded=ETrue;
       
  2110 					folderNode->AddEntryListL(selection, (isCompleteChildren && isParentAVisibleFolder));
       
  2111 					}
       
  2112 				}
       
  2113 			else
       
  2114 #endif
       
  2115 				{
       
  2116 				isEntryAdded=ETrue;
       
  2117 				folderNode->AddEntryListL(selection, (isCompleteChildren && isParentAVisibleFolder));
       
  2118 				}
       
  2119 			}
       
  2120 		}
       
  2121 	
       
  2122 	if(!isEntryAdded)
       
  2123 		{
       
  2124 		// If aId is the visibleFolder itself then pass
       
  2125 		// aIsCompleteChildOfFolder as ETrue.
       
  2126 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  2127 		// Standard Id can be unmasked.
       
  2128 		CMsvCacheVisibleFolder* newFolder = CMsvCacheVisibleFolder::NewL(MaskTMsvId(GetDriveId(aId), visibleFolderId));
       
  2129 #else
       
  2130 		CMsvCacheVisibleFolder* newFolder = CMsvCacheVisibleFolder::NewL(visibleFolderId);
       
  2131 #endif	
       
  2132 		iFolderListHeader.AddFirst(*newFolder);
       
  2133 		newFolder->AddEntryListL(selection, (isCompleteChildren && isParentAVisibleFolder));
       
  2134 		}
       
  2135 
       
  2136 	CleanupStack::Pop(entries);		// Fetch entries from stack. It will be destroyed by caller.
       
  2137 	CleanupStack::PopAndDestroy(2);
       
  2138 	
       
  2139 	//Start the background operations, if not running.
       
  2140 	if (!iIdle->IsActive())
       
  2141 		{
       
  2142 		iIdle->Start(TCallBack(BackGroundOperations, this));
       
  2143 		}
       
  2144 		
       
  2145 	return entries;
       
  2146 	}
       
  2147 
       
  2148 
       
  2149 
       
  2150 
       
  2151 /**
       
  2152  * GetChildrenId()
       
  2153  */
       
  2154 TInt CMsvIndexAdapter::GetChildrenId(TMsvId aId, const CMsvEntryFilter& aFilter, CMsvEntrySelection& aSelection)
       
  2155 	{
       
  2156 	TSecureId dummy = KMsvServerId.iId;
       
  2157 	return GetChildrenId(aId, aFilter, aSelection, EFalse, dummy);
       
  2158 	}
       
  2159 	
       
  2160 /**
       
  2161  * GetChildrenId()
       
  2162  */
       
  2163 TInt CMsvIndexAdapter::GetChildrenId(TMsvId aId, const CMsvEntryFilter& aFilter, CMsvEntrySelection& aSelection, TBool aFilterByOwnerId, TSecureId aOwnerId)
       
  2164 	{
       
  2165 	CMsvEntryArray* entries = NULL;
       
  2166 	TInt err = KErrNone;
       
  2167 	TRAP(err, entries=DoGetChildrenL(aId, aFilter, aFilterByOwnerId, aOwnerId));
       
  2168 	if(err)
       
  2169 		{
       
  2170 		delete entries;
       
  2171 		return err;
       
  2172 		}
       
  2173 
       
  2174 	TInt count = entries->Count();
       
  2175 	for(TInt i=0; i<count; ++i)
       
  2176 		{
       
  2177 		TRAP(err, aSelection.AppendL(entries->At(i)->Id()));
       
  2178 		}
       
  2179 	delete entries;
       
  2180 	return err;
       
  2181 	}
       
  2182 
       
  2183 
       
  2184 
       
  2185 /**
       
  2186  * FilterChildrenListL
       
  2187  */	
       
  2188 void CMsvIndexAdapter::FilterChildrenListL(TMsvId aId, RPointerArray<CMsvCacheEntry> aChacheEntry, CMsvEntryArray& aEntryArray, const CMsvEntryFilter& aFilter, TBool aFilterByOwnerId, TSecureId aOwnerId)
       
  2189 	{
       
  2190 	TBool getInvisibleEntries = aFilter.Order().ShowInvisibleEntries();
       
  2191 	TInt count = aChacheEntry.Count();
       
  2192 	for(TInt i=0; i<count; ++i)
       
  2193 		{
       
  2194 		TMsvEntry entry = aChacheEntry[i]->Entry();
       
  2195 		TBool vis = aChacheEntry[i]->Entry().Visible();
       
  2196 		if ((aChacheEntry[i]->Entry().Visible() || getInvisibleEntries) &&
       
  2197 			(aFilter.Service() == KMsvNullIndexEntryId || aChacheEntry[i]->Entry().iServiceId == aFilter.Service()) &&
       
  2198 			(aFilter.Mtm() == KNullUid || aChacheEntry[i]->Entry().iMtm == aFilter.Mtm()) &&
       
  2199 			(aFilter.Type() == KNullUid || aChacheEntry[i]->Entry().iType == aFilter.Type()) &&
       
  2200 			(aFilter.LastChangeDate().Int64() == 0 || aChacheEntry[i]->LastChangeDate() >= aFilter.LastChangeDate()))
       
  2201 			{
       
  2202 			// Add the entry if - 
       
  2203 			// 1. Not filtering by owner ID OR
       
  2204 			// 2. Filtering by owner ID, but entry owner ID matches OR
       
  2205 			// 3. Entry is a standard folder OR
       
  2206 			// 4. Entrt is a service entry.
       
  2207 			if( !aFilterByOwnerId || 
       
  2208 					aChacheEntry[i]->EntryOwnerId() == aOwnerId ||
       
  2209 					aChacheEntry[i]->Entry().StandardFolder() || 
       
  2210 					aChacheEntry[i]->Entry().iType == KUidMsvServiceEntry )
       
  2211 				{
       
  2212 				aEntryArray.AppendL(&aChacheEntry[i]->Entry());
       
  2213 				}
       
  2214 			}
       
  2215 		}
       
  2216 	
       
  2217 	if (aEntryArray.Count())
       
  2218 		{
       
  2219 		if (aId==KMsvRootIndexEntryId)
       
  2220 			{
       
  2221 			aEntryArray.SortL(TMsvSelectionOrdering(KMsvNoGrouping, aFilter.Order().Sorting()));	
       
  2222 			}
       
  2223 		else
       
  2224 			{
       
  2225 			aEntryArray.SortL(aFilter.Order());	
       
  2226 			}
       
  2227 		}	
       
  2228 	}
       
  2229 
       
  2230 
       
  2231 
       
  2232 
       
  2233 /** 
       
  2234  * LockEntry()
       
  2235  */
       
  2236 TInt CMsvIndexAdapter::LockEntry(TMsvId aId)
       
  2237 	{
       
  2238 	//__DEBUG_INVARIANT_ONEXIT;
       
  2239 	
       
  2240 	CMsvCacheEntry* entry = NULL;
       
  2241 	TRAPD(err, FindEntryL(aId, entry))
       
  2242 	if (err)
       
  2243 		{
       
  2244 		return KErrNotFound;
       
  2245 		}
       
  2246 	
       
  2247 	return entry->LockEntry();
       
  2248 	}
       
  2249 		
       
  2250 
       
  2251 
       
  2252 /**
       
  2253  * ReleaseEntry()
       
  2254  */
       
  2255 TInt CMsvIndexAdapter::ReleaseEntry(TMsvId aId)
       
  2256 	{
       
  2257 	//__DEBUG_INVARIANT_ONEXIT;
       
  2258 	
       
  2259 	CMsvCacheEntry* entry = NULL;
       
  2260 	if(FindEntryInCache(aId, entry))
       
  2261 		{
       
  2262 		entry->ReleaseEntry();
       
  2263 		return KErrNone;
       
  2264 		}
       
  2265 	else
       
  2266 		{
       
  2267 		return KErrNotFound;
       
  2268 		}
       
  2269 	}
       
  2270 	
       
  2271 	
       
  2272 
       
  2273 
       
  2274 /**
       
  2275  * IsEntryLocked()
       
  2276  */
       
  2277 TInt CMsvIndexAdapter::IsEntryLocked(TMsvId aId, TBool& aLocked)
       
  2278 	{
       
  2279 	CMsvCacheEntry* entry = NULL;
       
  2280 	TRAPD(err, FindEntryL(aId, entry));
       
  2281 	if(KErrNone != err)
       
  2282 		{
       
  2283 		aLocked = EFalse;
       
  2284 		return err;
       
  2285 		}
       
  2286 	
       
  2287 	aLocked = entry->IsEntryLocked();
       
  2288 	return KErrNone;
       
  2289 	}
       
  2290 	
       
  2291 	
       
  2292 
       
  2293 
       
  2294 
       
  2295 /**
       
  2296  * LockStore()
       
  2297  */
       
  2298 TInt CMsvIndexAdapter::LockStore(TMsvId aId)
       
  2299 	{
       
  2300 	//__DEBUG_INVARIANT_ONEXIT;
       
  2301 	CMsvCacheEntry* entry = NULL;
       
  2302 	TRAPD(err, FindEntryL(aId, entry));
       
  2303 	if (err)
       
  2304 		{
       
  2305 		return KErrNotFound;
       
  2306 		}
       
  2307 	
       
  2308 	return entry->LockStore();
       
  2309 	}
       
  2310 	
       
  2311 
       
  2312 
       
  2313 
       
  2314 /**
       
  2315  * ReleaseStore()
       
  2316  */
       
  2317 TInt CMsvIndexAdapter::ReleaseStore(TMsvId aId)
       
  2318 	{
       
  2319 	//__DEBUG_INVARIANT_ONEXIT;
       
  2320 	
       
  2321 	CMsvCacheEntry* entry = NULL;
       
  2322 	if(FindEntryInCache(aId, entry))
       
  2323 		{
       
  2324 		entry->ReleaseStore();
       
  2325 		return KErrNone;
       
  2326 		}
       
  2327 	else
       
  2328 		{
       
  2329 		return KErrNotFound;
       
  2330 		}
       
  2331 	}
       
  2332 	
       
  2333 
       
  2334 
       
  2335 
       
  2336 /**
       
  2337  * IsStoreLocked()
       
  2338  */
       
  2339 TInt CMsvIndexAdapter::IsStoreLocked(TMsvId aId, TBool& aLocked)
       
  2340 	{
       
  2341 	CMsvCacheEntry* entry = NULL;
       
  2342 	TRAPD(err, FindEntryL(aId, entry));
       
  2343 	if(KErrNone != err)
       
  2344 		{
       
  2345 		aLocked = EFalse;
       
  2346 		return err;
       
  2347 		}
       
  2348 	aLocked = entry->IsStoreLocked();
       
  2349 	return KErrNone;
       
  2350 	}
       
  2351 
       
  2352 
       
  2353 
       
  2354 	
       
  2355 /**
       
  2356  * IsEntryAndStoreLocked()
       
  2357  */
       
  2358 TInt CMsvIndexAdapter::IsEntryOrStoreLocked(TMsvId aId)
       
  2359 	{
       
  2360 	CMsvCacheEntry* entry = NULL;
       
  2361 	TBool locked = EFalse;
       
  2362 	if(FindEntryInCache(aId, entry))
       
  2363 		{
       
  2364 		locked = entry->IsEntryOrStoreLocked();
       
  2365 		}
       
  2366 	if(locked)
       
  2367 		{
       
  2368 		return KErrLocked;
       
  2369 		}
       
  2370 	else
       
  2371 		{
       
  2372 		return KErrNone;
       
  2373 		}
       
  2374 	}
       
  2375 
       
  2376 
       
  2377 
       
  2378 /**
       
  2379  * LockEntryAndStore()
       
  2380  */
       
  2381 TInt CMsvIndexAdapter::LockEntryAndStore(TMsvId aId)
       
  2382 	{
       
  2383 	//__DEBUG_INVARIANT_ONEXIT;
       
  2384 	CMsvCacheEntry* entry = NULL;
       
  2385 	TRAPD(err, FindEntryL(aId, entry));
       
  2386 	if (err)
       
  2387 		{
       
  2388 		return KErrNotFound;
       
  2389 		}
       
  2390 		
       
  2391 	return entry->LockEntryAndStore();
       
  2392 	}
       
  2393 	
       
  2394 
       
  2395 
       
  2396 
       
  2397 /**
       
  2398  * ReleaseEntryAndStore()
       
  2399  */
       
  2400 TInt CMsvIndexAdapter::ReleaseEntryAndStore(TMsvId aId)
       
  2401 	{
       
  2402 	//__DEBUG_INVARIANT_ONEXIT;
       
  2403 	CMsvCacheEntry* entry = NULL;
       
  2404 	if(FindEntryInCache(aId, entry))
       
  2405 		{
       
  2406 		entry->ReleaseEntryAndStore();
       
  2407 		return KErrNone;
       
  2408 		}
       
  2409 	else
       
  2410 		{
       
  2411 		return KErrNotFound;
       
  2412 		}
       
  2413 	}
       
  2414 	
       
  2415 
       
  2416 
       
  2417 
       
  2418 /**
       
  2419  * IsEntryOrStoreLocked()
       
  2420  */
       
  2421 TInt CMsvIndexAdapter::IsEntryOrStoreLocked(TMsvId aId, TBool& aLocked)
       
  2422 	{
       
  2423 	CMsvCacheEntry* entry = NULL;
       
  2424 	if(FindEntryInCache(aId, entry))
       
  2425 		{
       
  2426 		aLocked = entry->IsEntryOrStoreLocked();
       
  2427 		}
       
  2428 	else
       
  2429 		{
       
  2430 		aLocked = EFalse;
       
  2431 		}
       
  2432 	return KErrNone;
       
  2433 	}
       
  2434 	
       
  2435 
       
  2436 
       
  2437 
       
  2438 /**
       
  2439  * IsStoreReadingLocked()
       
  2440  */
       
  2441 TInt CMsvIndexAdapter::IsStoreReadingLocked(TMsvId aId, TBool& aLocked)
       
  2442 	{
       
  2443 	CMsvCacheEntry* entry = NULL;
       
  2444 	if(FindEntryInCache(aId, entry))
       
  2445 		{
       
  2446 		aLocked = entry->IsStoreReadingLocked();
       
  2447 		}
       
  2448 	else
       
  2449 		{
       
  2450 		aLocked = EFalse;
       
  2451 		}
       
  2452 	return KErrNone;	
       
  2453 	}
       
  2454 	
       
  2455 
       
  2456 
       
  2457 
       
  2458 /**
       
  2459  * IncStoreReaderCount()
       
  2460  */
       
  2461 TInt CMsvIndexAdapter::IncStoreReaderCount(TMsvId aId)
       
  2462 	{
       
  2463 	CMsvCacheEntry* entry = NULL;
       
  2464 	TRAPD(err, FindEntryL(aId, entry));
       
  2465 	if (err)
       
  2466 		{
       
  2467 		return KErrNotFound;
       
  2468 		}
       
  2469 		
       
  2470 	entry->IncStoreReaderCount();
       
  2471 	return KErrNone;
       
  2472 	}
       
  2473 	
       
  2474 
       
  2475 
       
  2476 
       
  2477 /**
       
  2478  * DecStoreReaderCount()
       
  2479  */
       
  2480 TInt CMsvIndexAdapter::DecStoreReaderCount(TMsvId aId)
       
  2481 	{
       
  2482 	CMsvCacheEntry* entry = NULL;
       
  2483 	if(FindEntryInCache(aId, entry))
       
  2484 		{
       
  2485 		entry->DecStoreReaderCount();
       
  2486 		}
       
  2487 	return KErrNone;
       
  2488 	}
       
  2489 	
       
  2490 
       
  2491 
       
  2492 
       
  2493 /**
       
  2494  * OwningService()
       
  2495  */
       
  2496 TInt CMsvIndexAdapter::OwningService(TMsvId aId, TMsvId& aService)
       
  2497 	{    
       
  2498 	aService = aId;
       
  2499 	if (aId!=KMsvRootIndexEntryId)
       
  2500 		{
       
  2501 		FOREVER
       
  2502 			{
       
  2503 			CMsvCacheEntry* entry = NULL;	
       
  2504 			TRAPD(err, FindEntryL(aService, entry));
       
  2505 			if (err)
       
  2506 				{
       
  2507 				return KErrNotFound;
       
  2508 				}
       
  2509 
       
  2510 			if (KUidMsvServiceEntry==entry->Entry().iType)
       
  2511 				{
       
  2512 				break;
       
  2513 				}
       
  2514 			aService = entry->Entry().Parent();
       
  2515 			}
       
  2516 		}
       
  2517 
       
  2518 	return KErrNone;
       
  2519 	}
       
  2520 	
       
  2521 
       
  2522 
       
  2523 
       
  2524 /**
       
  2525  * IsLocal()
       
  2526  */
       
  2527 TInt CMsvIndexAdapter::IsLocal(TMsvId aId, TBool& aLocal)
       
  2528 	{
       
  2529 	TInt errVal = KErrNone;
       
  2530 	aLocal = ETrue;
       
  2531 	
       
  2532 	if (aId!=KMsvRootIndexEntryId)
       
  2533 		{
       
  2534 		TMsvId service;
       
  2535 		errVal = OwningService(aId, service);
       
  2536 		aLocal = (KMsvLocalServiceIndexEntryId==service);
       
  2537 		}
       
  2538 		
       
  2539 	return errVal;
       
  2540 	}
       
  2541 
       
  2542 
       
  2543 
       
  2544 
       
  2545 /**
       
  2546  * MoveEntry
       
  2547  * Moves a entry with TMsvId as aId to a folder with target id as aTarget
       
  2548  * 
       
  2549  * @param aId TMsvId of the entry to be moved.
       
  2550  * @param aTarget TMsvId of the parent folder.
       
  2551  * @param aDescendents List of descendents id, if the caller also wants to move descendents
       
  2552  * in cache and DB. The last id in the descendent list must be the entry id itself.
       
  2553  * @return TInt System-wide error code.
       
  2554  */
       
  2555 TInt CMsvIndexAdapter::MoveEntry(TMsvId aId, TMsvId aTarget, CMsvEntrySelection* aDescendents /* DEFAULT=NULL */)
       
  2556 	{
       
  2557 	TRAPD(err, DoMoveEntryL(aId, aTarget, aDescendents));
       
  2558 	return err;
       
  2559 	}
       
  2560 	
       
  2561 
       
  2562 
       
  2563 /**
       
  2564  * DoMoveEntryL()
       
  2565  * Called from MoveEntry()
       
  2566  * */
       
  2567 void CMsvIndexAdapter::DoMoveEntryL(TMsvId aId, TMsvId aTarget, CMsvEntrySelection* aDescendents /* DEFAULT=NULL */)
       
  2568     {
       
  2569     // Leave if the message store is not currently available.
       
  2570     User::LeaveIfError(iErrorState);
       
  2571     
       
  2572     CMsvCacheEntry* entry = NULL;   
       
  2573     CMsvCacheVisibleFolder* oldFolderNode = NULL;
       
  2574     TMsvId oldVisibleFolderId = KMsvNullIndexEntryIdValue;
       
  2575     
       
  2576     // 1. Find the entry in cache.
       
  2577     GetVisibleFolderDetailsL(aId, entry, oldFolderNode);
       
  2578         
       
  2579     // 2. Validate entry.
       
  2580     TBool des;
       
  2581     __ASSERT_DEBUG(entry->IsEntryAndStoreLocked(), PanicServer(EMsvMovingUnlockedEntry));
       
  2582     __ASSERT_DEBUG(entry->Entry().Parent() != aTarget, PanicServer(EMsvMovingWithinSameEntry));
       
  2583     IsADescendent(entry->Entry().Id(), aTarget, des);
       
  2584     if (des)
       
  2585         {// we need to put changes in another method.
       
  2586         User::Leave(KErrArgument);
       
  2587         }
       
  2588     
       
  2589      // 3. Fetch the parent entries.    
       
  2590     CMsvCacheEntry* oldParentEntry = NULL;
       
  2591     CMsvCacheEntry* newParentEntry = NULL;
       
  2592     TMsvId oldParentId = entry->Entry().Parent();
       
  2593     FindEntryL(oldParentId, oldParentEntry);
       
  2594     FindEntryL(aTarget, newParentEntry);
       
  2595     
       
  2596     // 4. Check if the owner flag of the old parent needs to be reset.    
       
  2597     TBool resetOldParentOwnerFlag = EFalse;
       
  2598     CMsvEntrySelection* children = new(ELeave)CMsvEntrySelection;
       
  2599     CleanupStack::PushL(children);
       
  2600     GetChildrenIdL(oldParentId, *children);
       
  2601     if(1 == children->Count() && oldParentEntry->Entry().Owner())
       
  2602         {
       
  2603         // Just set this flag, this is updated in step 14.
       
  2604         resetOldParentOwnerFlag = ETrue;
       
  2605         }
       
  2606     CleanupStack::PopAndDestroy(); //children
       
  2607     
       
  2608     // 5. If required, pre-allocate memory for child array of newParentEntry.
       
  2609     // This is later updated in step 12.
       
  2610     RArray<TMsvId>* newParentChildArr = newParentEntry->ChildIdArray();
       
  2611     if(newParentChildArr)
       
  2612         {
       
  2613         // This to ensure that future append does not fail.
       
  2614         newParentChildArr->ReserveL(newParentChildArr->Count() + 1);
       
  2615         }
       
  2616 
       
  2617     // Step 6 & 7 is performed in this function.
       
  2618     TBool isChildEntriesNeedsUpdation = EFalse;
       
  2619     CMsvCacheVisibleFolder* newVisibleFolderNode = UpdateCacheForMoveEntryL(aTarget,                                                      
       
  2620                                                                             entry, 
       
  2621                                                                             oldFolderNode, 
       
  2622                                                                             aDescendents,
       
  2623                                                                             isChildEntriesNeedsUpdation);
       
  2624 
       
  2625     TMsvId newVisibleFolderId = newVisibleFolderNode? newVisibleFolderNode->GetFolderId(): oldFolderNode->GetFolderId();
       
  2626 
       
  2627     // 8. Update the entry.    
       
  2628     UpdateDates(*entry, EFalse);
       
  2629     entry->Entry().SetParent(aTarget);
       
  2630 
       
  2631     // 9. Update the DB.
       
  2632     TRAPD(err, 
       
  2633             iDbAdapter->BeginTransactionL();
       
  2634             // Update the actual entry
       
  2635             iDbAdapter->UpdateEntryL(entry->Entry(), newVisibleFolderId);
       
  2636             // Reset old parent owner flag.
       
  2637             if(resetOldParentOwnerFlag)
       
  2638                 iDbAdapter->UpdateOwnerStatusL(oldParentId, oldParentEntry->Entry(), EFalse);
       
  2639             // Set new parent owner flag.
       
  2640             if(!newParentEntry->Entry().Owner())
       
  2641                 iDbAdapter->UpdateOwnerStatusL(aTarget, newParentEntry->Entry(), ETrue);
       
  2642             // Update the child entries visibleFolderId in DB.
       
  2643             if(isChildEntriesNeedsUpdation)
       
  2644                 iDbAdapter->UpdateVisibleFolderL(aDescendents, newVisibleFolderId);
       
  2645             iDbAdapter->CommitTransactionL();
       
  2646          );
       
  2647 
       
  2648     if(err)
       
  2649         {        
       
  2650         TRAP_IGNORE(iDbAdapter->RollbackTransactionL());
       
  2651         // Undo step 8.
       
  2652         entry->Entry().SetParent(oldParentId);
       
  2653         // Undo step 7.
       
  2654         if(newVisibleFolderNode)    
       
  2655             newVisibleFolderNode->DeleteEntryL(aId);
       
  2656         if(isChildEntriesNeedsUpdation)
       
  2657             {
       
  2658             for(TInt index=(aDescendents->Count()-2); index>=0; index--)
       
  2659                 {
       
  2660                 newVisibleFolderNode->DeleteEntryL(aDescendents->At(index));
       
  2661                 }
       
  2662             }
       
  2663         User::Leave(err);
       
  2664         }
       
  2665 
       
  2666     // Nothing should fail after this. Ensure that 
       
  2667     // all leaving function after this does not leave.
       
  2668     
       
  2669     // 10. Continuing step 7.1.
       
  2670     // Removing entry from old visible folder.
       
  2671     if(oldVisibleFolderId != newVisibleFolderId)
       
  2672         {
       
  2673         oldFolderNode->DeleteEntryL(aId);
       
  2674         }
       
  2675     
       
  2676     // 11. Continuing step 7.2.
       
  2677     // Removing child entries from old visible folder.
       
  2678     if(isChildEntriesNeedsUpdation)
       
  2679         {
       
  2680         for(TInt index=(aDescendents->Count()-2); index>=0; index--)
       
  2681             {
       
  2682             oldFolderNode->DeleteEntryL(aDescendents->At(index));
       
  2683             }
       
  2684         }
       
  2685 
       
  2686     // 12. Add child id to new parent child array.
       
  2687     if(newParentChildArr)
       
  2688         {
       
  2689         // This will not leave, as memory is already reserved.
       
  2690         newParentChildArr->AppendL(aId);
       
  2691         }
       
  2692     
       
  2693     // 13. Remove child from old parent's child array.
       
  2694     RArray<TMsvId>* oldParentChildArr = oldParentEntry->ChildIdArray();
       
  2695     if(oldParentChildArr)
       
  2696         {
       
  2697         TInt pos = oldParentChildArr->Find(aId);
       
  2698         if(pos != KErrNotFound)
       
  2699             {
       
  2700             oldParentChildArr->Remove(pos);
       
  2701             }
       
  2702         }
       
  2703 
       
  2704     // 14. Update owner flag of parent entries.
       
  2705     if(resetOldParentOwnerFlag)
       
  2706         {
       
  2707         oldParentEntry->Entry().SetOwner(EFalse);
       
  2708         }
       
  2709     newParentEntry->Entry().SetOwner(ETrue);
       
  2710     }
       
  2711 
       
  2712 
       
  2713 
       
  2714 
       
  2715 void CMsvIndexAdapter::GetVisibleFolderDetailsL(TMsvId aEntryId, CMsvCacheEntry*& aEntry, CMsvCacheVisibleFolder*& aVisibleFolder)
       
  2716     {
       
  2717     TDblQueIter<CMsvCacheVisibleFolder> dqIter(iFolderListHeader);
       
  2718     dqIter.SetToFirst();
       
  2719     while((aVisibleFolder = dqIter++)!=NULL)
       
  2720         {
       
  2721         if(aVisibleFolder->GetEntry(aEntryId, aEntry))
       
  2722             {
       
  2723             break;
       
  2724             }
       
  2725         }
       
  2726     if(aEntry==NULL)
       
  2727         {
       
  2728         User::Leave(KErrNotFound);
       
  2729         }
       
  2730     }
       
  2731 
       
  2732 
       
  2733 
       
  2734 
       
  2735 CMsvCacheVisibleFolder* CMsvIndexAdapter::UpdateCacheForMoveEntryL(TMsvId aNewParentId,
       
  2736                                                                    CMsvCacheEntry*& aOrigEntry, 
       
  2737                                                                    CMsvCacheVisibleFolder* aOldVisibleFolderNode, 
       
  2738                                                                    CMsvEntrySelection* aDescendents,
       
  2739                                                                    TBool& aIsChildEntriesNeedsUpdation)
       
  2740     {
       
  2741     // 6. Find the visible folder of new parent.
       
  2742     TMsvId newVisibleFolderId = aOldVisibleFolderNode->GetFolderId();
       
  2743     if(!GetVisibleFolderId(aNewParentId, newVisibleFolderId))
       
  2744         {
       
  2745         User::Leave(KErrNotFound);
       
  2746         }
       
  2747     
       
  2748     // 7. Check if the visible folders are different.
       
  2749     CMsvCacheVisibleFolder* newVisibleFolderNode = NULL;
       
  2750     if(aOldVisibleFolderNode->GetFolderId() != newVisibleFolderId)
       
  2751         {
       
  2752         // 7.1. If the visible folders are different, add duplicate
       
  2753         // entry under new visible folder. Removing entry from old
       
  2754         // visible folder is done in step 10 of DoMoveEntryL().
       
  2755         CMsvCacheEntry* newCacheEntry = iFreePoolInstance->EntryL();    
       
  2756         TRAPD(err, newCacheEntry->DupNDestroyL(aOrigEntry);
       
  2757                    newVisibleFolderNode = AddEntryToCacheL(newVisibleFolderId, newCacheEntry);
       
  2758              );
       
  2759         if(err)
       
  2760             {
       
  2761             iFreePoolInstance->ReleaseEntryWithoutTransaction(newCacheEntry);
       
  2762             User::Leave(err);
       
  2763             }
       
  2764     
       
  2765         // 7.2. Check if child entries also needs to be moved. 
       
  2766         aOrigEntry = newCacheEntry;
       
  2767         if(aDescendents && !aOrigEntry->Entry().VisibleFolderFlag())
       
  2768              {
       
  2769              aIsChildEntriesNeedsUpdation = ETrue;
       
  2770              
       
  2771              // Add duplicate child entry under new visible folder.
       
  2772              // Removing child entries from old visible folder is done in step 11.
       
  2773              CMsvCacheEntry* childEntry = NULL;
       
  2774              CMsvCacheEntry* dupChildEntry = NULL;
       
  2775              for(TInt index=(aDescendents->Count()-2); index>=0; index--)
       
  2776                  {
       
  2777                  if(aOldVisibleFolderNode->GetEntry(aDescendents->At(index), childEntry))
       
  2778                      {
       
  2779                      dupChildEntry = NULL;
       
  2780                      // Create the duplicate of original entry.
       
  2781                      TRAP(err, dupChildEntry = iFreePoolInstance->EntryL();
       
  2782                                dupChildEntry->DupNDestroyL(childEntry);
       
  2783                                // Add under new visible folder node.
       
  2784                                newVisibleFolderNode->AddEntryL(dupChildEntry);
       
  2785                           );
       
  2786                      if(err)
       
  2787                          {
       
  2788                          // Delete should not be leaving...
       
  2789                          newVisibleFolderNode->DeleteEntryL(aOrigEntry->GetId());    // Undo step 7.1
       
  2790                          iFreePoolInstance->ReleaseEntryWithoutTransaction(dupChildEntry);   // Undo current entry
       
  2791                          // Undo remaining entries.
       
  2792                          for(TInt numEntries=index+1; numEntries<=(aDescendents->Count()-2); numEntries++)
       
  2793                              {
       
  2794                              newVisibleFolderNode->DeleteEntryL(aDescendents->At(numEntries));
       
  2795                              }
       
  2796                          User::Leave(err);
       
  2797                          }
       
  2798                      }   // if(oldFolderNode->GetEntry(aDescendents->At(index), childEntry))
       
  2799                  }   // for()
       
  2800              }   // if(aDescendents && !entry->Entry().VisibleFolderFlag())
       
  2801         }
       
  2802     return newVisibleFolderNode;
       
  2803     }
       
  2804 
       
  2805 
       
  2806 
       
  2807 
       
  2808 /**
       
  2809  * IsADescendent()
       
  2810  */
       
  2811 TInt CMsvIndexAdapter::IsADescendent(TMsvId aAscendentId, TMsvId aDescendentId, TBool& aDescendent)
       
  2812 	{
       
  2813 	__ASSERT_DEBUG((KMsvRootIndexEntryId != aAscendentId) && (KMsvRootIndexEntryId != aDescendentId), PanicServer(EMsvDescendentArgumentsRoot));
       
  2814 	__ASSERT_DEBUG(aAscendentId!=aDescendentId, PanicServer(EMsvDescendentArgumentsEqual));
       
  2815 	
       
  2816 	aDescendent=EFalse;
       
  2817 	while (KMsvRootIndexEntryId != aDescendentId)
       
  2818 		{
       
  2819 		CMsvCacheEntry* entry;	
       
  2820 		TRAPD(err, FindEntryL(aDescendentId, entry));
       
  2821 		if (err)
       
  2822 			{
       
  2823 			return KErrNotFound;
       
  2824 			}
       
  2825 		if (aDescendentId==aAscendentId)
       
  2826 			{
       
  2827 			aDescendent=ETrue;
       
  2828 			break;
       
  2829 			}
       
  2830 		aDescendentId=entry->Entry().Parent();
       
  2831 		}
       
  2832 		
       
  2833 	return KErrNone;
       
  2834 	}
       
  2835 	
       
  2836 
       
  2837 
       
  2838 
       
  2839 /**
       
  2840  * EntryExists()
       
  2841  */
       
  2842 TBool CMsvIndexAdapter::EntryExists(TMsvId aId)
       
  2843 	{
       
  2844 	// First search the entry in cache, 
       
  2845 	// if cache is not empty...
       
  2846 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  2847 	if(KMsvRootIndexEntryId == aId)
       
  2848 		{
       
  2849 		return true;
       
  2850 		}
       
  2851 #endif
       
  2852 	if(!iFolderListHeader.IsEmpty())
       
  2853 		{
       
  2854 		CMsvCacheVisibleFolder* folderNode = NULL;
       
  2855 		TDblQueIter<CMsvCacheVisibleFolder> dqIter(iFolderListHeader);
       
  2856 		dqIter.SetToFirst(); 
       
  2857 		
       
  2858 		while((folderNode = dqIter++)!=NULL)
       
  2859 			{
       
  2860 			if(aId == folderNode->GetFolderId())
       
  2861 				{
       
  2862 				return ETrue;
       
  2863 				}
       
  2864 			if(folderNode->EntryExists(aId))
       
  2865 				{
       
  2866 				return ETrue;
       
  2867 				}
       
  2868 			}
       
  2869 		}
       
  2870 	
       
  2871 	TBool entryExists = EFalse;
       
  2872 	if(iDbAdapter)
       
  2873 		{
       
  2874 		TRAP_IGNORE(entryExists = iDbAdapter->EntryExistsL(aId));
       
  2875 		}
       
  2876 	else
       
  2877 		{
       
  2878 		return EFalse;
       
  2879 		}
       
  2880 	if(!entryExists)
       
  2881 		{
       
  2882 		return EFalse;	
       
  2883 		}
       
  2884 	return ETrue;
       
  2885 	}
       
  2886 	
       
  2887 
       
  2888 
       
  2889 
       
  2890 /**
       
  2891  * ChangeTemporaryData()
       
  2892  */
       
  2893 TInt CMsvIndexAdapter::ChangeTemporaryData(const TMsvEntry& aNewEntryContents)
       
  2894 	{
       
  2895 	//__DEBUG_INVARIANT_ONEXIT;
       
  2896 	
       
  2897 	CMsvCacheEntry* entry;	
       
  2898 
       
  2899 	// find the entry in the index
       
  2900 	TRAPD(err, FindEntryL(aNewEntryContents.Id(), entry));
       
  2901 	if (err)
       
  2902 		{
       
  2903 		return KErrNotFound;
       
  2904 		}
       
  2905 
       
  2906 	// Can only change a locked entry and not one marked as read only
       
  2907 	if (!entry->IsEntryLocked() || entry->Entry().StandardFolder())
       
  2908 		{
       
  2909 		return KErrAccessDenied;
       
  2910 		}
       
  2911 
       
  2912 	// Check if just changing temporary flags (ie those not stored on file)
       
  2913 	entry->Entry().iData=aNewEntryContents.iData;
       
  2914 
       
  2915 	return KErrNone;	
       
  2916 	}
       
  2917 	
       
  2918 
       
  2919 
       
  2920 
       
  2921 /**
       
  2922  * ChangeAttributes()
       
  2923  */
       
  2924 TInt CMsvIndexAdapter::ChangeAttributes(CMsvEntrySelection& aSelection, TUint aSetAttributes, TUint aClearAttributes)
       
  2925 	{
       
  2926 	TRAPD(leave, DoChangeAttributesL(aSelection, aSetAttributes, aClearAttributes));
       
  2927 	return leave;
       
  2928 	}
       
  2929 	
       
  2930 
       
  2931 
       
  2932 void CMsvIndexAdapter::DoChangeAttributesL(CMsvEntrySelection& aSelection, TUint aSetAttributes, TUint aClearAttributes)
       
  2933 	{
       
  2934 	// Leave if the message store is not currently available
       
  2935 	User::LeaveIfError(iErrorState);
       
  2936 
       
  2937 	CArrayFixSeg<TInt32>* newData = new(ELeave)CArrayFixSeg<TInt32>(KMsvChangeAttributesListGranularity);
       
  2938 	CleanupStack::PushL(newData);
       
  2939 	CArrayFixSeg<TInt32>* newPcSyncCount = new(ELeave)CArrayFixSeg<TInt32>(KMsvChangeAttributesListGranularity);
       
  2940 	CleanupStack::PushL(newPcSyncCount);
       
  2941 
       
  2942 	newData->ResizeL(aSelection.Count(), 0);
       
  2943 	newPcSyncCount->ResizeL(aSelection.Count(), 0);
       
  2944 
       
  2945 	TInt count=aSelection.Count();
       
  2946 	TDblQueIter<CMsvCacheVisibleFolder> dqIter(iFolderListHeader);
       
  2947 	CMsvCacheEntry* entry = NULL;	
       
  2948 	CMsvCacheVisibleFolder* folderNode = NULL;
       
  2949 	TMsvId newVisibleFolderId = NULL;
       
  2950 	if(iDbAdapter)
       
  2951 		{
       
  2952 		iDbAdapter->BeginTransactionL();
       
  2953 		}
       
  2954 	else
       
  2955 		{
       
  2956 		User::Leave(ErrorState());	
       
  2957 		}
       
  2958 	while(count--)
       
  2959 		{
       
  2960 		// find the entry in the index
       
  2961 		dqIter.SetToFirst();
       
  2962 		while((folderNode = dqIter++)!=NULL)
       
  2963 			{
       
  2964 			if(folderNode->GetEntry(aSelection.At(count), entry))
       
  2965 				{
       
  2966 				newVisibleFolderId = folderNode->GetFolderId();
       
  2967 				break;
       
  2968 				}
       
  2969 			}
       
  2970 		if (entry == NULL)
       
  2971 			{
       
  2972 			User::Leave(KErrNotFound);
       
  2973 			}
       
  2974 		// can only change a locked entry and not one marked as read only
       
  2975 		if (!entry->IsEntryLocked() || entry->Entry().StandardFolder())
       
  2976 			{
       
  2977 			User::Leave(KErrAccessDenied);
       
  2978 			}
       
  2979 			
       
  2980 		// work out the new attributes
       
  2981 		TBool persistedFlagsChanged;
       
  2982 		if (!NewAttributes(entry->Entry(), newData->At(count), newPcSyncCount->At(count), aSetAttributes, aClearAttributes, persistedFlagsChanged))
       
  2983 			{
       
  2984 			// attributes don't need changing
       
  2985 			aSelection.Delete(count);
       
  2986 			newData->Delete(count);
       
  2987 			newPcSyncCount->Delete(count);
       
  2988 			continue;
       
  2989 			}
       
  2990 		if(persistedFlagsChanged)
       
  2991 			{
       
  2992 			TMsvEntry tEntry = entry->Entry();
       
  2993 			tEntry.iData = newData->At(count);
       
  2994 			tEntry.iPcSyncCount = newPcSyncCount->At(count);
       
  2995 			TInt err = KErrNone;
       
  2996 			if(iDbAdapter)
       
  2997 				{
       
  2998 				TRAP(err, iDbAdapter->UpdateEntryL(tEntry, newVisibleFolderId, EFalse));
       
  2999 				}
       
  3000 			else
       
  3001 				{
       
  3002 				User::Leave(ErrorState());	
       
  3003 				}
       
  3004 			if(err)
       
  3005 				{
       
  3006 				iDbAdapter->RollbackTransactionL();
       
  3007 				User::Leave(err);
       
  3008 				}
       
  3009 			}
       
  3010 		}
       
  3011 	if(iDbAdapter)
       
  3012 		{
       
  3013 		iDbAdapter->CommitTransactionL();
       
  3014 		}
       
  3015 	else
       
  3016 		{
       
  3017 		User::Leave(ErrorState());	
       
  3018 		}	
       
  3019 	
       
  3020 	count=aSelection.Count();
       
  3021 	while(count--)
       
  3022 		{
       
  3023 		// find the entry in the index
       
  3024 		CMsvCacheEntry* entryPtr = NULL;
       
  3025 		dqIter.SetToFirst();
       
  3026 		while((folderNode = dqIter++)!=NULL)
       
  3027 			{
       
  3028 			if(folderNode->GetEntry(aSelection.At(count), entryPtr))
       
  3029 				{
       
  3030 				break;
       
  3031 				}
       
  3032 			}
       
  3033 #if defined(_DEBUG)
       
  3034 		TBool found = (NULL != entryPtr);
       
  3035 		__ASSERT_DEBUG(found, PanicServer(EMsvChangeAttEmtryNotFound));
       
  3036 #endif
       
  3037 		entryPtr->Entry().iData=newData->At(count);
       
  3038 		entryPtr->Entry().iPcSyncCount=newPcSyncCount->At(count);
       
  3039 		}
       
  3040 	CleanupStack::PopAndDestroy(2, newData);
       
  3041 	if (!iIdle->IsActive())
       
  3042 		{
       
  3043 		iIdle->Start(TCallBack(BackGroundOperations, this));	
       
  3044 		}
       
  3045 		
       
  3046 	}
       
  3047 
       
  3048 /**
       
  3049  * NewAttributes
       
  3050 */	
       
  3051 TBool CMsvIndexAdapter::NewAttributes(const TMsvEntry& aEntry, TInt32& aNewData, TInt32& aNewPcSyncCount, TUint aSetAttributes, TUint aClearAttributes, TBool& aPersistedFlagsChanged)
       
  3052 	{
       
  3053 	aNewData = aEntry.iData;
       
  3054 	aNewPcSyncCount = aEntry.iPcSyncCount;
       
  3055 
       
  3056 	// KMsvPcSyncCountAttribute is a dummy flag that is used to increment/decrement the PC Sync Count
       
  3057 	// The visibility attribute is actually recorded as an 'invisible' flag in the index
       
  3058 	if (aSetAttributes)
       
  3059 		{
       
  3060 		if (aSetAttributes & KMsvPcSyncCountAttribute)
       
  3061 			{
       
  3062 			aNewPcSyncCount++;
       
  3063 			aSetAttributes &= ~KMsvPcSyncCountAttribute;
       
  3064 			}
       
  3065 		
       
  3066 		const TInt32 mask = KMsvSendStateMax << KMsvSendingStateShift;
       
  3067 		if (aSetAttributes & mask)
       
  3068 			{
       
  3069 			aNewData &= ~mask;
       
  3070 			}
       
  3071 			
       
  3072 
       
  3073 		aNewData |= aSetAttributes;
       
  3074 
       
  3075 		if (aSetAttributes & KMsvVisibilityAttribute)
       
  3076 			{
       
  3077 			aNewData &= ~TMsvEntry::KMsvEntryInvisibleFlag;
       
  3078 			}
       
  3079 		if (aSetAttributes & KMsvPendingDeleteAttribute)
       
  3080 			{
       
  3081 			aNewData |= TMsvEntry::KMsvEntryPendingDeleteFlag;
       
  3082 			}
       
  3083 		}
       
  3084 
       
  3085 	if (aClearAttributes)
       
  3086 		{
       
  3087 		if (aClearAttributes & KMsvPcSyncCountAttribute)
       
  3088 			{
       
  3089 			aNewPcSyncCount--;
       
  3090 			aClearAttributes &= ~KMsvPcSyncCountAttribute;
       
  3091 			}
       
  3092 
       
  3093 		aNewData &= ~aClearAttributes;
       
  3094 
       
  3095 		if (aClearAttributes&KMsvVisibilityAttribute)
       
  3096 			{
       
  3097 			aNewData |= TMsvEntry::KMsvEntryInvisibleFlag;
       
  3098 			}
       
  3099 			
       
  3100 		if (aClearAttributes&KMsvPendingDeleteAttribute)
       
  3101 			{
       
  3102 			aNewData &= ~TMsvEntry::KMsvEntryPendingDeleteFlag;
       
  3103 			}
       
  3104 			
       
  3105 		}
       
  3106 
       
  3107 	aPersistedFlagsChanged = (aNewData&TMsvEntry::KMsvEntryPersistedFlags)!=(aEntry.iData&TMsvEntry::KMsvEntryPersistedFlags) ||
       
  3108 								aNewPcSyncCount != aEntry.iPcSyncCount;
       
  3109 	return aNewData != aEntry.iData || aNewPcSyncCount != aEntry.iPcSyncCount;
       
  3110 	}
       
  3111 
       
  3112 /**
       
  3113  * UpdateDates
       
  3114 */
       
  3115 void CMsvIndexAdapter::UpdateDates(CMsvCacheEntry& aEntry, TBool aSetCreatedDate)
       
  3116 	{
       
  3117 	TTime now;
       
  3118 	now.UniversalTime();
       
  3119 	TMsvTime time;
       
  3120 	time.SetTime(now);
       
  3121 	aEntry.SetLastChangeDate(time);
       
  3122 	
       
  3123 	if (aSetCreatedDate)
       
  3124 		{
       
  3125 		aEntry.SetCreatedDate(time);
       
  3126 		}
       
  3127 	}
       
  3128 
       
  3129 
       
  3130 
       
  3131 
       
  3132 /**
       
  3133  * GetInternalEntry()
       
  3134  */
       
  3135 TInt CMsvIndexAdapter::GetInternalEntry(TMsvId aId, CMsvCacheEntry*& aEntry)
       
  3136 	{
       
  3137 	CMsvCacheEntry* entry=NULL;
       
  3138 	TRAPD(err, FindEntryL(aId, entry));
       
  3139 	if(err!=KErrNone)
       
  3140 		{
       
  3141 		return err;
       
  3142 		}
       
  3143 	if(entry==NULL)
       
  3144 		{
       
  3145 		return KErrNotFound;
       
  3146 		}
       
  3147 	aEntry=entry;
       
  3148 	return KErrNone;
       
  3149 	}
       
  3150 
       
  3151 	
       
  3152 /**
       
  3153  * Progress()
       
  3154 */ 
       
  3155 TMsvIndexProgress& CMsvIndexAdapter::Progress()
       
  3156 	{
       
  3157 	return iProgress;
       
  3158 	}
       
  3159 	
       
  3160 
       
  3161 /**
       
  3162  * EntryTreeInfo()
       
  3163  */
       
  3164 TInt CMsvIndexAdapter::EntryTreeInfo(TMsvId aId, TMsvServerEntryInfo& aEntryInfo)
       
  3165 	{
       
  3166 	aEntryInfo.Reset();
       
  3167 	aEntryInfo.iId = aId;
       
  3168 
       
  3169 	if( aId != KMsvRootIndexEntryId )
       
  3170 		{
       
  3171 		// Search up the tree to find which service the specified entry is under.
       
  3172 		// Also, record the highest owning folder for the entry.
       
  3173 		TMsvId id = aId;
       
  3174 		CMsvCacheEntry* entry =NULL;
       
  3175 		TRAPD(err, FindEntryL(id, entry));
       
  3176 		if(err)
       
  3177 			return KErrNotFound;
       
  3178 		
       
  3179 		id = entry->Entry().iId; //Id may be masked in cache
       
  3180 		aEntryInfo.iId = id;
       
  3181 		
       
  3182 		// Get info for the entry.
       
  3183 		aEntryInfo.iEntryOwnerId	= entry->EntryOwnerId();
       
  3184 		aEntryInfo.iMtm				= entry->Entry().iMtm;
       
  3185 		aEntryInfo.iType			= entry->Entry().iType;
       
  3186 		
       
  3187 		if( aEntryInfo.iType == KUidMsvFolderEntry )
       
  3188 			{
       
  3189 			// This is a folder - record as this may be needed.
       
  3190 			aEntryInfo.iTopFolder = id;
       
  3191 			}
       
  3192 		
       
  3193 		TBool found = (aEntryInfo.iType == KUidMsvServiceEntry);
       
  3194 		while( !found )
       
  3195 			{
       
  3196 			// Move up the tree and get the next entry...
       
  3197 			id = entry->Entry().Parent();
       
  3198 			TRAPD(err, FindEntryL(id, entry));
       
  3199 			if(err)
       
  3200 			 return KErrNotFound;
       
  3201 			
       
  3202 			TUid type = entry->Entry().iType;
       
  3203 			if( type == KUidMsvServiceEntry )
       
  3204 				{
       
  3205 				// Ok, we've found the owning service - stop looking.
       
  3206 				found = ETrue;
       
  3207 				}
       
  3208 			else if( type == KUidMsvFolderEntry )
       
  3209 				{
       
  3210 				// This is a folder - record as this may be needed.
       
  3211 				aEntryInfo.iTopFolder = id;
       
  3212 				}
       
  3213 			else 
       
  3214 				{
       
  3215 				// This is a message or attachment entry - this implies that the
       
  3216 				// original entry was part of an existing message. Set the owner
       
  3217 				// ID to the highest parent.
       
  3218 				aEntryInfo.iPartOfMessage	= ETrue;
       
  3219 				aEntryInfo.iParentOwnerId	= entry->EntryOwnerId();
       
  3220 				}
       
  3221 			}
       
  3222 		// Record the service and MTM...
       
  3223 		aEntryInfo.iService = id;
       
  3224 
       
  3225 		aEntryInfo.iServiceMtm = entry->Entry().iMtm;
       
  3226 		}
       
  3227 	else
       
  3228 		{
       
  3229 		// This is the root entry! Mark the service as being the local service.
       
  3230 		aEntryInfo.iType		= KUidMsvRootEntry;
       
  3231 		aEntryInfo.iMtm			= KUidMsvLocalServiceMtm;
       
  3232 		aEntryInfo.iService		= KMsvLocalServiceIndexEntryId;
       
  3233 		aEntryInfo.iServiceMtm	= KUidMsvLocalServiceMtm;
       
  3234 		aEntryInfo.iTopFolder	= KMsvRootIndexEntryId;
       
  3235 		}
       
  3236 	return KErrNone;
       
  3237 	}
       
  3238 	
       
  3239 
       
  3240 
       
  3241 
       
  3242 /**
       
  3243  * CommitNonCommitedEntries()
       
  3244  */
       
  3245 void CMsvIndexAdapter::CommitNonCommitedEntries()
       
  3246 	{
       
  3247 	// 1. Commit transaction in DB.
       
  3248 	if(iDbAdapter)
       
  3249 		{
       
  3250 		TRAPD(err, iDbAdapter->CommitTransactionL());
       
  3251 		if(err)
       
  3252 		    {
       
  3253 		    RollbackAdditions();
       
  3254 		    RollbackChanges();
       
  3255 		    return;
       
  3256 		    }
       
  3257 		}
       
  3258 
       
  3259 	// 2. Update changed entries completely.
       
  3260 	TInt count = iNonCommittedChangedEntryList.Count();
       
  3261 	while(count)
       
  3262 		{
       
  3263 		TNonCommittedChangedEntries changedEntry = iNonCommittedChangedEntryList[--count];
       
  3264 		CMsvCacheVisibleFolder* oldVisibleFolderNode = changedEntry.iOldVisibleFolderNode;
       
  3265         // Removing entry from old visible folder.
       
  3266         if(changedEntry.iNewVisibleFolderNode &&
       
  3267            oldVisibleFolderNode->GetFolderId() != changedEntry.iNewVisibleFolderNode->GetFolderId())
       
  3268             {
       
  3269             // Will never leave.
       
  3270             TRAP_IGNORE(changedEntry.iOldVisibleFolderNode->DeleteEntryL(changedEntry.iEntry->GetId()));
       
  3271             }
       
  3272         
       
  3273         // Removing child entries from old visible folder.
       
  3274         if(changedEntry.iDescendentList)
       
  3275             {
       
  3276             for(TInt index=(changedEntry.iDescendentList->Count()-2); index>=0; index--)
       
  3277                 {
       
  3278                 // Can leave with KErrNotFound.
       
  3279                 TRAP_IGNORE(oldVisibleFolderNode->DeleteEntryL(changedEntry.iDescendentList->At(index)));
       
  3280                 }
       
  3281             delete changedEntry.iDescendentList;            
       
  3282             }
       
  3283     
       
  3284         // Add child id to new parent child array.
       
  3285         if(changedEntry.iNewParentEntry && (changedEntry.iNewParentEntry->ChildIdArray()))
       
  3286             {
       
  3287             // This will not leave, as memory is already reserved.
       
  3288             TRAP_IGNORE(changedEntry.iNewParentEntry->ChildIdArray()->AppendL(changedEntry.iEntry->GetId()));
       
  3289             }
       
  3290         
       
  3291         // Remove child from old parent's child array.
       
  3292         if(changedEntry.iOldParentEntry)
       
  3293             {
       
  3294             RArray<TMsvId>* oldParentChildArr = changedEntry.iOldParentEntry->ChildIdArray();
       
  3295             if(oldParentChildArr)
       
  3296                 {
       
  3297                 TInt pos = oldParentChildArr->Find(changedEntry.iEntry->GetId());
       
  3298                 if(pos != KErrNotFound)
       
  3299                     {
       
  3300                     oldParentChildArr->Remove(pos);
       
  3301                     }
       
  3302                 }
       
  3303             }
       
  3304     
       
  3305         // Update owner flag of parent entries.
       
  3306         if(changedEntry.iResetOldParentOwnerFlag)
       
  3307             {
       
  3308             changedEntry.iOldParentEntry->Entry().SetOwner(EFalse);
       
  3309             }
       
  3310         if(changedEntry.iNewParentEntry)
       
  3311             {
       
  3312             changedEntry.iNewParentEntry->Entry().SetOwner(ETrue);
       
  3313             }
       
  3314 		}
       
  3315 
       
  3316 	// 3. Reset non-committed entry list.
       
  3317 	iNonCommittedAddedEntryList.ResetAndDestroy();
       
  3318 	iNonCommittedChangedEntryList.Reset();
       
  3319 	}
       
  3320 
       
  3321 
       
  3322 
       
  3323 /**
       
  3324  * RollbackAdditions()
       
  3325  */
       
  3326 void CMsvIndexAdapter::RollbackAdditions()
       
  3327 	{
       
  3328 	// 1. Rollback transaction in DB.
       
  3329 	if(iDbAdapter)
       
  3330 		{
       
  3331 		TRAP_IGNORE(iDbAdapter->RollbackTransactionL());
       
  3332 		}
       
  3333 	
       
  3334 	// 2. Delete added entry from cache.
       
  3335 	CMsvCacheVisibleFolder* folderNode = NULL;
       
  3336 	TInt count = iNonCommittedAddedEntryList.Count();
       
  3337 	TDblQueIter<CMsvCacheVisibleFolder> dqIter(iFolderListHeader);
       
  3338 	while(count)
       
  3339 		{
       
  3340 		--count;
       
  3341 		dqIter.SetToFirst();
       
  3342 	    while ((folderNode = dqIter++) != NULL)
       
  3343 	        {
       
  3344 	        if(iNonCommittedAddedEntryList[count]->iVisibleFolder == folderNode->GetFolderId())
       
  3345 	           	{
       
  3346 	           	iNonCommittedAddedEntryList[count]->entry->LockEntry();
       
  3347 	        	// Error can cause if the entry does not exist. Ignore.
       
  3348 	        	TRAP_IGNORE(folderNode->DeleteEntryL(iNonCommittedAddedEntryList[count]->entry->GetId()));
       
  3349 	        	break;
       
  3350 	        	}
       
  3351 	        };
       
  3352 		}
       
  3353 	
       
  3354 	// 3. Reset non-committed entry list.
       
  3355 	iNonCommittedAddedEntryList.ResetAndDestroy();
       
  3356 	}
       
  3357 
       
  3358 
       
  3359 
       
  3360 
       
  3361 
       
  3362 /**
       
  3363  * RollbackChanges()
       
  3364  */
       
  3365 void CMsvIndexAdapter::RollbackChanges()
       
  3366 	{
       
  3367 	// 1. Rollback transaction in DB.
       
  3368 	if(iDbAdapter)
       
  3369 		{
       
  3370 		TRAP_IGNORE(iDbAdapter->RollbackTransactionL());
       
  3371 		}
       
  3372 	
       
  3373 	// 2. Undo changed entry in cache.
       
  3374 	TInt count = iNonCommittedChangedEntryList.Count();
       
  3375 	while(count)
       
  3376 		{
       
  3377 		TNonCommittedChangedEntries changedEntry = iNonCommittedChangedEntryList[--count];
       
  3378 		CMsvCacheEntry* oldEntry = changedEntry.iEntry;
       
  3379 
       
  3380 		// If the visible folder Id of the entry is changed, 
       
  3381 		// oldEntry represents the entry under new visible folder node.
       
  3382 		// Get the actual old entry from old visible folder node.
       
  3383 		if(changedEntry.iNewVisibleFolderNode)
       
  3384 		    {
       
  3385 		    // This will be non leaving as entry is already present.
       
  3386 		    if(changedEntry.iOldVisibleFolderNode->GetEntry(oldEntry->GetId(), oldEntry))
       
  3387 				{
       
  3388 				// Remove added entry from new visible node. 
       
  3389 				// This function will never leave in the current 
       
  3390 				// scenario, hence ignoring the error.
       
  3391 				TRAP_IGNORE(changedEntry.iNewVisibleFolderNode->DeleteEntryL(oldEntry->GetId()));
       
  3392 				}
       
  3393 		    }
       
  3394         oldEntry->SetEntryOwnerId(changedEntry.iBkpEntry->EntryOwnerId());
       
  3395         oldEntry->RollBackCopyEntry(changedEntry.iBkpEntry->Entry());
       
  3396         iFreePoolInstance->ReleaseEntryWithoutTransaction(changedEntry.iBkpEntry);
       
  3397         
       
  3398         if(changedEntry.iDescendentList)
       
  3399             {
       
  3400             delete changedEntry.iDescendentList;
       
  3401             }
       
  3402  		}
       
  3403         
       
  3404 	// 3. Reset non-committed entry list.
       
  3405 	iNonCommittedChangedEntryList.Reset();
       
  3406 	}
       
  3407 
       
  3408 
       
  3409 
       
  3410 
       
  3411 CMsvIndexAdapter::TMsvServerEntryInfo::TMsvServerEntryInfo()
       
  3412 	{
       
  3413 	iId				= KMsvNullIndexEntryIdValue;
       
  3414 	iTopFolder		= KMsvNullIndexEntryIdValue;
       
  3415 	iService		= KMsvNullIndexEntryIdValue;
       
  3416 	iMtm			= KUidMsvNullEntry;
       
  3417 	iType			= KUidMsvNullEntry;
       
  3418 	iServiceMtm		= KUidMsvNullEntry;
       
  3419 	iEntryOwnerId	= KMsvServerId.iId; 
       
  3420 	iParentOwnerId	= KMsvServerId.iId;
       
  3421 	iPartOfMessage	= EFalse;	
       
  3422 	}
       
  3423 
       
  3424 
       
  3425 
       
  3426 
       
  3427 void CMsvIndexAdapter::TMsvServerEntryInfo::Reset()
       
  3428 	{
       
  3429 	iId				= KMsvNullIndexEntryIdValue;
       
  3430 	iTopFolder		= KMsvNullIndexEntryIdValue;
       
  3431 	iService		= KMsvNullIndexEntryIdValue;
       
  3432 	iMtm			= KUidMsvNullEntry;
       
  3433 	iType			= KUidMsvNullEntry;
       
  3434 	iServiceMtm		= KUidMsvNullEntry;
       
  3435 	iEntryOwnerId	= KMsvServerId.iId; 
       
  3436 	iParentOwnerId	= KMsvServerId.iId;
       
  3437 	iPartOfMessage	= EFalse;	
       
  3438 	}	
       
  3439 
       
  3440 
       
  3441 /**
       
  3442 Need to see the posibilty of getting this first from cache
       
  3443 */
       
  3444 TBool CMsvIndexAdapter::GetNextSiblingL(TMsvId aId,TMsvId aParentId,TMsvId& aNextSiblingId)
       
  3445 	{
       
  3446 	TBool flag = EFalse;
       
  3447 	if(iDbAdapter)
       
  3448 		{
       
  3449 		flag = iDbAdapter->GetNextSiblingL(aId, aParentId, aNextSiblingId);
       
  3450 		}
       
  3451 	else
       
  3452 		{
       
  3453 		User::Leave(ErrorState());	
       
  3454 		}
       
  3455 	return flag;
       
  3456 	}
       
  3457 
       
  3458 
       
  3459 /**
       
  3460 Need to see the posibilty of getting this first from cache
       
  3461 */
       
  3462 TBool CMsvIndexAdapter::GetFirstChildIdL(TMsvId aParentId,TMsvId& aFirstChild)
       
  3463 	{
       
  3464 	TBool flag = EFalse;
       
  3465 	if(iDbAdapter)
       
  3466 		{
       
  3467 		flag = iDbAdapter->GetFirstChildIdL(aParentId, aFirstChild);
       
  3468 		}
       
  3469 	else
       
  3470 		{
       
  3471 		User::Leave(ErrorState());	
       
  3472 		}
       
  3473 	return flag;
       
  3474 	}
       
  3475 
       
  3476 
       
  3477 /**
       
  3478  * SetLocalServiceComplete
       
  3479  * @param TUint: Drive Id of the local service folder node.
       
  3480  *
       
  3481  * Code changes for PREQ 557.
       
  3482  * Sets the localservice visiblefolder.
       
  3483  */	
       
  3484 void CMsvIndexAdapter::SetLocalServiceComplete()
       
  3485 	{
       
  3486 	TDblQueIter<CMsvCacheVisibleFolder> dqIter(iFolderListHeader);
       
  3487 	dqIter.SetToFirst();
       
  3488 	CMsvCacheVisibleFolder* folderNode = NULL;
       
  3489 
       
  3490 	while((folderNode = dqIter++)!=NULL)
       
  3491 		{
       
  3492 		if(KMsvLocalServiceIndexEntryIdValue == folderNode->GetFolderId())
       
  3493 			{
       
  3494 			folderNode->SetComplete(ETrue);
       
  3495 			break;
       
  3496 			}
       
  3497 		}
       
  3498 	}
       
  3499 
       
  3500 	
       
  3501 /**
       
  3502  *BackGroundOperations()
       
  3503  *@param  aPtr 	A TAny*
       
  3504  *@return TBool ETrue if the background operation needs to be rescheduled.
       
  3505  *				EFalse if the background operation need not be rescheduled.
       
  3506  */
       
  3507 TBool CMsvIndexAdapter::BackGroundOperations(TAny* aPtr)
       
  3508 	{
       
  3509 	return ((CMsvIndexAdapter*)aPtr)->DoBackGroundOperations();
       
  3510 	}
       
  3511 
       
  3512 
       
  3513 
       
  3514 
       
  3515 
       
  3516 /**
       
  3517  *DoBackGroundOperations()
       
  3518  *@param  None
       
  3519  *@return TBool ETrue if the background operation needs to be rescheduled.
       
  3520  *				EFalse if the background operation need not be rescheduled.
       
  3521  */
       
  3522 TBool CMsvIndexAdapter::DoBackGroundOperations()
       
  3523 	{
       
  3524 	TInt stopBackgroundOperation = EFalse;
       
  3525 	TRAPD(err, DoBackGroundOperationsL(stopBackgroundOperation));
       
  3526 	if(KErrNone == err && !stopBackgroundOperation)
       
  3527 		{
       
  3528 		return ETrue;
       
  3529 		}
       
  3530 	return EFalse;	
       
  3531 	}
       
  3532 
       
  3533 
       
  3534 
       
  3535 
       
  3536 
       
  3537 /**
       
  3538  *DoBackGroundOperations()
       
  3539  *This is the background operation state machine, this will perform a set
       
  3540  *of operations in each of the iteration.
       
  3541  *
       
  3542  *@param  None
       
  3543  *@return void
       
  3544  */
       
  3545 void CMsvIndexAdapter::DoBackGroundOperationsL(TBool& aStopBackgroundOperation)
       
  3546 	{
       
  3547 	iFreePoolInstance->RoutineFreePoolCleanUpL();
       
  3548 	switch(iBackgroundOperationState)
       
  3549 		{
       
  3550 		case ERemoveDeletedEntries:
       
  3551 			{
       
  3552 			iBackgroundOperationState = EAllocateMemoryOperation;
       
  3553 			DoRemoveDeletedEntriesL();
       
  3554 			break;
       
  3555 			}
       
  3556 		case EAllocateMemoryOperation:
       
  3557 			{
       
  3558 			iBackgroundOperationState = ECheckBlockSize;
       
  3559 			if(CheckAndAllocateMemoryL())
       
  3560 				{
       
  3561 				iBackgroundOperationPerformed = 0;
       
  3562 				break;	
       
  3563 				}
       
  3564 			iBackgroundOperationPerformed++;	
       
  3565 			}
       
  3566 		case ECheckBlockSize:
       
  3567 			{
       
  3568 			iBackgroundOperationState = ENoOperation;	
       
  3569 			SplitBlockL();
       
  3570 			break;
       
  3571 			}
       
  3572 		case ENoOperation:
       
  3573 		default:
       
  3574 			{
       
  3575 			iBackgroundOperationState = ERemoveDeletedEntries;
       
  3576 			// The background operation has run multiple times, without doing
       
  3577 			// much work, so it can be stopped temporarily.
       
  3578 			if(iBackgroundOperationPerformed >= 5)
       
  3579 				{
       
  3580 				iBackgroundOperationPerformed = 0;
       
  3581 				aStopBackgroundOperation = ETrue;
       
  3582 				}
       
  3583 				
       
  3584 			break;
       
  3585 			}		
       
  3586 		}
       
  3587 
       
  3588 	}
       
  3589 
       
  3590 
       
  3591 
       
  3592 /**
       
  3593  *CheckAndAllocateMemory
       
  3594  *Will check the state of the free pool and allocate memory if required.
       
  3595  *Allocation will be done if 70% of the CMsvCacheEntries created are used.
       
  3596  *
       
  3597  *@return  TBool    ETrue,  if allocation has been done.
       
  3598  *		   			EFalse, if no allocation is done.			
       
  3599  */
       
  3600 TBool CMsvIndexAdapter::CheckAndAllocateMemoryL()
       
  3601 	{
       
  3602 	if(iFreePoolInstance->IsAllocationRequiredL())
       
  3603 		{
       
  3604 		iFreePoolInstance->AllocateMemoryL();
       
  3605 		return ETrue;
       
  3606 		}
       
  3607 	return EFalse;	
       
  3608 	}
       
  3609 	
       
  3610 
       
  3611 
       
  3612 	
       
  3613 /**
       
  3614  *SplitBlockL
       
  3615  *Will sort and split the blocks of CMsvCacheEntries.
       
  3616  *
       
  3617  *@return  void     		
       
  3618  */	
       
  3619 void CMsvIndexAdapter::SplitBlockL()
       
  3620 	{
       
  3621 	TDblQueIter<CMsvCacheVisibleFolder> dqIter(iFolderListHeader);
       
  3622 	dqIter.SetToFirst();
       
  3623 	CMsvCacheVisibleFolder* folderNode = NULL;
       
  3624 	while((folderNode = dqIter++)!=NULL)
       
  3625 		{
       
  3626 		folderNode->SplitBlockL();
       
  3627 		}
       
  3628 	}
       
  3629 
       
  3630 
       
  3631 
       
  3632 /**
       
  3633  *ForceDeleteEntry
       
  3634  *Deletes the TMsvEntry even if it is not in the cache.This does not require 
       
  3635  *the entry to be locked.
       
  3636  *
       
  3637  *@param aId  TMsvId, id ofthe entry to be deleted.
       
  3638  *@return TInt Any of the system wide error codes.
       
  3639  */
       
  3640 TInt CMsvIndexAdapter::ForceDeleteEntry(TMsvId aId)
       
  3641 	{
       
  3642 	TRAPD(leave, DoForceDeleteEntryL(aId));
       
  3643 	return leave;
       
  3644 	}
       
  3645 
       
  3646 
       
  3647 
       
  3648 /**
       
  3649  *DoForceDeleteEntryL
       
  3650  *Called from ForceDeleteEntry
       
  3651  *
       
  3652  *@param aId  TMsvId, id ofthe entry to be deleted.
       
  3653  *@return void 
       
  3654  */
       
  3655 void CMsvIndexAdapter::DoForceDeleteEntryL(TMsvId aId)
       
  3656 	{
       
  3657 	User::LeaveIfError(iErrorState);
       
  3658 	CMsvCacheVisibleFolder* folderNode = NULL;
       
  3659 	TDblQueIter<CMsvCacheVisibleFolder> dqIter(iFolderListHeader);
       
  3660 	
       
  3661 	if(!iDbAdapter)
       
  3662 		{
       
  3663 		User::Leave(ErrorState());
       
  3664 		}
       
  3665 	CMsvCacheEntry* entry = NULL;
       
  3666 	TBool releaseEntry = FindEntryL(aId, entry, EFalse);
       
  3667 	TMsvId parentId = entry->Entry().Parent();
       
  3668 	TRAPD(err, iDbAdapter->DeleteEntryL(aId));
       
  3669 	// If the entry does not exists in cache,
       
  3670 	// we need to release the entry explicitly.
       
  3671 	if(releaseEntry)
       
  3672 		{
       
  3673 		iFreePoolInstance->ReleaseEntry(entry, ETrue);
       
  3674 		User::LeaveIfError(err);
       
  3675 		}
       
  3676 	else
       
  3677 		{
       
  3678 		User::LeaveIfError(err);
       
  3679 		// Otherwise remove the entry from cache.
       
  3680 		dqIter.SetToFirst();
       
  3681 		while((folderNode = dqIter++)!=NULL)
       
  3682 			{
       
  3683 			TRAPD(err, folderNode->DeleteEntryL(aId, ETrue));	
       
  3684 			if(KErrNone == err)
       
  3685 				{
       
  3686 			 	break;
       
  3687 			 	}
       
  3688 			}
       
  3689 		}
       
  3690 	//Find the parent entry in cache and check for any children.
       
  3691 	//If there are no more children under the parent, then
       
  3692 	//reset the owner flag in cache and database.
       
  3693 	CMsvEntrySelection* children = new(ELeave)CMsvEntrySelection;
       
  3694 	CleanupStack::PushL(children);
       
  3695 	releaseEntry = FindEntryL(parentId, entry, EFalse);
       
  3696 	TRAP(err, 
       
  3697 		GetChildrenIdL(parentId, *children);
       
  3698 		if(0 == children->Count() && entry->Entry().Owner())
       
  3699 			{
       
  3700 			iDbAdapter->UpdateOwnerStatusL(parentId, entry->Entry(), EFalse);
       
  3701 			entry->Entry().SetOwner(EFalse);
       
  3702 			}
       
  3703 		);
       
  3704 	if(releaseEntry)
       
  3705 		{
       
  3706 		iFreePoolInstance->ReleaseEntry(entry, ETrue);
       
  3707 		}
       
  3708 	User::LeaveIfError(err);
       
  3709 	CleanupStack::PopAndDestroy(); //children
       
  3710 	}
       
  3711 
       
  3712 
       
  3713 
       
  3714 /**
       
  3715  *DeleteSelectionUsingTransaction
       
  3716  *Deletes a selection of TMsvEntries.This will also delete enteries that are not locked.
       
  3717  *
       
  3718  *@param aSelection  CMsvEntrySelection&, selection of the TMsvEntries.
       
  3719  @param TInt Any of the system wide error codes.
       
  3720  */
       
  3721 
       
  3722 TInt CMsvIndexAdapter::DeleteSelectionUsingTransaction(const CMsvEntrySelection& aSelection)
       
  3723 	{
       
  3724 	TRAPD(leave, DoDeleteSelectionUsingTransactionL(aSelection));
       
  3725 	return leave;
       
  3726 	}
       
  3727 
       
  3728 
       
  3729 /**
       
  3730  *DoDeleteSelectionUsingTransactionL
       
  3731  *Called from DeleteSelectionUsingTransaction.
       
  3732  *
       
  3733  *@param aSelection  CMsvEntrySelection&, selection of the TMsvEntries.
       
  3734  @param void
       
  3735  */
       
  3736 void CMsvIndexAdapter::DoDeleteSelectionUsingTransactionL(const CMsvEntrySelection& aSelection)
       
  3737 	{
       
  3738     User::LeaveIfError(iErrorState);
       
  3739     if(!iDbAdapter)
       
  3740         {
       
  3741         User::Leave(iErrorState);
       
  3742         }
       
  3743     
       
  3744     CMsvCacheVisibleFolder* folderNode = NULL;
       
  3745     TDblQueIter<CMsvCacheVisibleFolder> dqIter(iFolderListHeader);
       
  3746     const TInt count = aSelection.Count();
       
  3747     
       
  3748     if(!count)
       
  3749         {
       
  3750         return;
       
  3751         }   
       
  3752         
       
  3753     CMsvEntrySelection* children = new(ELeave)CMsvEntrySelection;
       
  3754     CleanupStack::PushL(children);
       
  3755     CMsvCacheEntry* entry = NULL;
       
  3756     TBool releaseEntry = FindEntryL(aSelection.At(0), entry, EFalse);
       
  3757     TMsvId parentId = entry->Entry().Parent();
       
  3758     if(releaseEntry)
       
  3759         {
       
  3760         iFreePoolInstance->ReleaseEntry(entry, ETrue);
       
  3761         }
       
  3762 
       
  3763     // Find the parent in the cache - we may need to update its owner status flag both in cache and DB.
       
  3764     TBool updateTheParent = ETrue;
       
  3765     TRAPD(err, releaseEntry = FindEntryL(parentId, entry, EFalse)); // can't let it leave - need to delete the child in any case.
       
  3766     if(err == KErrNotFound)
       
  3767         {
       
  3768         updateTheParent = EFalse;
       
  3769         if(releaseEntry)
       
  3770             {
       
  3771             iFreePoolInstance->ReleaseEntry(entry, ETrue);
       
  3772             }
       
  3773         }
       
  3774     else
       
  3775         {
       
  3776         // Get parent's children.
       
  3777         GetChildrenIdL(parentId, *children); // can leave - we'll let it leave as there's nothing to be rolled back now.
       
  3778         if(children->Count() > 1)
       
  3779             updateTheParent = EFalse;
       
  3780         }
       
  3781         
       
  3782     // Perform DB operations:
       
  3783     //      - Delete the entry.
       
  3784     //      - Update owner status flag of the parent.
       
  3785     iDbAdapter->DeleteEntryL(aSelection); // can leave - we'll let it leave as there's nothing to be rolled back now.
       
  3786     if(updateTheParent)
       
  3787         {
       
  3788         TRAP(err, iDbAdapter->UpdateOwnerStatusL(parentId, entry->Entry(), EFalse));
       
  3789         }
       
  3790     // Leave if DB operations fail. Cache is not touched.
       
  3791     if(err)
       
  3792         {
       
  3793         TRAP_IGNORE(iDbAdapter->RollbackTransactionL()); //
       
  3794         User::Leave(err);
       
  3795         }
       
  3796     else
       
  3797         {
       
  3798         if(updateTheParent)
       
  3799             {
       
  3800             entry->Entry().SetOwner(EFalse);
       
  3801             }
       
  3802         // Do the cache operations. These don't require any memory allocation and cannot fail.
       
  3803         for (TInt index=0; index<count; ++index)
       
  3804             {
       
  3805             // If the entry is a visible folder, then delete the node.
       
  3806             dqIter.SetToFirst(); 
       
  3807             while((folderNode = dqIter++)!=NULL)
       
  3808                 {
       
  3809                 if(folderNode->GetFolderId() == aSelection.At(index))
       
  3810                     {
       
  3811                     folderNode->iDlink.Deque();
       
  3812                     delete folderNode;
       
  3813                     break;
       
  3814                     }
       
  3815                 }
       
  3816             
       
  3817             // Delete the entry from under its parent visible folder.
       
  3818             dqIter.SetToFirst();
       
  3819             while((folderNode = dqIter++)!=NULL)
       
  3820                 {
       
  3821                 TRAPD(err, folderNode->DeleteEntryL(aSelection.At(index), ETrue));  
       
  3822                 if(KErrNone == err) 
       
  3823                     {
       
  3824                     break;
       
  3825                     }
       
  3826                 }
       
  3827             }
       
  3828         }
       
  3829     
       
  3830     // Update SearchSort delta cache.
       
  3831     TMsgType aType(EDeletedMsg);
       
  3832     if(CMSvSearchSortCacheManager::Instance()->iManagerEntry != NULL)
       
  3833         {   
       
  3834         if(CMSvSearchSortCacheManager::Instance()->iManagerEntry->Count()>0)
       
  3835             {
       
  3836             for(TInt ii =0; ii < aSelection.Count() ; ii ++)
       
  3837                 {
       
  3838                 CMsvSearchSortDeltaCache::Instance()->EntryInDeltaCache(aSelection[ii],aType);
       
  3839                 }
       
  3840             }
       
  3841         }
       
  3842 
       
  3843     CleanupStack::PopAndDestroy(); //children
       
  3844 	}
       
  3845 
       
  3846 
       
  3847 
       
  3848 /**
       
  3849  * BeginTransaction()
       
  3850  * 
       
  3851  * Starts a new DB transaction.
       
  3852  */
       
  3853 void CMsvIndexAdapter::BeginTransaction()
       
  3854 	{
       
  3855 	if(iDbAdapter)
       
  3856 		{
       
  3857 		TRAP_IGNORE(iDbAdapter->BeginTransactionL());
       
  3858 		}
       
  3859 	}
       
  3860 
       
  3861 
       
  3862 
       
  3863 /**
       
  3864  * CommitTransaction()
       
  3865  * 
       
  3866  * Commits an already opened transaction.
       
  3867  */
       
  3868 void CMsvIndexAdapter::CommitTransaction()
       
  3869 	{
       
  3870 	if(iDbAdapter)
       
  3871 		{
       
  3872 		TRAP_IGNORE(iDbAdapter->CommitTransactionL());
       
  3873 		}
       
  3874 	}
       
  3875 	
       
  3876 
       
  3877 
       
  3878 /**
       
  3879  * DoRemoveDeletedEntriesL()
       
  3880  * 
       
  3881  * Deletes all the entries whose PcSyncCount is 0 and delete flag is set.
       
  3882  */
       
  3883 TBool CMsvIndexAdapter::DoRemoveDeletedEntriesL()
       
  3884 	{
       
  3885 	CMsvCacheEntry* parent = NULL;
       
  3886 	CMsvCacheEntry* entry = NULL;
       
  3887 	CMsvCacheEntry* siblingEntry = NULL;
       
  3888 	TMsvId siblingId = KMsvNullIndexEntryId;
       
  3889 	TMsvId visibleFolder = KMsvNullIndexEntryId;
       
  3890 	TMsvId firstchildId = KMsvNullIndexEntryId;
       
  3891 	TInt commitCount = 1;
       
  3892 	
       
  3893 	// Find deleted folder
       
  3894 	FindEntryL(KMsvDeletedEntryFolderEntryId, parent, ETrue);
       
  3895 
       
  3896 	CMsvEntrySelection* selection = new(ELeave)CMsvEntrySelection;
       
  3897 	CleanupStack::PushL(selection);
       
  3898 
       
  3899 	// All deleted entries are a child of deleted folder
       
  3900 	if(iDbAdapter->GetFirstChildIdL(parent->Entry().Id(),firstchildId))
       
  3901 		{
       
  3902 		iDbAdapter->GetEntryL(firstchildId, entry, visibleFolder);
       
  3903 		}
       
  3904 					
       
  3905 	while(entry && commitCount > 0)
       
  3906 		{
       
  3907 		if (entry->Entry().PcSyncCount() <= 0)
       
  3908 			{
       
  3909 			// Add entry to list of things to be deleted
       
  3910 			__ASSERT_DEBUG(entry->Entry().Deleted(), PanicServer(EMsvDeletedFlagNotSet));
       
  3911 			
       
  3912 			User::LeaveIfError(LockEntryAndStore(entry->Entry().Id()));
       
  3913 			selection->AppendL(entry->Entry().Id());
       
  3914 			// Will the next entry be deleted?
       
  3915 			if(iDbAdapter->GetNextSiblingL(entry->Entry().Id(), parent->Entry().Id(), siblingId))
       
  3916 				{
       
  3917 				iDbAdapter->GetEntryL(siblingId, siblingEntry, visibleFolder);
       
  3918 				if(siblingEntry->Entry().PcSyncCount() > 0)
       
  3919 					{
       
  3920 					commitCount--;
       
  3921 					}
       
  3922 				}
       
  3923 			else
       
  3924 			    break;
       
  3925 			}
       
  3926 		iFreePoolInstance->ReleaseEntryWithoutTransaction(entry);
       
  3927 		entry = siblingEntry;
       
  3928 		}
       
  3929 
       
  3930 	if (selection->Count() > 0)
       
  3931 		{
       
  3932 		User::LeaveIfError(DeleteSelection(*selection));
       
  3933 		}
       
  3934 	CleanupStack::PopAndDestroy(); // selection
       
  3935 	
       
  3936 	// Possibly more to delete if we did not get to the end of the child list
       
  3937 	TBool retVal = entry != NULL;
       
  3938 	iFreePoolInstance->ReleaseEntryWithoutTransaction(entry);
       
  3939 	return retVal;
       
  3940 	}
       
  3941 
       
  3942 
       
  3943 
       
  3944 
       
  3945 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3946 
       
  3947 /**
       
  3948  * GetChildrenAllL()
       
  3949  *
       
  3950  * Code added for PREQ 557.
       
  3951  *
       
  3952  * The function is similar to function GetChildrenL(), but
       
  3953  * additionally it fetches entries from all the drive in the
       
  3954  * preferred drive list.
       
  3955  */
       
  3956 void CMsvIndexAdapter::GetChildrenAllL(TMsvId aId, CArrayPtr<const TMsvEntry>& aSelection, const TMsvSelectionOrdering& aOrdering, TUid aMtm, TBool aFilterByOwnerId, TSecureId aOwnerId)
       
  3957 	{
       
  3958 	TMsvPreferredDrive driveEntry;
       
  3959 	CMsvPreferredDriveList *driveList = CMsvPreferredDriveList::GetDriveList();
       
  3960 	for(TInt index=0; index<driveList->Count(); ++index)
       
  3961 		{
       
  3962 		driveEntry = (*driveList)[index];
       
  3963 		if(EMsvMessageStoreAvailableStatus == driveEntry.status)
       
  3964 			{
       
  3965 			GetChildrenL(MaskTMsvId(driveEntry.driveId, aId), aSelection, aOrdering, aMtm, aFilterByOwnerId, aOwnerId);
       
  3966 			}
       
  3967 		}
       
  3968 	}
       
  3969 
       
  3970 
       
  3971 
       
  3972 
       
  3973 /**
       
  3974  * GetChildrenIdAll()
       
  3975  *
       
  3976  * Code added for PREQ 557.
       
  3977  *
       
  3978  * The function is similar to function GetChildrenId(), but
       
  3979  * additionally it fetches entries from all the drive in the
       
  3980  * preferred drive list.
       
  3981  */
       
  3982 TInt CMsvIndexAdapter::GetChildrenIdAll(TMsvId aId, const CMsvEntryFilter& aFilter, CMsvEntrySelection& aSelection)
       
  3983 	{
       
  3984 	TSecureId dummy = KMsvServerId.iId;
       
  3985 	return GetChildrenIdAll(aId, aFilter, aSelection, EFalse, dummy);
       
  3986 	}
       
  3987 	
       
  3988 	 
       
  3989 
       
  3990 // Overloaded.
       
  3991 TInt CMsvIndexAdapter::GetChildrenIdAll(TMsvId aId, const CMsvEntryFilter& aFilter, CMsvEntrySelection& aSelection, TBool aFilterByOwnerId, TSecureId aOwnerId)
       
  3992 	{
       
  3993 	TInt err = KErrNone;
       
  3994 	TMsvPreferredDrive driveEntry;
       
  3995 	CMsvPreferredDriveList *driveList = CMsvPreferredDriveList::GetDriveList();
       
  3996 	for(TInt index=0; index<driveList->Count(); ++index)
       
  3997 		{
       
  3998 		driveEntry = (*driveList)[index];
       
  3999 		if(EMsvMessageStoreAvailableStatus == driveEntry.status)
       
  4000 			{
       
  4001 			err = GetChildrenId(MaskTMsvId(driveEntry.driveId, aId), aFilter, aSelection, aFilterByOwnerId, aOwnerId);
       
  4002 			if(KErrNone != err)
       
  4003 				{
       
  4004 				return err;
       
  4005 				}
       
  4006 			}
       
  4007 		}
       
  4008 	return KErrNone;
       
  4009 	}
       
  4010 	
       
  4011 
       
  4012 
       
  4013 /**
       
  4014  * RemoveDriveL()
       
  4015  * 
       
  4016  * This function is added in PREQ 557.
       
  4017  * @param TUint: The drive priority, which is also the index of drive 
       
  4018  *               entry in message server data structure.
       
  4019  * @param TBool: If the drive still remains in the preferred drive list.
       
  4020  * @return None.
       
  4021  * 
       
  4022  */
       
  4023 void CMsvIndexAdapter::RemoveDriveL(TUint aDriveId, TUint aDriveIndex, TBool aIsStdFolderVisible /*=ETrue */)
       
  4024 	{
       
  4025 	CMsvCacheVisibleFolder* folderNode = NULL;
       
  4026 	TDblQueIter<CMsvCacheVisibleFolder> dqIter(iFolderListHeader);
       
  4027 
       
  4028 	// Browse through the folder list.
       
  4029     dqIter.SetToFirst();
       
  4030     while ((folderNode = dqIter++) != NULL)
       
  4031         {
       
  4032         // If the folder is from the same drive.
       
  4033         // Caution: If the current drive is removed, 
       
  4034         // this will also include root and localService.
       
  4035         if(folderNode->GetDrive() == aDriveId)
       
  4036         	{
       
  4037        				folderNode->iDlink.Deque();
       
  4038        				delete folderNode;
       
  4039         			}
       
  4040         }	// while ((folderNode = dqIter++) != NULL)
       
  4041     
       
  4042     // If current drive is removed, 
       
  4043     // Remove localService entry as well.
       
  4044 
       
  4045 	// Detach the database and remove maxId entry.   	
       
  4046     if(!aIsStdFolderVisible)
       
  4047     	{
       
  4048     	iDbAdapter->DetachDBL(aDriveId);
       
  4049     	iMaxMsvIdList[aDriveId] = NULL;
       
  4050 
       
  4051 		CMsvPreferredDriveList::GetDriveList()->UpdateDriveIdL(aDriveIndex, KMsvInvalidDriveId);
       
  4052 		CMsvPreferredDriveList::GetDriveList()->UpdateDriveStatusL(aDriveIndex, EMsvDriveDiskNotAvailableStatus);
       
  4053 		}
       
  4054 	}
       
  4055 
       
  4056 
       
  4057 
       
  4058 
       
  4059 
       
  4060 /**
       
  4061  * AddDriveL()
       
  4062  * 
       
  4063  * This function is added in PREQ 557.
       
  4064  * @param TUint: The drive priority, which is also the index of drive 
       
  4065  *               entry in message server data structure.
       
  4066  * 
       
  4067  */
       
  4068 void CMsvIndexAdapter::AddDriveL(TUint aDrivePriority)
       
  4069 	{
       
  4070 	// Assign a new drive id.
       
  4071 	TUint driveId = GetNextAvailableDriveId();
       
  4072 	CMsvPreferredDriveList::GetDriveList()->UpdateDriveIdL(aDrivePriority, driveId);
       
  4073 	
       
  4074 	// Attach the database.
       
  4075 	TMsvId maxId;
       
  4076 	TMsvPreferredDrive driveEntry;
       
  4077 	CMsvPreferredDriveList::GetDriveList()->DriveInfoL(aDrivePriority, driveEntry);
       
  4078 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
       
  4079 	TRAPD(err, iDbAdapter->AttachDBL(driveEntry.driveNum, driveId, maxId, &iServer.MessageDBAdapter()));
       
  4080 #else
       
  4081 	TRAPD(err, iDbAdapter->AttachDBL(driveEntry.driveNum, driveId, maxId));
       
  4082 #endif
       
  4083 	WrapDBErrorL(err);
       
  4084 	
       
  4085 	// Insert the max Id in the list.
       
  4086 	iMaxMsvIdList[driveId] = ((maxId >= MaskTMsvId(driveId, KFirstFreeEntryId))? (maxId+1) : MaskTMsvId(driveId, KFirstFreeEntryId));
       
  4087 	}
       
  4088 
       
  4089 
       
  4090 
       
  4091 
       
  4092 /**
       
  4093  * ChangeDriveL()
       
  4094  * 
       
  4095  * This function is added in PREQ 557.
       
  4096  * @param TUint: The drive priority, which is also the index of drive 
       
  4097  *               entry in message server data structure.
       
  4098  * @param TBool: If the previous drive still remains in the preferred drive list.
       
  4099  * @return None.
       
  4100  * 
       
  4101  */
       
  4102 void CMsvIndexAdapter::ChangeDriveL(TUint aNewDriveIndex, TBool aIsStdFolderVisible /*= ETrue*/)
       
  4103 	{
       
  4104 	// Rule1: Remove all non-standard folder node of current drive.
       
  4105 	TInt oldCurrentDriveIndex = CMsvPreferredDriveList::GetDriveList()->CurrentDriveIndex();
       
  4106 	RemoveDriveL(KCurrentDriveId, oldCurrentDriveIndex, EFalse);
       
  4107 
       
  4108 	// If old drive should be visible, re-attach the drive.
       
  4109 	// This assigns a new drive id to the old current drive.
       
  4110 	if(aIsStdFolderVisible)
       
  4111 		{
       
  4112 		CMsvPreferredDriveList::GetDriveList()->UpdateDriveStatusL(oldCurrentDriveIndex, EMsvMessageStoreAvailableStatus);
       
  4113 		AddDriveL(oldCurrentDriveIndex);
       
  4114 		}
       
  4115 
       
  4116 	
       
  4117 	// Clear search sort cache db table
       
  4118 	TRAPD(err, GetDbAdapter()->ClearDBContentsL());
       
  4119 	WrapDBErrorL(err);
       
  4120 	
       
  4121 	
       
  4122 	// 3. Flush up entries from new current drive, 
       
  4123 	// if it is already attached.
       
  4124 	
       
  4125 	TMsvPreferredDrive driveEntry;
       
  4126 	CMsvPreferredDriveList::GetDriveList()->DriveInfoL(aNewDriveIndex, driveEntry);	
       
  4127 	if(KMsvInvalidDriveId != driveEntry.driveId)
       
  4128 		{
       
  4129 		RemoveDriveL(driveEntry.driveId, aNewDriveIndex, EFalse);
       
  4130 		}
       
  4131 	
       
  4132 
       
  4133 	// Assign a new drive Id to the drive.
       
  4134 	CMsvPreferredDriveList::GetDriveList()->UpdateDriveIdL(aNewDriveIndex, KCurrentDriveId);
       
  4135 	CMsvPreferredDriveList::GetDriveList()->UpdateDriveStatusL(aNewDriveIndex, EMsvMessageStoreAvailableStatus);
       
  4136 	
       
  4137 
       
  4138 	// Assign a new drive Id to the drive.
       
  4139 	CMsvPreferredDriveList::GetDriveList()->UpdateDriveIdL(aNewDriveIndex, KCurrentDriveId);
       
  4140 	CMsvPreferredDriveList::GetDriveList()->UpdateDriveStatusL(aNewDriveIndex, EMsvMessageStoreAvailableStatus);
       
  4141 	// --------- Attach the database and update MaxId.		
       
  4142 	TMsvId maxId;
       
  4143 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
  4144 	TRAP(err, iDbAdapter->AttachDBL(driveEntry.driveNum, KCurrentDriveId, maxId, &iServer.MessageDBAdapter()));
       
  4145 #else
       
  4146 	TRAP(err, iDbAdapter->AttachDBL(driveEntry.driveNum, KCurrentDriveId, maxId));
       
  4147 #endif
       
  4148 	WrapDBErrorL(err);
       
  4149 	
       
  4150 	// Insert the max Id in the list.
       
  4151 	iMaxMsvIdList[KCurrentDriveId] = ((maxId >= MaskTMsvId(KCurrentDriveId, KFirstFreeEntryId))? (maxId+1) : MaskTMsvId(KCurrentDriveId, KFirstFreeEntryId));		
       
  4152 
       
  4153 
       
  4154 	// ------- Create a root node and its children.
       
  4155 	TMsvId folderId = MaskTMsvId(KCurrentDriveId, KMsvRootIndexEntryId);
       
  4156 	
       
  4157 	// Add local service folder node in the folder list.
       
  4158 	iRootNode = CMsvCacheVisibleFolder::NewL(folderId);
       
  4159 	iFolderListHeader.AddFirst(*iRootNode);
       
  4160 	
       
  4161 	// Fetch children of root folder to cache.
       
  4162 	RPointerArray<CMsvCacheEntry> childEntryList;
       
  4163 	CleanupClosePushL(childEntryList);
       
  4164 	
       
  4165 	TRAP(err, iDbAdapter->GetChildrenL(folderId, childEntryList));
       
  4166 	WrapDBErrorL(err);
       
  4167 	iRootNode->AddEntryListL(childEntryList, ETrue);
       
  4168 	childEntryList.Reset();	
       
  4169 
       
  4170 	
       
  4171 	// ------- Create a local service node and its children.
       
  4172 	folderId = MaskTMsvId(KCurrentDriveId, KMsvLocalServiceIndexEntryId);
       
  4173 	
       
  4174 	// Add local service folder node in the folder list.
       
  4175 	CMsvCacheVisibleFolder* localServiceFolder = CMsvCacheVisibleFolder::NewL(folderId);
       
  4176 	iFolderListHeader.AddFirst(*localServiceFolder);
       
  4177 	
       
  4178 	TRAP(err, iDbAdapter->GetChildrenL(folderId, childEntryList));
       
  4179 	WrapDBErrorL(err);
       
  4180 	localServiceFolder->AddEntryListL(childEntryList, ETrue);
       
  4181 
       
  4182 	CleanupStack::PopAndDestroy();   // childEntryList.	
       
  4183 	}
       
  4184 
       
  4185 
       
  4186 
       
  4187 /**
       
  4188  * GetNextAvailableDriveId()
       
  4189  * 
       
  4190  * This function is added in PREQ 557.
       
  4191  * @param None: 
       
  4192  * @return TUint: The next available drive Id.
       
  4193  * 
       
  4194  */
       
  4195 TUint CMsvIndexAdapter::GetNextAvailableDriveId()
       
  4196 	{
       
  4197 	TMsvPreferredDrive driveEntry;
       
  4198 	TUint driveId = iFirstFreeDriveId;
       
  4199 	for(TUint index=0; index<8; index++)
       
  4200 		{
       
  4201 		TBool driveIdFound = EFalse;
       
  4202 		CMsvPreferredDriveList *driveList = CMsvPreferredDriveList::GetDriveList();
       
  4203 		for(TInt index=0; index<driveList->Count(); ++index)
       
  4204 			{
       
  4205 			driveEntry = (*driveList)[index];
       
  4206 			if(driveId == driveEntry.driveId)
       
  4207 				{
       
  4208 				driveIdFound = ETrue;
       
  4209 				break;
       
  4210 				}
       
  4211 			}
       
  4212 		if(EFalse == driveIdFound)
       
  4213 			{
       
  4214 			iFirstFreeDriveId = ((driveId)%7 ? (driveId+1) : 2);
       
  4215 			return driveId;
       
  4216 			}
       
  4217 		driveId = ((driveId)%7 ? (driveId+1) : 2);
       
  4218 		}
       
  4219 	return KErrNone;
       
  4220 	}
       
  4221 	
       
  4222 	
       
  4223 
       
  4224 /**
       
  4225  * ReloadCacheL()
       
  4226  * 
       
  4227  * This function is used by backup and restore functionality
       
  4228  * when it finds that DB being restored is changed. The function
       
  4229  * destroys the cache of the current drive and recreates it.
       
  4230  */
       
  4231 void CMsvIndexAdapter::ReloadCacheL()
       
  4232 	{
       
  4233 	TUint currDriveIndex = CMsvPreferredDriveList::GetDriveList()->CurrentDriveIndex();
       
  4234 	TDriveNumber currDriveNum = CMsvPreferredDriveList::GetDriveList()->CurrentDriveNumber();
       
  4235 
       
  4236 	// Attach the database.
       
  4237 	TMsvId maxId;
       
  4238 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
  4239 	TRAPD(err, iDbAdapter->AttachDBL(currDriveNum, KCurrentDriveId, maxId, &iServer.MessageDBAdapter()));
       
  4240 #else
       
  4241 	TRAPD(err, iDbAdapter->AttachDBL(currDriveNum, KCurrentDriveId, maxId));
       
  4242 #endif
       
  4243 	WrapDBErrorL(err);
       
  4244 	
       
  4245 	// Update the entry in drive list.
       
  4246 	CMsvPreferredDriveList::GetDriveList()->UpdateDriveStatusL(currDriveIndex, EMsvMessageStoreAvailableStatus);
       
  4247 
       
  4248 	// Insert the max Id in the list.
       
  4249 	iMaxMsvIdList[KCurrentDriveId] = ((maxId >= MaskTMsvId(KCurrentDriveId, KFirstFreeEntryId))? (maxId+1) : MaskTMsvId(KCurrentDriveId, KFirstFreeEntryId));		
       
  4250 
       
  4251 	TMsvId folderId = MaskTMsvId(KCurrentDriveId, KMsvRootIndexEntryId);
       
  4252 	
       
  4253 	// Add local service folder node in the folder list.
       
  4254 	iRootNode = CMsvCacheVisibleFolder::NewL(folderId);
       
  4255 	iFolderListHeader.AddFirst(*iRootNode);
       
  4256 	
       
  4257 	// Fetch children of root folder to cache.
       
  4258 	RPointerArray<CMsvCacheEntry> childEntryList;
       
  4259 	CleanupClosePushL(childEntryList);
       
  4260 	
       
  4261 	// Updating children under root node.	
       
  4262 	TRAP(err, iDbAdapter->GetChildrenL(folderId, childEntryList));
       
  4263 	WrapDBErrorL(err);
       
  4264 	iRootNode->AddEntryListL(childEntryList, ETrue);
       
  4265 	childEntryList.Reset();	
       
  4266 
       
  4267 	// Create a local service node and its children.
       
  4268 	folderId = MaskTMsvId(KCurrentDriveId, KMsvLocalServiceIndexEntryId);
       
  4269 	
       
  4270 	// Add local service folder node in the folder list.
       
  4271 	CMsvCacheVisibleFolder* localServiceFolder = CMsvCacheVisibleFolder::NewL(folderId);
       
  4272 	iFolderListHeader.AddFirst(*localServiceFolder);
       
  4273 	
       
  4274 	// Fetch children of localService folder to cache.
       
  4275 	TRAP(err, iDbAdapter->GetChildrenL(folderId, childEntryList));
       
  4276 	WrapDBErrorL(err);
       
  4277 	localServiceFolder->AddEntryListL(childEntryList, ETrue);
       
  4278 
       
  4279 	CleanupStack::PopAndDestroy();   // childEntryList.
       
  4280 	}
       
  4281 #endif 		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  4282 
       
  4283 
       
  4284 
       
  4285 
       
  4286 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
  4287 #ifdef _DEBUG
       
  4288 void CMsvIndexAdapter::PrintL()
       
  4289 	{
       
  4290 	_LIT8(KFolderId, "FOLDER ID: ");
       
  4291 	_LIT8(KDriveId, "      DRIVE ID: ");
       
  4292 	_LIT8(KComplete, "      COMPLETE FLAG: ");
       
  4293 	_LIT8(KFalse, "FALSE.");
       
  4294 	_LIT8(KTrue, "TRUE.");
       
  4295 	
       
  4296 	RFileLogger logger;
       
  4297 	CleanupClosePushL(logger);
       
  4298 	if (logger.Connect() == KErrNone)
       
  4299 		{
       
  4300 		logger.CreateLog(_L("msgs"), _L("Cache.txt"), EFileLoggingModeAppend);
       
  4301 		logger.SetDateAndTime(EFalse, EFalse);
       
  4302 		logger.Write(_L(" Message Index Cache Structure."));
       
  4303 		logger.Write(_L("--------------------------------"));
       
  4304 		logger.Write(_L(""));
       
  4305 		}
       
  4306 	
       
  4307 	CMsvCacheVisibleFolder* folderNode = NULL;
       
  4308 	TDblQueIter<CMsvCacheVisibleFolder> dqIter(iFolderListHeader);
       
  4309 
       
  4310 	dqIter.SetToFirst();
       
  4311 	while((folderNode = dqIter++)!=NULL)
       
  4312 		{
       
  4313 		RBuf8 text;
       
  4314 		CleanupClosePushL(text);
       
  4315 		text.CreateL(100);
       
  4316 		text.Append(KFolderId);
       
  4317 		text.AppendNum(folderNode->GetFolderId());
       
  4318 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  4319 		text.Append(KDriveId);
       
  4320 		text.AppendNum(folderNode->GetDrive());
       
  4321 #endif
       
  4322 		text.Append(KComplete);
       
  4323 		if(folderNode->IsComplete())
       
  4324 			{
       
  4325 			text.Append(KTrue);
       
  4326 			}
       
  4327 		else
       
  4328 			{
       
  4329 			text.Append(KFalse);
       
  4330 			}
       
  4331 		logger.Write(text);
       
  4332 		CleanupStack::PopAndDestroy();  // text
       
  4333 		folderNode->Print(logger);
       
  4334 		logger.Write(_L(""));		
       
  4335 		}
       
  4336 	logger.CloseLog();
       
  4337 	CleanupStack::PopAndDestroy();  // logger
       
  4338 	}
       
  4339 #endif			// #ifdef _DEBUG	
       
  4340 #endif			// #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
  4341