messagingfw/msgsrvnstore/server/src/msvcachevisiblefolder.Cpp
changeset 0 8e480a14352b
child 36 e7635922c074
equal deleted inserted replaced
-1:000000000000 0:8e480a14352b
       
     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 // CMSVCACHEVISIBLEFOLDER.CPP
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "msvcachevisiblefolder.h"
       
    19 #include "msventryfreepool.h"
       
    20 #include "msvcacheindextableentry.h"
       
    21 #include "msvdbadapter.h"
       
    22 #include "msvcacheentry.h"
       
    23 
       
    24 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)	
       
    25 	#include "msvindexadapter.h"
       
    26 #endif
       
    27 
       
    28 #define BLOCK_SIZE 64
       
    29 #define BLOCK_THRESHOLD 16
       
    30 
       
    31 /**
       
    32 Literal Definition
       
    33 */
       
    34 
       
    35 _LIT8(KId, "id ");
       
    36 _LIT8(KBetween, "between ");
       
    37 _LIT8(KAnd, " and ");
       
    38 _LIT8(KOr, " or ");
       
    39 _LIT8(KIn, " in ");
       
    40 _LIT8(KRtBrace, ") ");
       
    41 _LIT8(KLtBrace, "( ");
       
    42 _LIT8(KComma, ", ");
       
    43 _LIT8(KSemiColon, ";");
       
    44 _LIT8(KOrder, " order by id ASC");
       
    45 
       
    46 
       
    47 
       
    48 /**
       
    49 CMsvCacheVisibleFolder
       
    50 */
       
    51 const TInt CMsvCacheVisibleFolder::iOffset = _FOFF(CMsvCacheVisibleFolder, iDlink);
       
    52 
       
    53 
       
    54 /**
       
    55  NewL()
       
    56 @param TMsvId: Visible Folder TMsvId.
       
    57 @return The newly created Visible Folder.
       
    58  
       
    59 It returns an instance of CMsvCacheVisibleFolder class. 
       
    60 */
       
    61 CMsvCacheVisibleFolder* CMsvCacheVisibleFolder::NewL(TMsvId aId)
       
    62 	{
       
    63 	CMsvCacheVisibleFolder *self = new(ELeave) CMsvCacheVisibleFolder(aId);
       
    64 	return self;
       
    65 	}
       
    66 
       
    67 
       
    68 /**
       
    69  NewL()
       
    70 @param 	TMsvId: Visible Folder TMsvId.
       
    71 @param 	RPointerArray<CMsvCacheEntry>: Rpointer Reference to children Entries
       
    72 @return The newly created Visible Folder.
       
    73  		It returns an instance of CMsvCacheVisibleFolder class. 
       
    74 */
       
    75 CMsvCacheVisibleFolder* CMsvCacheVisibleFolder::NewL(TMsvId aId, RPointerArray<CMsvCacheEntry>& aEntries)
       
    76 	{
       
    77 	CMsvCacheVisibleFolder *self = new(ELeave) CMsvCacheVisibleFolder(aId);
       
    78 	CleanupStack::PushL(self);
       
    79 	self->ConstructL(aEntries);
       
    80 	CleanupStack::Pop();
       
    81 	return self;
       
    82 	}
       
    83 
       
    84 
       
    85 /**
       
    86  ~CMsvCacheVisibleFolder()
       
    87 @param 	None.
       
    88 @return None.
       
    89  		Destructor for the CMsvCacheVisibleFolder class.
       
    90 */
       
    91 CMsvCacheVisibleFolder::~CMsvCacheVisibleFolder()
       
    92 	{
       
    93 	iIndexTable.ResetAndDestroy();
       
    94 	iIndexTable.Close();
       
    95 	}
       
    96 
       
    97 
       
    98 /**
       
    99  CMsvCacheVisibleFolder()
       
   100 @param 	None.
       
   101 @return None.
       
   102  		Constructor for the CMsvCacheVisibleFolder class. 
       
   103 */
       
   104 CMsvCacheVisibleFolder::CMsvCacheVisibleFolder(TMsvId aId)
       
   105 :iFlags(EMsvCacheVisibleFolderClearFlag)
       
   106 	{
       
   107 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   108 	// Keep standard id unmasked.
       
   109 	if(IsStandardId(aId))
       
   110 		{
       
   111 		iVisibleFolderId = UnmaskTMsvId(aId);
       
   112 		}
       
   113 	else
       
   114 		{
       
   115 		iVisibleFolderId = aId;
       
   116 		}
       
   117 	// Store drive id information.
       
   118 	iDriveId = GetDriveId(aId);
       
   119 #else
       
   120 	iVisibleFolderId = aId;
       
   121 #endif
       
   122 	}
       
   123 
       
   124 
       
   125 /**
       
   126  ConstructL()
       
   127 @param 	RPointerArray<CMsvCacheEntry>& aEntries.
       
   128 @return None.
       
   129  		Two Phase constructor for adding the entries passed during the creation
       
   130  		of the CMsvCacheVisibleFolder object. 
       
   131 */
       
   132 void CMsvCacheVisibleFolder::ConstructL(RPointerArray<CMsvCacheEntry>& aEntries)
       
   133 	{
       
   134 	AddEntryListL(aEntries, ETrue);
       
   135 	}
       
   136 
       
   137 
       
   138 /**
       
   139  AddEntryL()
       
   140 @param CMsvCacheEntry&: CMsvCacheEntry Reference.
       
   141 @return none.
       
   142 
       
   143 The function Adds an Entry into the cache block
       
   144 01. check if the parent id of the entry exists; Incase if it is a child of a non-visible folder
       
   145 	we cannot add it unless the parent is present
       
   146 02. Check if The Parent Id of the Entry is same as the visible folder id.
       
   147 02.1. If yes, Set the Flag to Update the ChildMsvId array of the parent.
       
   148 03. If there is no Index Table created, Create a new index table entry
       
   149 	and add the entry into the table
       
   150 04. Iterate the Indextable entries and add the entry in the appropriate 
       
   151 	IndexTable entry Block and update the child msvid array of the parent
       
   152 	If the entry is not an immediate child.
       
   153 05. In case index table is not yet created, then there is a possibility that entry Id does not fall in
       
   154  the first block range but it can be added before the first block. In such case, add the entry in the first
       
   155  block itself and update the first block range.
       
   156 06. If the Entry doesnt fall in the range of any of the blocks add the Entry
       
   157 	in the last block and update the child MsvId array if the entry is not an immediate child.
       
   158 */
       
   159 void CMsvCacheVisibleFolder::AddEntryL(CMsvCacheEntry*& aEntry, TBool aReplace /* DEFAULT = EFalse */)
       
   160 	{
       
   161 	TBool updateChild=EFalse;
       
   162 	TInt noOfIndexTableEntries  = iIndexTable.Count();
       
   163 	TMsvId entryId = aEntry->Entry().Id();
       
   164 	TMsvId parentId = aEntry->Entry().Parent();
       
   165 	
       
   166 	
       
   167 	// 02. Check if The Parent Id of the Entry is same as the visible folder id.
       
   168 	if(parentId != iVisibleFolderId)
       
   169 		{
       
   170 		// 02.1. If yes, Set the Flag to Update the ChildMsvId array of the parent.
       
   171 		updateChild = ETrue;
       
   172 		}
       
   173 	
       
   174 	// 03. If there is no Index Table created, Create a new index table entry
       
   175 	//		and add the entry into the table
       
   176 	if(NULL == noOfIndexTableEntries )
       
   177 		{
       
   178 		CMsvCacheIndexTableEntry* tableEntry = CMsvCacheIndexTableEntry::NewLC(aEntry);
       
   179 		tableEntry->SetMinMsvIdRange(aEntry->GetId());
       
   180 		tableEntry->SetMaxMsvIdRange(aEntry->GetId());
       
   181 		if(aEntry->Entry().Parent() != iVisibleFolderId)
       
   182 			{
       
   183 			tableEntry->SetGrandChildPresent();
       
   184 			}
       
   185 		iIndexTable.AppendL(tableEntry);
       
   186 		CleanupStack::Pop();		
       
   187 		return;
       
   188 		}
       
   189 	
       
   190 	// 04. Iterate the Indextable entries and add the entry in the appropriate 
       
   191 	// 		IndexTable entry Block and update the child msvid array of the parent
       
   192 	//		If the entry is not an immediate child.
       
   193 	for(TInt index=0; index < noOfIndexTableEntries; ++index)
       
   194 		{
       
   195 	 	if(iIndexTable[index]->IsInRange(entryId))
       
   196 	 		{
       
   197 	 		iIndexTable[index]->AddEntryL(aEntry, aReplace);
       
   198 	 		if(aEntry->Entry().Parent() != iVisibleFolderId)
       
   199 				{
       
   200 				iIndexTable[index]->SetGrandChildPresent();
       
   201 				}	
       
   202 	 		if(updateChild)
       
   203 	 			{
       
   204 	 			UpdateChildMsvIdsL(parentId, entryId);
       
   205 	 			}
       
   206 	 		return;
       
   207 	 		}
       
   208 		//05. In case index table is not yet created, then there is a possibility that entry Id does not fall in
       
   209 		// the first block range but it can be added before the first block. In such case, add the entry in the first
       
   210 		// block itself and update the first block range.
       
   211 		if((NULL == index) && (entryId < iIndexTable[index]->GetMinMsvIdRange()))
       
   212 			{
       
   213 	 		iIndexTable[index]->AddEntryL(aEntry, aReplace);
       
   214 	 		if(aEntry->Entry().Parent() != iVisibleFolderId)
       
   215 				{
       
   216 				iIndexTable[index]->SetGrandChildPresent();
       
   217 				}	
       
   218 	 		if(updateChild)
       
   219 	 			{
       
   220 	 			UpdateChildMsvIdsL(parentId, entryId);
       
   221 	 			}
       
   222 	 		return;
       
   223 			}
       
   224 		}
       
   225 		
       
   226 	// 06. If the Entry doesnt fall in the range of any of the blocks add the Entry
       
   227 	// 		in the last block and update the child MsvId array if the entry is not an immediate child.
       
   228 	iIndexTable[noOfIndexTableEntries-1]->AddEntryL(aEntry, aReplace);
       
   229 	if(aEntry->Entry().Parent() != iVisibleFolderId)
       
   230 		{
       
   231 		iIndexTable[noOfIndexTableEntries-1]->SetGrandChildPresent();
       
   232 		}
       
   233 	if(entryId > iIndexTable[noOfIndexTableEntries-1]->GetMaxMsvIdRange())
       
   234 		{
       
   235 		iIndexTable[noOfIndexTableEntries-1]->SetMaxMsvIdRange(entryId);
       
   236 		}
       
   237 	if(updateChild)
       
   238 		{
       
   239 		UpdateChildMsvIdsL(parentId, entryId);
       
   240 		}
       
   241 	}
       
   242 
       
   243 
       
   244 /**
       
   245  AddEntryListL()
       
   246 @param RPointerArray<CMsvCacheEntry>&: Entries to be added under this visible folder which are in sorted order.
       
   247 @param TBool: Set to true if the passed array of CMsvCacheEntry contains the complete childrens of VisibleFolder
       
   248 @return none.
       
   249 
       
   250 The function Adds a set of Entries into the cache
       
   251 1. If entry list is NULL, return to the caller.
       
   252 2.check if the IndexTable is not created then,
       
   253 2.1 Yes, create the required number of index tables and append the entries in the appropriate blocks
       
   254 2.2 No, Check if getchildren has already been performed on this VisibleFolder
       
   255 2.2.1 Yes Assuming the input list is already sorted, Add the entries in the appropriate
       
   256  blocks depending on the range of each blocks
       
   257 2.2.1.1 The remaining entries should be put in the last block
       
   258 2.3 No, check if getchildren has'nt been performed on this VisibleFolder
       
   259 2.3.1 Check If index table exists
       
   260 2.3.1.1 Yes,Create a Copy of the existing index table entries
       
   261 2.3.1.2 create the required number of index tables and append the entries in the appropriate blocks
       
   262 2.3.1.3 check the copy of the previous list if any entry exists
       
   263 2.3.1.3 copy back only the locked entries or entires
       
   264  which are not immediate childrens of the visible folder or
       
   265  entries which are locked and release the remaining entries
       
   266 2.3.2 If indextable is not present add the entries in the appropriate blocks 
       
   267 */
       
   268 void CMsvCacheVisibleFolder::AddEntryListL(RPointerArray<CMsvCacheEntry>& aEntries, TBool aIsCompleteChildOfFolder /*DEFAULT = EFalse */)
       
   269 	{	
       
   270 	//1. If entry list is NULL, return to the caller.
       
   271 	TInt size = aEntries.Count();
       
   272 	if(size <= 0)
       
   273 		{
       
   274 		if(!size && aIsCompleteChildOfFolder)
       
   275 			{
       
   276 			SetComplete(ETrue);
       
   277 			}
       
   278 		return;
       
   279 		}
       
   280 
       
   281 	TBool isGrandChildrenAdded = EFalse;
       
   282 	if(aEntries[0]->Entry().Parent() != iVisibleFolderId)
       
   283 		{
       
   284 		isGrandChildrenAdded = ETrue;
       
   285 		}
       
   286 		
       
   287 	
       
   288 	//2.check if the IndexTable is not created then,
       
   289 	if(0 == iIndexTable.Count())
       
   290 		{
       
   291 		//2.1 Yes, create the required number of index tables and append the entries in the appropriate blocks
       
   292 		SplitAndAppendL(aEntries);
       
   293 		}
       
   294 	else
       
   295 		{
       
   296 		//2.2 No, Check if getchildren has already been performed on this VisibleFolder
       
   297 		if(IsComplete())		
       
   298 			{
       
   299 			TInt tmpIndex = 0, index = 0;
       
   300 			//2.2.1 Yes Assuming the input list is already sorted, Add the entries in the appropriate
       
   301 			// blocks depending on the range of each blocks
       
   302 			for(TInt tableIndex = 0; tableIndex < iIndexTable.Count(); ++tableIndex)
       
   303 				{
       
   304 				while((tmpIndex < size) && (iIndexTable[tableIndex]->GetMaxMsvIdRange() >= aEntries[tmpIndex]->GetId()))
       
   305 					{
       
   306 					++tmpIndex;
       
   307 					}
       
   308 				if(index != tmpIndex)
       
   309 					{
       
   310 					// No need to set Max/Min range, as IsComplete() is true.
       
   311 					iIndexTable[tableIndex]->AddEntrySetL(aEntries, index, tmpIndex-index);
       
   312 					if(isGrandChildrenAdded)
       
   313 						{
       
   314 						iIndexTable[tableIndex]->SetGrandChildPresent();
       
   315 						}
       
   316 					}	
       
   317 				
       
   318 				if(aIsCompleteChildOfFolder)
       
   319 					{
       
   320 					iIndexTable[tableIndex]->ClearDirty();
       
   321 					}
       
   322 				
       
   323 				if( tmpIndex >= size )
       
   324 					{
       
   325 					break;
       
   326 					}
       
   327 				index = tmpIndex;
       
   328 				
       
   329 				}
       
   330 			
       
   331 			//2.2.1.1 The remaining entries should be put in the last block
       
   332 			tmpIndex = size - tmpIndex;		// Amount of entries remaining.
       
   333 			if(tmpIndex > BLOCK_THRESHOLD)
       
   334 				{				
       
   335 				SplitAndAppendL(aEntries, index);
       
   336 				}
       
   337 			else if(0 != tmpIndex)	
       
   338 				{
       
   339 				TMsvId maxId = aEntries[size-1]->GetId();
       
   340 				iIndexTable[iIndexTable.Count()-1]->AddEntrySetL(aEntries, index, tmpIndex);
       
   341 				if(isGrandChildrenAdded)
       
   342 					{
       
   343 					iIndexTable[iIndexTable.Count()-1]->SetGrandChildPresent();
       
   344 					}
       
   345 				iIndexTable[iIndexTable.Count()-1]->SetMaxMsvIdRange(maxId);
       
   346 				}
       
   347 			}
       
   348 		//2.3 No, check if getchildren has'nt been performed on this VisibleFolder
       
   349 		else
       
   350 			{
       
   351 			//2.3.1 Check If index table exists
       
   352 			if(aIsCompleteChildOfFolder)
       
   353 				{
       
   354 				// 2.3.1.1 Yes,Create a Copy of the existing index table entries
       
   355 				RPointerArray<CMsvCacheIndexTableEntry> tmpTable;
       
   356 				CleanupClosePushL(tmpTable);
       
   357 				for(TInt index=0; index<iIndexTable.Count(); index++)
       
   358 					{
       
   359 					tmpTable.AppendL(iIndexTable[index]);
       
   360 					}
       
   361 				iIndexTable.Reset();
       
   362 				// 2.3.1.2 create the required number of index tables and append the entries in the appropriate blocks
       
   363 				SplitAndAppendL(aEntries);
       
   364 				// 2.3.1.3 check the copy of the previous list if any entry exists
       
   365 				while(tmpTable.Count())					
       
   366 					{
       
   367 					if(tmpTable[0]->BlockPtr() != NULL)
       
   368 						{
       
   369 						RPointerArray<CMsvCacheEntry>* blockPtr = tmpTable[0]->BlockPtr();
       
   370 						TInt count = blockPtr->Count();
       
   371 						while(count--)
       
   372 							{
       
   373 							// 2.3.1.3 copy back only the locked entries or entires
       
   374 							//which are not immediate childrens of the visible folder or
       
   375 							//entries which are locked and release the remaining entries
       
   376 							if( ((*blockPtr)[count]->Entry().Parent() != iVisibleFolderId) || !((*blockPtr)[count]->IsEntrySwappable()) )
       
   377 								{
       
   378 								AddEntryL((*blockPtr)[count], ETrue);
       
   379 								}
       
   380 							else
       
   381 								{
       
   382 								CMsvEntryFreePool::Instance()->ReleaseEntry((*blockPtr)[count]);
       
   383 								}
       
   384 							}
       
   385 						blockPtr->Reset();
       
   386 						blockPtr->Close();
       
   387 						}
       
   388 					delete tmpTable[0];
       
   389 					tmpTable.Remove(0);
       
   390 					}
       
   391 				tmpTable.Reset();	
       
   392 				CleanupStack::PopAndDestroy();
       
   393 				}
       
   394 			//2.3.2 If indextable is not present add the entries in the appropriate blocks 
       
   395 			else	
       
   396 				{
       
   397 				TInt size = aEntries.Count();
       
   398 				while(size--)
       
   399 					{
       
   400 					AddEntryL(aEntries[size]);
       
   401 					}
       
   402 				}	
       
   403 			}
       
   404 		}
       
   405 	
       
   406 	if(aIsCompleteChildOfFolder)
       
   407 		{
       
   408 		SetComplete(ETrue);
       
   409 		}
       
   410 	}
       
   411 
       
   412 
       
   413 /**
       
   414  SplitAndAppendL()
       
   415 @param RPointerArray<CMsvCacheEntry>&: Entries to be added under this visible folder which are in sorted order.
       
   416 @param TInt: Maximum range of the last block under this visible folder
       
   417 @return none.
       
   418 
       
   419 The function Adds a set Entries into the cache
       
   420 1. Calculate the number of blocks to be created.
       
   421 2. If remaining entries are less then BLOCK_THRESHOLD they will be appended to last block.
       
   422 3. Create new indextable entries and then add the child entries into the appropriate blocks
       
   423 4. If few entries are still left, append them to the last block.
       
   424 */
       
   425 void CMsvCacheVisibleFolder::SplitAndAppendL(RPointerArray<CMsvCacheEntry>& aEntryList, TInt aInitIndex /*(DEFAULT=0)*/)
       
   426 	{
       
   427 	//1. Calculate the number of blocks to be created.
       
   428 	TInt entriesToBeAdded = aEntryList.Count() - aInitIndex;
       
   429 	TInt blocksToCreate = entriesToBeAdded /(TInt) BLOCK_SIZE;
       
   430 	TInt aLastMaxRange = -1;
       
   431 	TBool isGrandChildrenAdded = EFalse;
       
   432 
       
   433 	TInt blocksCreated = iIndexTable.Count();
       
   434 	if(blocksCreated != 0)
       
   435 		{
       
   436 		aLastMaxRange = iIndexTable[blocksCreated-1]->GetMaxMsvIdRange();
       
   437 		}
       
   438 	if( aEntryList[aInitIndex]->Entry().Parent() != iVisibleFolderId)
       
   439 		{
       
   440 		isGrandChildrenAdded = ETrue;
       
   441 		}
       
   442 	
       
   443 	//2. If remaining entries are less then BLOCK_THRESHOLD they will be appended to last block.
       
   444 	if( (BLOCK_THRESHOLD < (entriesToBeAdded % BLOCK_SIZE)) || 
       
   445 		( (NULL == (blocksCreated+blocksToCreate)) && (entriesToBeAdded <= BLOCK_THRESHOLD) )
       
   446 	  )
       
   447 		{
       
   448 		++ blocksToCreate;
       
   449 		}
       
   450 
       
   451 	TInt blockSize = entriesToBeAdded/blocksToCreate;
       
   452 
       
   453 	//3. Create new indextable entries and then add the child entries into the appropriate blocks
       
   454 	for(TInt index = 0; index < blocksToCreate; ++index)
       
   455 		{
       
   456 		CMsvCacheIndexTableEntry* newTableEntry = CMsvCacheIndexTableEntry::NewLC(aEntryList, aInitIndex, blockSize);
       
   457 		if(isGrandChildrenAdded)
       
   458 			{
       
   459 			newTableEntry->SetGrandChildPresent();
       
   460 			}
       
   461 		TMsvId maxRange = aEntryList[aInitIndex+blockSize-1]->GetId();
       
   462 		newTableEntry->SetMinMsvIdRange(++aLastMaxRange);
       
   463 		newTableEntry->SetMaxMsvIdRange(maxRange);
       
   464 		iIndexTable.AppendL(newTableEntry);
       
   465 		aLastMaxRange = maxRange;
       
   466 		aInitIndex += blockSize;
       
   467 		
       
   468 		CleanupStack::Pop();
       
   469 		}
       
   470 
       
   471 	//4. If few entries are still left, append them to the last block.
       
   472 	entriesToBeAdded = aEntryList.Count() - aInitIndex;
       
   473 	if(entriesToBeAdded > 0)	
       
   474 		{
       
   475 		CMsvCacheIndexTableEntry* newTableEntry = iIndexTable[iIndexTable.Count()-1];
       
   476 		newTableEntry->AddEntrySetL(aEntryList, aInitIndex, entriesToBeAdded);
       
   477 		if(isGrandChildrenAdded)
       
   478 			{
       
   479 			newTableEntry->SetGrandChildPresent();
       
   480 			}
       
   481 		if(newTableEntry->GetMaxMsvIdRange() < aEntryList[aEntryList.Count()-1]->GetId())
       
   482 			{
       
   483 			newTableEntry->SetMaxMsvIdRange(aEntryList[aEntryList.Count()-1]->GetId());
       
   484 			}
       
   485 		}
       
   486 	}
       
   487 
       
   488 
       
   489 
       
   490 /**
       
   491  GetEntry()
       
   492 @param TMsvId: TMsvId for the Entry to be fetched
       
   493 @param CMsvCacheEntry&: CMsvCacheEntry Reference.
       
   494 @return TBool: Cache Hit or Cache Miss.
       
   495  
       
   496 The function Gets an Entry from the cache block
       
   497 1. Find the IndexTable entry where the Range of the TMsvId falls.
       
   498 2. Get the Entry in the Block to which it belongs
       
   499 */
       
   500 TBool CMsvCacheVisibleFolder::GetEntry(TMsvId aId, CMsvCacheEntry*& aEntry)
       
   501 	{
       
   502 	// 1. Find the IndexTable entry where the Range of the TMsvId falls.
       
   503 	for(TInt index=0; index < iIndexTable.Count(); ++index)
       
   504 		{
       
   505 		if(iIndexTable[index]->IsInRange(aId))
       
   506 	 		{
       
   507 	 		//2. Get the Entry in the Block to which it belongs
       
   508 			return(iIndexTable[index]->GetEntry(aId, aEntry));
       
   509 	 		}
       
   510 	 	}
       
   511 	return EFalse;
       
   512 	}
       
   513 
       
   514 
       
   515 /**
       
   516  GetChildren()
       
   517 @param TMsvId: TMsvId of the Parent Entry whose children are to be fetched.
       
   518 @param RPointerArray<const CMsvCacheEntry>&: Array to fill childrens
       
   519 @return TBool: Cache Hit or Cache Miss.
       
   520  
       
   521 The function Gets the childrens of the parent from the cache
       
   522 1. Check if the Parent Id is same as the Visible Folder
       
   523 1.1 yes, check if getchildren has'nt already been performed on this visible folder entry
       
   524 	or all the blocks present are dirty.
       
   525 1.1.1 Then Fetch and fill all the childrens then return the same to the caller
       
   526 1.2 yes, check if getchildren has beeb performed on this visible folder
       
   527 1.2.1 yes, only few blocks are dirty, so fetch and fill the dirty blocks
       
   528 2. If the if the Parent Id is not same as the Visible Folder
       
   529 2.1 check if the parent of the children is present
       
   530 2.2 If parent is a visible folder
       
   531 2.2.1 Yes, then return Efalse to the caller stating that
       
   532 the parent is a visible folder
       
   533 2.3 Check if Getchildren has'nt been performed on the parent
       
   534 2.3.1 Yes, Fetch and fill the childrens of the Parent from DB
       
   535 2.4 Check If GetChildren has been already performed
       
   536 2.4.1 If childrens are available in the cache get them
       
   537 2.4.2 else fetch the children from DB add them to cache
       
   538 */
       
   539 TBool CMsvCacheVisibleFolder::GetChildrenL(TMsvId aId, CMsvDBAdapter* aDbAdapter, RPointerArray<CMsvCacheEntry>& aEntries)
       
   540 	{
       
   541 	 SetGetChildrenFromVisibleFolder(ETrue);
       
   542 	//1. Check if the Parent Id is same as the Visible Folder
       
   543 	TMsvId id = aId;
       
   544 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   545 	if(IsStandardId(aId))
       
   546 		{
       
   547 		id = UnmaskTMsvId(aId);
       
   548 		}
       
   549 #endif
       
   550 	if(id == iVisibleFolderId)
       
   551 		{
       
   552 		//1.1 yes, check if getchildren has'nt already been performed on this visible folder entry
       
   553 		//	or all the blocks present are dirty.
       
   554 		if( (!IsComplete()) || (IsComplete() && IsAllBlocksDirty()) )
       
   555 			{
       
   556 			//1.1.1 Then Fetch and fill all the childrens then return the same to the caller
       
   557 			aDbAdapter->GetChildrenL(id, aEntries);
       
   558 			TInt excessEntries = CMsvEntryFreePool::Instance()->ExcessMemoryAllocated();
       
   559 			if(excessEntries)
       
   560 				{
       
   561 				TInt index = 0;
       
   562 				RPointerArray<CMsvCacheEntry> entryList;
       
   563 				CleanupClosePushL(entryList);				
       
   564 				for(; index<excessEntries; index++)
       
   565 					{
       
   566 					CMsvEntryFreePool::Instance()->RecordExcessMemoryL(aEntries[index]);					
       
   567 					}
       
   568 				for(; index<aEntries.Count(); index++)
       
   569 					{
       
   570 					entryList.AppendL(aEntries[index]);
       
   571 					}
       
   572 				AddEntryListL(entryList, EFalse);
       
   573 				CleanupStack::PopAndDestroy();
       
   574 				}
       
   575 			else
       
   576 				{
       
   577 				AddEntryListL(aEntries, ETrue);
       
   578 				}
       
   579 			SetGetChildrenFromVisibleFolder(EFalse);
       
   580 			return ETrue;
       
   581 			}
       
   582 		//1.2 yes, check if getchildren has beeb performed on this visible folder
       
   583 		if(IsComplete())
       
   584 			{
       
   585 			//1.2.1 yes, only few blocks are dirty, so fetch and fill the dirty blocks
       
   586 			RBuf8 buf;
       
   587 			buf.Create(2000);
       
   588 			CleanupClosePushL(buf);
       
   589 			TBool isDBOperationReqd = EFalse;
       
   590 			for(TInt index=0; index < iIndexTable.Count(); ++index)
       
   591 				{
       
   592 				if(iIndexTable[index]->IsDirty())
       
   593 					{
       
   594 					if(!isDBOperationReqd)
       
   595 						{
       
   596 						buf.Append(KAnd);		
       
   597 						buf.Append(KLtBrace);
       
   598 						isDBOperationReqd = ETrue;
       
   599 						}
       
   600 					else
       
   601 						{
       
   602 						buf.Append(KOr);	
       
   603 						}
       
   604 					buf.Append(KId);
       
   605 					buf.Append(KBetween);
       
   606 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   607 					buf.AppendNum(UnmaskTMsvId(iIndexTable[index]->GetMinMsvIdRange()));
       
   608 					buf.Append(KAnd);
       
   609 					buf.AppendNum(UnmaskTMsvId(iIndexTable[index]->GetMaxMsvIdRange()));
       
   610 #else
       
   611 					buf.AppendNum(iIndexTable[index]->GetMinMsvIdRange());
       
   612 					buf.Append(KAnd);
       
   613 					buf.AppendNum(iIndexTable[index]->GetMaxMsvIdRange());
       
   614 #endif	// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   615 					}
       
   616 				}
       
   617 			if(isDBOperationReqd)	
       
   618 				{
       
   619 				buf.Append(KRtBrace);
       
   620 				buf.Append(KOrder);
       
   621 				buf.Append(KSemiColon);
       
   622 				RPointerArray<CMsvCacheEntry> childEntries;
       
   623 				CleanupClosePushL(childEntries);
       
   624 				aDbAdapter->GetChildrenL(buf, id, childEntries);
       
   625 				AddEntryListL(childEntries);
       
   626 				CleanupStack::PopAndDestroy();
       
   627 				}
       
   628 			for(TInt index=0; index < iIndexTable.Count(); ++index)
       
   629 				{
       
   630 				iIndexTable[index]->GetChildrenL(id, aEntries);
       
   631 				iIndexTable[index]->ClearDirty();
       
   632 				}
       
   633 			CleanupStack::PopAndDestroy(); 
       
   634 			SetGetChildrenFromVisibleFolder(EFalse);
       
   635 			return ETrue;
       
   636 			}
       
   637 		}
       
   638 	//2. If the if the Parent Id is not same as the Visible Folder
       
   639 	else 
       
   640 		{
       
   641 		CMsvCacheEntry* parentEntry;
       
   642 		//2.1 check if the parent of the children is present
       
   643 		if(!GetEntry(id, parentEntry))
       
   644 			{
       
   645 			User::Leave(KErrNotFound);
       
   646 			}
       
   647 		
       
   648 		//2.2 If parent is a visible folder
       
   649 		if(parentEntry->Entry().VisibleFolderFlag())
       
   650 			{
       
   651 			//2.2.1 Yes, then return Efalse to the caller stating that
       
   652 			//	the parent is a visible folder
       
   653 			SetGetChildrenFromVisibleFolder(EFalse);
       
   654 			return EFalse;
       
   655 			}
       
   656 		
       
   657 		//2.3 Check if Getchildren hasn't been performed on the parent
       
   658 		if(NULL == parentEntry->ChildIdArray())
       
   659 			{
       
   660 			//2.3.1 Yes, Fetch and fill the childrens of the Parent from DB
       
   661 			aDbAdapter->GetChildrenL(id, aEntries);
       
   662 			TInt excessEntries = CMsvEntryFreePool::Instance()->ExcessMemoryAllocated();
       
   663 			if(excessEntries)
       
   664 				{
       
   665 				TInt index = 0;
       
   666 				RPointerArray<CMsvCacheEntry> entryList;
       
   667 				CleanupClosePushL(entryList);				
       
   668 				for(; index<excessEntries; index++)
       
   669 					{
       
   670 					CMsvEntryFreePool::Instance()->RecordExcessMemoryL(aEntries[index]);					
       
   671 					}
       
   672 				for(; index<aEntries.Count(); index++)
       
   673 					{
       
   674 					entryList.AppendL(aEntries[index]);
       
   675 					}
       
   676 				AddEntryListL(entryList);
       
   677 				CleanupStack::PopAndDestroy();
       
   678 				}
       
   679 			else
       
   680 				{
       
   681 				AddEntryListL(aEntries);
       
   682 				}
       
   683 			RArray<TMsvId>* childIds = new(ELeave) RArray<TMsvId>;
       
   684 			CleanupStack::PushL(childIds);
       
   685 			CleanupClosePushL(*childIds);
       
   686 			for(TInt index=0; index < aEntries.Count(); ++index)
       
   687 				{
       
   688 				childIds->AppendL(aEntries[index]->GetId());
       
   689 				}
       
   690 			parentEntry->SetChildIdArray(childIds);
       
   691 			CleanupStack::Pop(2);
       
   692 			}
       
   693 		// 2.4 Check If GetChildren has been already performed
       
   694 		else
       
   695 			{
       
   696 			RBuf8 buf;
       
   697 			buf.Create(2000);
       
   698 			CleanupClosePushL(buf);
       
   699 			CMsvCacheEntry* childEntry;
       
   700 			TBool isDBOperationReqd = EFalse;
       
   701 			for(TInt index=0; index< parentEntry->ChildIdArray()->Count(); ++index)
       
   702 				{
       
   703 				//2.4.1 If childrens are available in the cache get them
       
   704 				if(GetEntry((*parentEntry->ChildIdArray())[index], childEntry))
       
   705 					{
       
   706 					aEntries.AppendL(childEntry);
       
   707 					}
       
   708 				//2.4.2 else fetch the children from DB add them to cache
       
   709 				else
       
   710 					{
       
   711 					if(isDBOperationReqd)
       
   712 						{
       
   713 						buf.Append(KComma);	
       
   714 						}
       
   715 					if(!isDBOperationReqd)
       
   716 						{
       
   717 						buf.Append(KAnd);		
       
   718 						buf.Append(KId);
       
   719 						buf.Append(KIn);
       
   720 						buf.Append(KLtBrace);						
       
   721 						isDBOperationReqd = ETrue;
       
   722 						}
       
   723 					#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   724 						buf.AppendNum(UnmaskTMsvId((*parentEntry->ChildIdArray())[index]));
       
   725 					#else
       
   726 						buf.AppendNum((*parentEntry->ChildIdArray())[index]);
       
   727 					#endif 	
       
   728 					}
       
   729 				}
       
   730 			if(isDBOperationReqd)
       
   731 				{
       
   732 				buf.Append(KRtBrace);
       
   733 				buf.Append(KSemiColon);
       
   734 				
       
   735 				RPointerArray<CMsvCacheEntry> childEntries;
       
   736 				CleanupClosePushL(childEntries);
       
   737 				aDbAdapter->GetChildrenL(buf, parentEntry->GetId(), childEntries);
       
   738 				for(TInt index=0; index<childEntries.Count(); ++index)
       
   739 					{
       
   740 					aEntries.AppendL(childEntries[index]);
       
   741 					}
       
   742 				AddEntryListL(childEntries);	
       
   743 				CleanupStack::PopAndDestroy(); 
       
   744 				}
       
   745 			CleanupStack::PopAndDestroy(); 
       
   746 			}
       
   747 		}
       
   748 		SetGetChildrenFromVisibleFolder(EFalse);
       
   749 		return ETrue;
       
   750 	}
       
   751 
       
   752 
       
   753 /**
       
   754  * GetChildrenIdL()
       
   755  * @param CMsvEntrySelection& (OUT): List of child TMsvIds of the current visible
       
   756  * 									 folder.
       
   757  * @return TBool: Returns ETrue, if children list can be returned, otherwise EFalse.
       
   758  * 
       
   759  * The function returns list of child TMsvId of the current visible folder.
       
   760  * It will return ETrue if it is possible to return all child IDs, otherwise
       
   761  * it returns EFalse (In case when not all children of the folder is present
       
   762  * in cache i.e. IsComplete() is false. OR in case when some of the blocks 
       
   763  * are dirty.).
       
   764  */
       
   765 TBool CMsvCacheVisibleFolder::GetChildrenIdL(CMsvEntrySelection& aSelection)
       
   766 	{
       
   767 	if(IsComplete())
       
   768 		{
       
   769 		for(TInt index=0; index < iIndexTable.Count(); ++index)
       
   770 			{
       
   771 			if(iIndexTable[index]->IsDirty())
       
   772 				{
       
   773 				return EFalse;
       
   774 				}
       
   775 			}
       
   776 		for(TInt index=0; index < iIndexTable.Count(); ++index)
       
   777 			{
       
   778 			CMsvCacheIndexTableEntry* entry = iIndexTable[index];
       
   779 			TInt blockSize = entry->Size();
       
   780 			RPointerArray<CMsvCacheEntry>* blkPtr = entry->BlockPtr();
       
   781 			// 1. Check if there are grandchildren present in the block.
       
   782 			if(entry->IsGrandChildPresent())
       
   783 				{
       
   784 				// 1.1 If yes, then fetch only those entries with parent Id as aParentId.
       
   785 				//       If the array of entries is NULL, then allocate space for it.
       
   786 				for(TInt index1 = 0 ; index1 < blockSize ; ++index1)
       
   787 					{
       
   788 					if((*blkPtr)[index1]->Entry().Parent() == iVisibleFolderId)
       
   789 						{
       
   790 						aSelection.AppendL((*blkPtr)[index1]->GetId());
       
   791 						}
       
   792 					}
       
   793 				} //if(IsGrandChildPresent())
       
   794 			else
       
   795 				{
       
   796 				// 1.2 If not, then return a copy of the whole block.
       
   797 				for(TInt index1 = 0 ; index1 < blockSize ; ++index1)
       
   798 					{
       
   799 					aSelection.AppendL((*blkPtr)[index1]->GetId());
       
   800 					}
       
   801 				} //else
       
   802 			}
       
   803 		return ETrue;
       
   804 		}
       
   805 	else
       
   806 		{
       
   807 		return EFalse;
       
   808 		}
       
   809 	}
       
   810 
       
   811 
       
   812 
       
   813 /**
       
   814  DeleteEntry()
       
   815 @param TMsvId: TMsvId of the Entry to be deleted.
       
   816 @param aForceDelete TBool, it indicates whether the entry needs to be locked while deleting.
       
   817 @return TInt: Error Status.
       
   818  
       
   819 The function deletes an Entry from the Cache.
       
   820 1. Iterate through the IndexTable Entries.
       
   821 2. Find the IndexTable where the entry is present
       
   822 3. Delete the Entry and update the ChildMsvId array of the parent if delete successful
       
   823 4. If the its the last Entry in the IndexTable and the complete flag is False
       
   824 	delete the IndexTable entry
       
   825 */
       
   826 void CMsvCacheVisibleFolder::DeleteEntryL(TMsvId aId, TBool aForceDelete)
       
   827 	{
       
   828 	TMsvId parentIdOfEntry;
       
   829 	
       
   830 	// 1. Iterate through the IndexTable Entries.
       
   831 	for(TInt index=0; index < iIndexTable.Count(); ++index)
       
   832 		{
       
   833 		// 2. Find the IndexTable where the entry is present
       
   834 		if(iIndexTable[index]->IsInRange(aId))
       
   835 			{
       
   836 			// 3. Delete the Entry and update the ChildMsvId array of the parent if delete successful
       
   837 			iIndexTable[index]->DeleteEntryL(aId, parentIdOfEntry, aForceDelete);
       
   838 			if(parentIdOfEntry != iVisibleFolderId)
       
   839 				{
       
   840 				UpdateChildMsvIdsL(parentIdOfEntry, aId, EFalse);
       
   841 				}
       
   842 			
       
   843 			// 4. If the its the last Entry in the IndexTable and the complete flag is False
       
   844 			//		delete the IndexTable entry
       
   845 			if(NULL == iIndexTable[index]->Size() )
       
   846 				{
       
   847 				if((index+1) < iIndexTable.Count())
       
   848 					{
       
   849 					iIndexTable[index+1]->SetMinMsvIdRange(iIndexTable[index]->GetMinMsvIdRange());
       
   850 					}
       
   851 				delete iIndexTable[index];
       
   852 				iIndexTable.Remove(index);
       
   853 				}
       
   854 			return;
       
   855 			}
       
   856 		}
       
   857 	User::Leave(KErrNotFound);
       
   858 	}
       
   859 
       
   860 
       
   861 /**
       
   862  DeleteEntryList()
       
   863 @param CMsvEntrySelection& aEntrySelection.
       
   864 @return TInt: Error Status.
       
   865  
       
   866 The function deletes a set of Entries from the Cache.
       
   867 */
       
   868 void CMsvCacheVisibleFolder::DeleteEntryListL(CMsvEntrySelection& aEntrySelection)
       
   869 	{
       
   870 	TInt count = aEntrySelection.Count();
       
   871 	for(TInt index=0; index < count; ++index)
       
   872 		{
       
   873 		DeleteEntryL(aEntrySelection.At(index));
       
   874 		}
       
   875 	}
       
   876 
       
   877 
       
   878 /**
       
   879  IsAllBlocksDirty()
       
   880 @param None.
       
   881 @return TBool: Is All the IndexTableEntries dirty or not.
       
   882  
       
   883 The function checks whether all the IndexTable Entry are dirty.
       
   884 1. Iterate through all the IndexTable Entries.
       
   885 2. Check if the IndexTable Entry is Not Dirty.
       
   886 2.1 Yes, Then Return EFalse; stating that all IndexTable Entries are not dirty.
       
   887 2.2 No, Then Return ETrue; stating that all IndexTable Entries are dirty.
       
   888 */
       
   889 TBool CMsvCacheVisibleFolder::IsAllBlocksDirty() const
       
   890 	{
       
   891 	// 1. If index table size is zero, return EFalse.
       
   892 	if(0 == iIndexTable.Count())
       
   893 		{
       
   894 		return (EFalse);
       
   895 		}	
       
   896 	
       
   897 	// 2. Iterate through all the IndexTable Entries.
       
   898 	for(TInt index=0; index <  iIndexTable.Count(); ++index)
       
   899 		{
       
   900 		// 3. Check if the IndexTable Entry is Not Dirty.
       
   901 		if(!(iIndexTable[index]->IsDirty()))
       
   902 			{
       
   903 			// 3.1 Yes, Then Return EFalse; stating that all IndexTable Entries are not dirty.
       
   904 			return(EFalse);
       
   905 			}
       
   906 		}
       
   907 	// 3.2 No, Then Return ETrue; stating that all IndexTable Entries are dirty.
       
   908 	return(ETrue);
       
   909 	}
       
   910 
       
   911 
       
   912 /**
       
   913  EntryExists()
       
   914 @param TMsvId: TMsvId of the Entry.
       
   915 @return TBool: Entry Exists or not.
       
   916  
       
   917 The function checks whether an Entry with the Specified TMsvId Exists in the cache.
       
   918 1. Check if the TMsvId is same as the visible folder id.
       
   919 1.1. If they are same then return ETrue stating that id is present
       
   920 2. Else Check through all the IndexTableEntries and check if the Entry Exists.
       
   921 3. Else Return Entry is not Present.
       
   922 */
       
   923 TBool CMsvCacheVisibleFolder::EntryExists(TMsvId aId) const
       
   924 	{
       
   925 	// 1. Check if the TMsvId is same as the visible folder id.
       
   926  	if(aId == iVisibleFolderId)
       
   927  		{
       
   928  		// 1.1. If they are same then return ETrue stating that id is present
       
   929 		return(ETrue);
       
   930 		}
       
   931  	
       
   932  	// 2. Else Check through all the IndexTableEntries and check if the Entry
       
   933  	//		Exists.
       
   934  	for(TInt index=0; index < iIndexTable.Count(); ++index)
       
   935  		{
       
   936  		if(iIndexTable[index]->EntryExists(aId))
       
   937  			{
       
   938  			return(ETrue);
       
   939  			}
       
   940  		}
       
   941  	
       
   942  	// 3. Else Return Entry is not Present.
       
   943  	return(EFalse);
       
   944    	}
       
   945 
       
   946 
       
   947 /**
       
   948  UpdateChildMsvIdsL()
       
   949 @param TMsvId  aParentId :  parent Id whose MsvId Array has to be updated.
       
   950 @param TMsvId AChildId : Child Id which as to be updated in the MsvId Array.
       
   951 @param TBool aAppend : Whether the Entry has to be appended or removed from the Parent MsvId Array.
       
   952 @return none.
       
   953  
       
   954 The function Updates the Owner with its child TMsvIds.
       
   955 1. Iterate through the index Table entri
       
   956 2.Find the indexTable where the entry is present
       
   957 3. Update the Parent with the child TMsvIds
       
   958 */
       
   959 void CMsvCacheVisibleFolder::UpdateChildMsvIdsL(TMsvId aParentId, TMsvId aChildId, TBool aAppend /* DEFAULT = ETrue */)
       
   960 	{
       
   961 	// 1. Iterate through the index Table entries
       
   962 	for(TInt index = 0; index < iIndexTable.Count(); ++index)
       
   963 		{
       
   964 		// 2.Find the indexTable where the entry is present
       
   965 		if(iIndexTable[index]->IsInRange(aParentId))
       
   966 			{
       
   967 			// 3. Update the Parent with the child TMsvIds
       
   968 			iIndexTable[index]->UpdateChildMsvIdsL(aParentId, aChildId, aAppend);
       
   969 			return;
       
   970 			}
       
   971 		}
       
   972 	}
       
   973 
       
   974 
       
   975 /**
       
   976  UpdateChildMsvIdsL()
       
   977 @param RPointerArray<CMsvCacheEntry>&: CMsvCacheEntry Pointer Array.
       
   978 @return none.
       
   979  
       
   980 The function Updates the Owner with its child TMsvIds.
       
   981 1. Find the IndexTableEntry where the parent is present.
       
   982 2. Update the Parent with the child TMsvIds
       
   983 */
       
   984 void CMsvCacheVisibleFolder::UpdateChildMsvIdsL(RPointerArray<CMsvCacheEntry>& aEntries)
       
   985 	{
       
   986 	// 1. Find the IndexTableEntry where the parent is present.
       
   987 	for(TInt index=0; index < iIndexTable.Count(); ++index)
       
   988 		{
       
   989 		if(iIndexTable[index]->IsInRange(aEntries[0]->Entry().Parent()))
       
   990 			{
       
   991 			// 2. Update the Parent with the child TMsvIds
       
   992 			iIndexTable[index]->UpdateChildMsvIdsL(aEntries);
       
   993 			return;
       
   994 			}
       
   995 		}
       
   996 	}
       
   997 
       
   998 
       
   999 /**
       
  1000  ReleaseAllBlocks()
       
  1001 @param TInt : Number Entries Successfully released.
       
  1002 @return TBool : Returns true if all the entries are released successfully.
       
  1003  
       
  1004 The function Releases the blocks owned by the all indextable entries to freepool.
       
  1005 1. Iterate through the indextable entries.
       
  1006 2. Release the IndexTable Entry Block to the free pool
       
  1007 */
       
  1008 TBool CMsvCacheVisibleFolder::ReleaseAllBlocks(TInt& aCount)
       
  1009 	{
       
  1010 	TBool isAllBlocksReleased = ETrue;
       
  1011 	aCount = 0;
       
  1012 	
       
  1013 	// 1. Iterate through the indextable entries.
       
  1014 	for(TInt index=0; index < iIndexTable.Count(); ++index)
       
  1015 		{
       
  1016 		TInt size = iIndexTable[index]->Size();
       
  1017 		//2.Release the IndexTable Entry Block to the free pool
       
  1018 		if(!iIndexTable[index]->ReleaseBlock())
       
  1019 			{
       
  1020 			isAllBlocksReleased = EFalse;
       
  1021 			}
       
  1022 		else
       
  1023 			{
       
  1024 			aCount += size;				
       
  1025 			}
       
  1026 		}
       
  1027 	if(!IsComplete() && isAllBlocksReleased)
       
  1028 		{
       
  1029 		iIndexTable.ResetAndDestroy();
       
  1030 		}
       
  1031 	
       
  1032 	return (isAllBlocksReleased);
       
  1033 	}
       
  1034 
       
  1035 
       
  1036 /**
       
  1037  CompareOrder()
       
  1038 @param CMsvCacheIndexTableEntry : First indexTable entry (Comparison arg)
       
  1039 @param CMsvCacheIndexTableEntry : Second indexTable entry (Comparison arg)
       
  1040 @return TInt : Returns TTime difference.
       
  1041 
       
  1042 Used to sort indexTableEntry.
       
  1043 */
       
  1044 static TInt CompareOrder(const CMsvCacheIndexTableEntry& aFirst, const CMsvCacheIndexTableEntry& aSecond)
       
  1045 	{
       
  1046 	return (TInt) (aFirst.AccessTime().Int64()-aSecond.AccessTime().Int64());
       
  1047 	}
       
  1048 
       
  1049 
       
  1050 
       
  1051 /**
       
  1052  ReleaseBlocks()
       
  1053 @param TInt : number of blocks to be released to free pool.
       
  1054 @param TBool : Returns true if the indextable was deleted.
       
  1055 @return TInt : Returns Number of entries successfully released.
       
  1056  
       
  1057 The function Releases the required number blocks owned by the all indextable entries to freepool.
       
  1058 1. Create a Copy of the IndexTable Entries & sort them w.r.t time
       
  1059 2. Iterate through all the blocks or until the expected number of entries are released
       
  1060 3. Release the entries to free pool
       
  1061 */
       
  1062 TInt CMsvCacheVisibleFolder::ReleaseBlocks(TInt aNumberOfEntriesToRelease, TBool& aIsFolderEmpty)
       
  1063 	{
       
  1064 	aIsFolderEmpty = EFalse;
       
  1065 	TInt index = 0;
       
  1066 	TInt sizeOfBlock = 0;
       
  1067 	TInt numEntries = aNumberOfEntriesToRelease;
       
  1068 	TInt addrIndex = 0;
       
  1069 	
       
  1070 	//1. Create a Copy of the IndexTable Entries & sort them w.r.t time
       
  1071 	RPointerArray<CMsvCacheIndexTableEntry> indexTableCopytoSort;
       
  1072 	for(index=0; index<iIndexTable.Count(); ++index)
       
  1073 		{
       
  1074 		TInt err = indexTableCopytoSort.Append(iIndexTable[index]);
       
  1075 		if(KErrNone != err)
       
  1076 			{
       
  1077 			indexTableCopytoSort.Close();
       
  1078 			return err;
       
  1079 			}
       
  1080 		}
       
  1081 	
       
  1082 	TLinearOrder<CMsvCacheIndexTableEntry> order(CompareOrder);
       
  1083 	indexTableCopytoSort.Sort(order);
       
  1084 	
       
  1085 	index = 0;
       
  1086 	// 2. Iterate through all the blocks or until the expected number of entries are released
       
  1087 	while( (aNumberOfEntriesToRelease > 0) && (index < iIndexTable.Count()))
       
  1088 		{
       
  1089 		// 3. Release the entries to free pool
       
  1090 		sizeOfBlock = indexTableCopytoSort[index]->Size();
       
  1091 		if(indexTableCopytoSort[index]->ReleaseBlock())
       
  1092 			{
       
  1093 			aNumberOfEntriesToRelease -= sizeOfBlock;
       
  1094 			if(!IsComplete())
       
  1095 				{
       
  1096 				addrIndex = iIndexTable.Find(indexTableCopytoSort[index]);
       
  1097 				if((addrIndex+1) < iIndexTable.Count())
       
  1098 					{
       
  1099 					iIndexTable[addrIndex+1]->SetMinMsvIdRange(iIndexTable[addrIndex]->GetMinMsvIdRange());
       
  1100 					}
       
  1101 				delete iIndexTable[addrIndex];
       
  1102 				iIndexTable.Remove(addrIndex);
       
  1103 				indexTableCopytoSort.Remove(index);
       
  1104 				--index;
       
  1105 				}
       
  1106 			}
       
  1107 		++index;
       
  1108 		}
       
  1109 	
       
  1110 	if(!IsComplete() && 0 == iIndexTable.Count())
       
  1111 		{
       
  1112 		aIsFolderEmpty = ETrue;
       
  1113 		}
       
  1114 	indexTableCopytoSort.Close();
       
  1115 	return (numEntries - aNumberOfEntriesToRelease);
       
  1116 	}
       
  1117 
       
  1118 
       
  1119 
       
  1120 /**
       
  1121  *SplitBlock
       
  1122  *Will check if the block size will be more than 120, then call the IndexTable SplitBlock()
       
  1123  * 	
       
  1124  *@param None.
       
  1125  *@return void 
       
  1126  */
       
  1127 void CMsvCacheVisibleFolder::SplitBlockL()
       
  1128 	{
       
  1129 	TInt tableCount = iIndexTable.Count(); 
       
  1130 	while(tableCount--)
       
  1131 		{
       
  1132 		TInt size = iIndexTable[tableCount]->Size();
       
  1133 		if(size > 120)
       
  1134 			{
       
  1135 			iIndexTable[tableCount]->SortBlock();
       
  1136 			RPointerArray<CMsvCacheEntry> splitEntryBlock;
       
  1137 			CleanupClosePushL(splitEntryBlock);
       
  1138 			// Split the block and get the enteries of the 2nd block				
       
  1139 			iIndexTable[tableCount]->SplitBlockL(splitEntryBlock);
       
  1140 			TInt count = splitEntryBlock.Count();
       
  1141 			
       
  1142 			CMsvCacheIndexTableEntry* newTableEntry = CMsvCacheIndexTableEntry::NewLC(splitEntryBlock, 0, count);
       
  1143 			
       
  1144 			TMsvId minId = splitEntryBlock[0]->GetId();
       
  1145 			// Copy the flags(dirty and grandchildren) of the parent block.
       
  1146 			if(iIndexTable[tableCount]->IsDirty())
       
  1147 				{
       
  1148 				newTableEntry->SetDirty();
       
  1149 				}
       
  1150 			if(iIndexTable[tableCount]->IsGrandChildPresent())
       
  1151 				{
       
  1152 				newTableEntry->SetGrandChildPresent();
       
  1153 				}
       
  1154 			newTableEntry->SetAccessTime(iIndexTable[tableCount]->AccessTime());
       
  1155 			
       
  1156 			iIndexTable.InsertL(newTableEntry, tableCount+1);
       
  1157 			iIndexTable[tableCount+1]->SetMinMsvIdRange(minId);
       
  1158 			iIndexTable[tableCount+1]->SetMaxMsvIdRange(splitEntryBlock[count-1]->GetId());
       
  1159 			
       
  1160 			iIndexTable[tableCount]->SetMaxMsvIdRange(minId - 1);
       
  1161 			CleanupStack::Pop();//newTableEntry
       
  1162 			splitEntryBlock.Reset();
       
  1163 			CleanupStack::PopAndDestroy();// splitEntryBlock
       
  1164 			}
       
  1165 		}
       
  1166 	}
       
  1167 
       
  1168 
       
  1169 
       
  1170 /**
       
  1171  * GetIndexTableEntry()
       
  1172  * @param TInt : Index at which the desired indextable entry exists.
       
  1173  * @return CMsvCacheIndexTableEntry* : Returns pointer at the index specified.
       
  1174  * 
       
  1175  * The function returns the pointer to the IndexTable from the list.
       
  1176  */
       
  1177 RPointerArray<CMsvCacheIndexTableEntry>* CMsvCacheVisibleFolder::GetIndexTableEntry()
       
  1178 	{
       
  1179 	return &iIndexTable;
       
  1180 	}
       
  1181 
       
  1182 
       
  1183 
       
  1184 
       
  1185 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
  1186 #ifdef _DEBUG
       
  1187 // To print message index cache.
       
  1188 void CMsvCacheVisibleFolder::Print(RFileLogger& aLogger)
       
  1189 	{
       
  1190 	_LIT8(KBlock, "     BLOCK-ID: ");
       
  1191 	TInt blockCount = iIndexTable.Count(); 
       
  1192 	
       
  1193 	for(TInt index=0; index < blockCount; index++)
       
  1194 		{
       
  1195 		RBuf8 text;
       
  1196 		text.Create(100);
       
  1197 		text.Append(KBlock);
       
  1198 		text.AppendNum(index+1);
       
  1199 		aLogger.Write(text);
       
  1200 		text.Close();	
       
  1201 		iIndexTable[index]->Print(aLogger);	
       
  1202 		aLogger.Write(_L(""));
       
  1203 		}
       
  1204 	}
       
  1205 #endif 		// #ifdef _DEBUG
       
  1206 #endif		// #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
  1207