messagingfw/msgsrvnstore/server/src/msvcacheindextableentry.Cpp
changeset 0 8e480a14352b
child 22 d2c4c66342f3
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 // CMSVCACHEINDEXTABLEENTRY.CPP
       
    15 // HEADER FILES
       
    16 // 
       
    17 //
       
    18 
       
    19 #include "msvcacheindextableentry.h"
       
    20 #include "msventryfreepool.h"
       
    21 #include "msvcacheentry.h"
       
    22 
       
    23 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)	
       
    24 	#include "msvindexadapter.h"
       
    25 #endif
       
    26 
       
    27 /**
       
    28  * FUNCTION DEFINITION
       
    29  */
       
    30  
       
    31 
       
    32 //****************************
       
    33 //CMsvCacheIndexTableEntry
       
    34 //****************************
       
    35 
       
    36 /**
       
    37  * NewL()
       
    38  * @param None.
       
    39  * @return The newly created index table entry
       
    40  * 
       
    41  * It returns an instance of the CMsvCacheIndexTableEntry class, i.e. a newly 
       
    42  * constructed index table with no entries in it.
       
    43  */
       
    44 CMsvCacheIndexTableEntry* CMsvCacheIndexTableEntry::NewL()
       
    45 	{
       
    46 	CMsvCacheIndexTableEntry *self = new(ELeave) CMsvCacheIndexTableEntry();
       
    47 	return self;
       
    48 	}
       
    49 
       
    50 
       
    51 /**
       
    52  * NewL()
       
    53  * @param CMsvCacheEntry& : a new cache entry
       
    54  * @return The newly created index table entry
       
    55  * 
       
    56  * It returns an instance of the CMsvCacheIndexTableEntry class with the passed entry
       
    57  * added.
       
    58  */
       
    59 CMsvCacheIndexTableEntry* CMsvCacheIndexTableEntry::NewL(CMsvCacheEntry*& aEntry)
       
    60 	{
       
    61 	CMsvCacheIndexTableEntry *self = CMsvCacheIndexTableEntry::NewLC(aEntry);
       
    62 	CleanupStack::Pop();
       
    63 	return self;
       
    64 	}
       
    65 
       
    66 
       
    67 /**
       
    68  * NewLC()
       
    69  * @param CMsvCacheEntry& : a new cache entry
       
    70  * @return The newly created index table entry
       
    71  * 
       
    72  * It returns an instance of the CMsvCacheIndexTableEntry class 
       
    73  * with the passed entry added. It leaves the object into cleanup stack.
       
    74  */
       
    75 CMsvCacheIndexTableEntry* CMsvCacheIndexTableEntry::NewLC(CMsvCacheEntry*& aEntry)
       
    76 	{
       
    77 	CMsvCacheIndexTableEntry *self = new(ELeave) CMsvCacheIndexTableEntry();
       
    78 	CleanupStack::PushL(self);
       
    79 	self->AddEntryL(aEntry);
       
    80 	return self;
       
    81 	}
       
    82 
       
    83 
       
    84 
       
    85 
       
    86 /**
       
    87  * NewL()
       
    88  * @param RPointerArrayCMsvCacheEntry>& : RPointerArray reference to child entries
       
    89  * @return The newly created index table entry
       
    90  * 
       
    91  * It returns an instance of the CMsvCacheIndexTableEntry class filled with child
       
    92  * entries.
       
    93  */
       
    94 CMsvCacheIndexTableEntry* CMsvCacheIndexTableEntry::NewL(RPointerArray<CMsvCacheEntry>& aEntries, TInt aInitIndex /*(DEFALUT=0)*/, TInt aCount /* DEFAULT = -1*/)
       
    95 	{
       
    96 	CMsvCacheIndexTableEntry *self = CMsvCacheIndexTableEntry::NewLC(aEntries, aInitIndex, aCount);
       
    97 	CleanupStack::Pop();
       
    98 	return self;
       
    99 	}
       
   100 
       
   101 
       
   102 
       
   103 
       
   104 /**
       
   105  * NewLC()
       
   106  * @param RPointerArrayCMsvCacheEntry>& : RPointerArray reference to child entries
       
   107  * @return The newly created index table entry
       
   108  * 
       
   109  * It returns an instance of the CMsvCacheIndexTableEntry class filled with child
       
   110  * entries. It leaves the object into cleanup stack.
       
   111  */
       
   112 CMsvCacheIndexTableEntry* CMsvCacheIndexTableEntry::NewLC(RPointerArray<CMsvCacheEntry>& aEntries, TInt aInitIndex /*(DEFALUT=0)*/, TInt aCount /* DEFAULT = -1*/)
       
   113 	{
       
   114 	CMsvCacheIndexTableEntry *self = new(ELeave) CMsvCacheIndexTableEntry();
       
   115 	CleanupStack::PushL(self);
       
   116 	self->AddEntrySetL(aEntries, aInitIndex, aCount);
       
   117 	return self;
       
   118 	}
       
   119 
       
   120 
       
   121 
       
   122 
       
   123 /**
       
   124  * CMsvCacheIndexTableEntry()
       
   125  * @param None.
       
   126  * @return None.
       
   127  * 
       
   128  * Constructor
       
   129  */
       
   130 CMsvCacheIndexTableEntry::CMsvCacheIndexTableEntry()
       
   131 :iMinMsvId(0), iMaxMsvId(0), iFlags(EMsvCacheIndexTableClearFlag)
       
   132 	{
       
   133 	iTimeStamp.HomeTime(); //set the timestamp to number of seconds since Epoc.
       
   134 	iBlockPtr = NULL;
       
   135 	}
       
   136 
       
   137 
       
   138 /**
       
   139  * ~CMsvCacheIndexTableEntry()
       
   140  * @param None.
       
   141  * @return None.
       
   142  * 
       
   143  * Destructor - releases the block to the cache free pool and sets it to NULL.
       
   144  */
       
   145 CMsvCacheIndexTableEntry::~CMsvCacheIndexTableEntry()
       
   146 	{
       
   147 	//destructor should delete everything no matter if entries are locked or not
       
   148 	ReleaseBlock(ETrue);
       
   149 	}
       
   150 
       
   151 
       
   152 /**
       
   153  * AddEntryL()
       
   154  * @param CMsvCacheEntry& : reference to the CMsvCacheEntry to be added.
       
   155  * @return None.
       
   156  * 
       
   157  * The function adds an entry into the index table. The entity who passes the entry
       
   158  * to the function will give up ownership of the same and hence cannot modify or 
       
   159  * delete it.
       
   160  * 1. If the block is NULL, it creates a new one and appends the entry to the block
       
   161  *    and accordingly sets the TMsvId ranges.
       
   162  * 2. If block is not NULL, then append the entry to it.
       
   163  * 	2.1 If the entry already exists in the block then release the old entry from the block and
       
   164  *		append the new one.
       
   165  * 	2.2 If the entry fits only at the end of the last block then we need to change
       
   166  *      the iMaxMsvid.
       
   167  *      If the indextable has not been created and if the folder has just one block, and this block contains
       
   168  * 		random entries, then we may need to set the iMinMsvId.
       
   169  */
       
   170 void CMsvCacheIndexTableEntry::AddEntryL(CMsvCacheEntry*& aEntry, TBool aReplace /* DEFAULT = EFalse*/)
       
   171 	{
       
   172 	TMsvId entryId = aEntry->GetId();
       
   173 	//	1. If the block is NULL, it creates a new one and appends the entry to the block
       
   174 	//     and accordingly sets the TMsvId ranges.
       
   175 	if(NULL == iBlockPtr)
       
   176 		{
       
   177 		iBlockPtr = new(ELeave) RPointerArray<CMsvCacheEntry>;
       
   178 		iBlockPtr->AppendL(aEntry);
       
   179 		SetMinMsvIdRange(entryId);
       
   180 		SetMaxMsvIdRange(entryId);
       
   181 		} //if(NULL == iBlockPtr)
       
   182 	
       
   183 	//	2. If block is not NULL:
       
   184 	else
       
   185 		{
       
   186 		// 2.1 If the entry already exists in the block then release the old entry from the
       
   187 		//	   block and append the new one.
       
   188 		TInt blockSize = Size();
       
   189 		for(TInt blockIndex = 0; blockIndex < blockSize; ++blockIndex)
       
   190 			{
       
   191 			if((*iBlockPtr)[blockIndex]->GetId() == aEntry->GetId())
       
   192 				{
       
   193 				if(!aReplace)
       
   194 					{
       
   195 					CMsvEntryFreePool::Instance()->ReleaseEntry(aEntry);
       
   196 					aEntry = (*iBlockPtr)[blockIndex];
       
   197 					return;
       
   198 					}
       
   199 				CMsvEntryFreePool::Instance()->ReleaseEntry((*iBlockPtr)[blockIndex]);
       
   200 				iBlockPtr->Remove(blockIndex);
       
   201 				iBlockPtr->Insert(aEntry, blockIndex);
       
   202 				return;
       
   203 				}
       
   204 			}
       
   205 		iBlockPtr->AppendL(aEntry);
       
   206 		
       
   207 		// 2.2 If the entry fits only at the end of the last block then we need to
       
   208 		//     change the iMaxMsvid.
       
   209 		//     If the indextable has not been created and if the folder has just
       
   210 		//     one block, and this block contains random entries, then we may need to 
       
   211 		//     set the iMinMsvId.
       
   212 		if(entryId > iMaxMsvId)
       
   213 			{
       
   214 			SetMaxMsvIdRange(entryId);
       
   215 			}
       
   216 			
       
   217 		if(entryId < iMinMsvId)
       
   218 			{
       
   219 			SetMinMsvIdRange(entryId);
       
   220 			}
       
   221 		} //else
       
   222 	iTimeStamp.HomeTime();
       
   223 	}
       
   224 
       
   225 
       
   226 
       
   227 
       
   228 /**
       
   229  * AddEntrySetL()
       
   230  * @param RPointerArray<CMsvCacheEntry>& : reference to the new entry set to be added.
       
   231  * 										   These entries can either be immediate children
       
   232  * 										   or non-immediate children, but not both.
       
   233  * @param TInt aInitIndex : Start index of the entry to be added in the entryList.
       
   234  * @param TInt aCount     : Number of entries that should be added.
       
   235  * @return None.
       
   236  * 
       
   237  * The function adds a set of entries to the index table. The caller who passes the 
       
   238  * array of entries to the function will give up ownership of the entries in the array.
       
   239  * 1. When the block is NULL:
       
   240  * 	1.1 If children of a non-immediate folder are present in the array then set the 
       
   241  *      grandchildren and dirty flags.
       
   242  * 	1.2 If there aren't, then clear the above two flags.
       
   243  * 	1.3 Assign the new entry set to the block, but reset the passed set so that
       
   244  *	   the caller cannot modify or delete the cache entries.
       
   245  * 2. When the block is not NULL:
       
   246  *  2.1 If children of a non-immediate folder are present in the array then
       
   247  *	    set the grandchildren flag and simply append entries to the block.
       
   248  *  2.2 If there aren't, append entries avoiding duplication.
       
   249  * 		2.2.1 Search for each entry that is present in the current block in the
       
   250  *			  new set passed. If the entry is present then release it from the
       
   251  *			  current block. If not then append to the new set.
       
   252  * 		2.2.2 All entries are now in the passed array. Reset the current block,
       
   253  *			  allocate space for it and copy the entries to it. Also reset the 
       
   254  *			  passed array so that callers do not have access to the cache
       
   255  *			  entries after the addition.
       
   256  * 3. Calculate and set the maximum and minimum TMsvId ranges in the newly added set.
       
   257  */
       
   258 void CMsvCacheIndexTableEntry::AddEntrySetL(RPointerArray<CMsvCacheEntry>& aEntries, TInt aInitIndex /*(DEFAULT=0)*/, TInt aCount /* DEFAULT=-1 */)
       
   259 	{
       
   260 	// Add all entries if aCount is -1.
       
   261 	TInt arrSize = aEntries.Count();
       
   262 	if(-1 == aCount)
       
   263 		{
       
   264 		aCount = arrSize;
       
   265 		}
       
   266 	if(aInitIndex < 0 || aInitIndex >= arrSize)
       
   267 		{
       
   268 		return;
       
   269 		}
       
   270 	
       
   271 	// 1. When the block is NULL:
       
   272 	if(NULL == iBlockPtr)
       
   273 		{
       
   274 		//     Assign the new entry set to the block, but reset the passed set so that
       
   275 		//	   the caller cannot modify or delete the cache entries.
       
   276 		//	   Update the ranges of the block.
       
   277 		
       
   278 		iBlockPtr = new(ELeave) RPointerArray<CMsvCacheEntry>;
       
   279 		for(TInt listIndex = 0; (listIndex < aCount) && (arrSize > listIndex+aInitIndex); ++listIndex)
       
   280 			{
       
   281 			iBlockPtr->AppendL(aEntries[listIndex+aInitIndex]);
       
   282 			}
       
   283 		
       
   284 		} //if(NULL == iBlockPtr)
       
   285 	
       
   286 	// 2. When the block is not NULL append the entries. If there is a duplicate entry,
       
   287 	//	  discard the new entry.
       
   288 	else
       
   289 		{
       
   290 		TBool entryFound = EFalse;
       
   291 		TInt blockSize = Size();
       
   292 		for(TInt listCount = 0; (listCount < aCount) && (arrSize > listCount+aInitIndex); ++listCount)
       
   293 			{
       
   294 			entryFound = EFalse;
       
   295 			for(TInt blockIndex = 0; blockIndex < blockSize; ++blockIndex)
       
   296 				{
       
   297 				if(aEntries[listCount+aInitIndex]->GetId() == (*iBlockPtr)[blockIndex]->GetId())
       
   298 					{
       
   299 					CMsvEntryFreePool::Instance()->ReleaseEntry(aEntries[listCount+aInitIndex]);
       
   300 					aEntries.Remove(listCount+aInitIndex);
       
   301 					aEntries.Insert((*iBlockPtr)[blockIndex], listCount+aInitIndex);
       
   302 					entryFound = ETrue;
       
   303 					break;
       
   304 					}
       
   305 				}   //for()
       
   306 			if(!entryFound)
       
   307 				{
       
   308 				iBlockPtr->AppendL(aEntries[listCount+aInitIndex]);
       
   309 				}			
       
   310 			}   //for()
       
   311 		} //else
       
   312 	iTimeStamp.HomeTime();
       
   313 	}
       
   314 	
       
   315 	
       
   316 
       
   317 
       
   318 /**
       
   319  * GetEntry()
       
   320  * @param TMsvId : the TMsvId of the entry to be fetched.
       
   321  * @param CMsvCacheEntry*& : output parameter for the entry.
       
   322  * @return TBool.
       
   323  * 
       
   324  * The function fetches the entry with the specified TMsvId.
       
   325  * 1. If the block is NULL, there is no entry that can be fetched. Return EFalse.
       
   326  * 2. Iterate through the block searching for the TMsvId and return ETrue for a hit
       
   327  * 3. Return EFalse if the entry is not present in the block.
       
   328  */
       
   329 TBool CMsvCacheIndexTableEntry::GetEntry(TMsvId aId, CMsvCacheEntry*& aEntry)
       
   330 	{
       
   331 	// 1. If the block is NULL, there is no entry that can be fetched. Return EFalse.
       
   332 	if(NULL == iBlockPtr)
       
   333 		{
       
   334 		aEntry = NULL;
       
   335 		return EFalse;
       
   336 		}
       
   337 	
       
   338 	//	2. Iterate through the block searching for the TMsvId and return ETrue for a hit.
       
   339 	TInt blockSize = Size();
       
   340 	for(TInt index = 0 ; index < blockSize ; ++index)
       
   341 		{
       
   342 		if((*iBlockPtr)[index]->GetId() ==  aId)
       
   343 			{
       
   344 			aEntry = (*iBlockPtr)[index];
       
   345 			iTimeStamp.HomeTime();
       
   346 			return ETrue;
       
   347 			}
       
   348 		} //for
       
   349 	
       
   350 	//	3. Return EFalse if the entry is not present in the block.
       
   351 	return EFalse;
       
   352 	}
       
   353 
       
   354 
       
   355 /**
       
   356  * GetChildrenL()
       
   357  * @param TMsvId : TMsvId of the parent entry of the entries to be fetched.
       
   358  * @param RPointerArray<CMsvCacheEntry>*& : output parameter for the entries to be
       
   359  *        fetched.
       
   360  * @return None.
       
   361  * 
       
   362  * The function fetches a set of entries with the specified parent TMsvId.
       
   363  * 1. Check if there are grandchildren present in the block.
       
   364  * 	1.1. If yes, then fetch only those entries with parent Id as aParentId.
       
   365  * 		 If the array of entries is NULL, then allocate space for it.
       
   366  * 	1.2. If not, then return a copy of the whole block.
       
   367  */
       
   368 void CMsvCacheIndexTableEntry::GetChildrenL(TMsvId aParentId, RPointerArray<CMsvCacheEntry>& aEntries) /*const*/
       
   369 	{ 
       
   370 	// 1. Check if there are grandchildren present in the block.
       
   371 	if(IsGrandChildPresent())
       
   372 		{
       
   373 		// 1.1 If yes, then fetch only those entries with parent Id as aParentId.
       
   374 		//       If the array of entries is NULL, then allocate space for it.
       
   375 		TInt blockSize = Size();
       
   376 		for(TInt index = 0 ; index < blockSize ; ++index)
       
   377 			{
       
   378 			if((*iBlockPtr)[index]->Entry().Parent() == aParentId)
       
   379 				{
       
   380 				aEntries.AppendL((*iBlockPtr)[index]);
       
   381 				}
       
   382 			}
       
   383 		} //if(IsGrandChildPresent())
       
   384 	
       
   385 	else
       
   386 		{
       
   387 		// 1.2 If not, then return a copy of the whole block.
       
   388 		TInt blockSize = Size();
       
   389 		for(TInt index = 0 ; index < blockSize ; ++index)
       
   390 			{
       
   391 			aEntries.AppendL((*iBlockPtr)[index]);
       
   392 			}
       
   393 		} //else
       
   394 	iTimeStamp.HomeTime();
       
   395 	}
       
   396 	
       
   397 
       
   398 /**
       
   399  * DeleteEntryL()
       
   400  * @param TMsvId : the TMsvId of the entry to be deleted.
       
   401  * @param aParentIdOfEntry
       
   402  * @param aForceDelete TBool, it indicates whether the entry needs to be locked while deleting.
       
   403  * @return None.
       
   404  * 
       
   405  * The function deletes an entry from the cache releasing the entry to the cache free
       
   406  * pool. The function is called when the entry is being deleted from both the DB and
       
   407  * cache.
       
   408  * 1. Return if the block is NULL.
       
   409  * 2. Iterate through the block searching for the TMsvId.
       
   410  *	2.1 If the entry exists, remove it and release to the free pool. Deletion
       
   411  *		 is possible only if the entry is locked in the cache, otherwise the function
       
   412  * 		 returns KErrAccessDenied.
       
   413  * 		 2.1.1 If the entry deleted was the last entry in the block, delete the
       
   414  *		        block.
       
   415  * 3. Leave with KErrNotFound if the entry does not exist in the block.	
       
   416  */
       
   417 void CMsvCacheIndexTableEntry::DeleteEntryL(TMsvId aId, TMsvId& aParentIdOfEntry /*DEFAULT = NULL*/, TBool aForceDelete /*DEFAULT=EFalse*/)
       
   418 	{ 
       
   419 	// 1. Return if the block is NULL.
       
   420 	if(NULL == iBlockPtr)
       
   421 		{
       
   422 		User::Leave(KErrNotFound);
       
   423 		}
       
   424 	
       
   425 	//	2. Iterate through the block searching for the TMsvId.
       
   426 	TInt blockSize = Size();
       
   427 	for(TInt index = 0 ; index < blockSize ; ++index)
       
   428 		{
       
   429 		//	2.1 If the entry exists, remove it and release to the free pool. Deletion
       
   430 		//		 is possible only if the entry is locked in the cache.
       
   431 		if((*iBlockPtr)[index]->GetId() ==  aId)
       
   432 			{
       
   433 			if(aForceDelete || (*iBlockPtr)[index]->IsEntryLocked())
       
   434 				{
       
   435 				aParentIdOfEntry = (*iBlockPtr)[index]->Entry().Parent();
       
   436 				CMsvEntryFreePool::Instance()->ReleaseEntry((*iBlockPtr)[index]);
       
   437 				iBlockPtr->Remove(index);
       
   438 				// 2.1.1. If the entry deleted was the last entry in the block,
       
   439 				//        delete the block.
       
   440 				if(iBlockPtr->Count() == 0)
       
   441 					{
       
   442 					iBlockPtr->Close();
       
   443 					delete iBlockPtr;
       
   444 					iBlockPtr = NULL;
       
   445 					}
       
   446 				iTimeStamp.HomeTime();
       
   447 				}
       
   448 			else
       
   449 				{
       
   450 				User::Leave(KErrAccessDenied);
       
   451 				}
       
   452 			return;
       
   453 			}
       
   454 		} //for
       
   455 	// 3. Leave with KErrNotFound if the entry does not exist in the block.
       
   456 	User::Leave(KErrNotFound);
       
   457 	}
       
   458 
       
   459 
       
   460 /**
       
   461  * ReleaseBlock()
       
   462  * @param TBool: internally used flag which is used by destructor to forcibly swap out
       
   463  * 				 the block even if entries have been locked.
       
   464  * @return TBool: EFalse if block cannot be released as a result of entries having been
       
   465  * 				  locked in the cache, ETrue if otherwise.
       
   466  * 
       
   467  * The function releases a block to the cache free pool.
       
   468  * 1. Return EFalse if any of the entries in the block have been locked. Do not
       
   469  *    swap out the block to the free pool if so.
       
   470  * 2. No entries are locked and/or the block is to be swapped out forcibly.
       
   471  *  2.1 Release the entries to the free pool.
       
   472  *  2.2 Free the memory allocated to the block itself.
       
   473  *  2.3 Set the dirty flag.
       
   474  */
       
   475 TBool CMsvCacheIndexTableEntry::ReleaseBlock(TBool aForceRelease /*DEFAULT = EFalse*/)
       
   476 	{ 
       
   477 	if(NULL == iBlockPtr)
       
   478 		{
       
   479 		return ETrue;
       
   480 		}
       
   481 	// 1. Return EFalse if any of the entries in the block have been locked. Do not
       
   482 	//	  swap out the block to the free pool if so.
       
   483 	if(!aForceRelease)
       
   484 		{
       
   485 		TInt blockSize = Size();
       
   486 		for(TInt index = 0; index < blockSize; ++index)
       
   487 			{
       
   488 			if(!(*iBlockPtr)[index]->IsEntrySwappable())
       
   489 				{
       
   490 				return EFalse;
       
   491 				}
       
   492 			}
       
   493 		}
       
   494 	
       
   495 	// 2. No entries are locked and the block can be swapped out safely.
       
   496 	CMsvEntryFreePool::Instance()->ReleaseEntrySet(*iBlockPtr);
       
   497 	
       
   498 	iBlockPtr->Close();
       
   499 	delete iBlockPtr;
       
   500 	iBlockPtr = NULL;
       
   501 	SetDirty();
       
   502 	return ETrue;
       
   503 	}
       
   504 
       
   505 
       
   506 /**
       
   507  * CompareOrder()
       
   508  * @param const CMsvCacheEntry& : the first operand
       
   509  * @param const CMsvCacheEntry& : the second operand
       
   510  * @return TInt : the order (-1/0/+1)
       
   511  * 
       
   512  * The function returns the order for the sort operation.
       
   513  */
       
   514 static TInt CompareOrder(const CMsvCacheEntry& aFirst, const CMsvCacheEntry& aSecond)
       
   515 	{
       
   516 	return aFirst.GetId() - aSecond.GetId();
       
   517 	}
       
   518 
       
   519 
       
   520 /**
       
   521  * SortBlockL()
       
   522  * @param None.
       
   523  * @return None.
       
   524  * 
       
   525  * The function is called by a background active object to sort the index table
       
   526  * according to TMsvIds of the entries.
       
   527  * 1. Sort based on the order in the TLinearOrder package.
       
   528  */
       
   529 void CMsvCacheIndexTableEntry::SortBlock()
       
   530 	{
       
   531 	if(iBlockPtr != NULL)
       
   532 		{
       
   533 		//	1. Sort based on the order in the TLinearOrder package.
       
   534 		TLinearOrder<CMsvCacheEntry> order(CompareOrder);
       
   535 		iBlockPtr->Sort(order);
       
   536 		}
       
   537 	}
       
   538 
       
   539 
       
   540 /**
       
   541  * EntryExists()
       
   542  * @param TMsvId : the Id of the entry to be checked for existence.
       
   543  * @return TBool : success/failure.
       
   544  * 
       
   545  * The function return EFalse if either the block is NULL or the entry does not exist.
       
   546  * ETrue is returned for a hit.
       
   547  */
       
   548 TBool CMsvCacheIndexTableEntry::EntryExists(TMsvId aId) const
       
   549  	{
       
   550  	if(NULL == iBlockPtr)
       
   551 		{
       
   552 		return EFalse;
       
   553 		}
       
   554  	TInt blockSize = Size();
       
   555  	for(TInt index = 0 ; index < blockSize ; ++index)
       
   556  		{
       
   557  		if(aId == (*iBlockPtr)[index]->GetId())
       
   558  			{
       
   559  			return ETrue;
       
   560  			}
       
   561  		} //for
       
   562  	return EFalse;
       
   563  	}
       
   564 
       
   565 
       
   566 /**
       
   567  * UpdateChildMsvIdsL()
       
   568  * @param TMsvId : TMsvId of the parent entry.
       
   569  * @param TMsvId : TMsvId of the child entry.
       
   570  * @param TBool : flag, set to ETrue if aChildId is to be added, and EFalse if it is
       
   571  * 				  to be removed from the parent's child array.
       
   572  * @return None.
       
   573  * 
       
   574  * The function updates the child array of the parent entry if it is not NULL.
       
   575  * 1. Return if the block is NULL, i.e. the parent is not in the cache.
       
   576  * 2. Iterate through the block searching for the parent entry.
       
   577  * 	2.1 If the iChildIdArray is not NULL:
       
   578  * 		2.1.1 If the child has to be added as a consequence of it being
       
   579  *				  added to the cache, then append it to the child array.
       
   580  * 		2.1.2 If the child has to be removed as a consequence to the child
       
   581  * 		       entry being deleted, then remove it from the child array.
       
   582  */
       
   583 void CMsvCacheIndexTableEntry::UpdateChildMsvIdsL(TMsvId aParentId, TMsvId aChildId, TBool aAdd /*DEFAULT = ETrue*/)
       
   584 	{
       
   585 	// 1. Return if the block is NULL, i.e. the parent is not in the cache.
       
   586 	if(NULL == iBlockPtr)
       
   587 		{
       
   588 		return;
       
   589 		}
       
   590 	
       
   591 	//	2. Iterate through the block searching for the parent entry.
       
   592 	TInt blockSize = Size();
       
   593 	for(TInt index = 0 ; index < blockSize ; ++index)
       
   594 		{
       
   595 		if((*iBlockPtr)[index]->GetId() ==  aParentId)
       
   596 			{
       
   597 			RArray<TMsvId>* childArr = (*iBlockPtr)[index]->ChildIdArray();
       
   598 			// 2.1 If the iChildIdArray is not NULL: i.e GetChildren has been performed
       
   599 			if(childArr != NULL)
       
   600 				{
       
   601 				// 2.1.1 If the child has to be added as a consequence of it being
       
   602 				//		  added to the cache, then append it to the child array.
       
   603 				TInt arrSize = childArr->Count();
       
   604 				if(aAdd)
       
   605 					{
       
   606 					TInt index = childArr->Find(aChildId);
       
   607 					if(index == KErrNotFound)
       
   608 						{
       
   609 						childArr->AppendL(aChildId);
       
   610 						}
       
   611 					}
       
   612 				
       
   613 				// 2.1.2 If the child has to be removed as a consequence to the child
       
   614 				//        entry being deleted, then remove it from the child array.
       
   615 				else
       
   616 					{
       
   617 					TInt index = childArr->Find(aChildId);
       
   618 					if(index != KErrNotFound)
       
   619 						{
       
   620 						childArr->Remove(index);
       
   621 						}
       
   622 					}
       
   623 				} //if(((*iBlockPtr)[index]->ChildIdArray()) != NULL)
       
   624 			return;
       
   625 			} //if((*iBlockPtr)[index]->GetId() ==  aParentId)
       
   626 		} //for(TInt index = 0 ; index < Size() ; index++)
       
   627 }
       
   628 
       
   629 
       
   630 /**
       
   631  * UpdateChildMsvIdsL()
       
   632  * @param RPointerArray<CMsvCacheEntry>& : array of complete set of child 
       
   633  * 										   CMsvCacheEntries sorted by TMsvId.
       
   634  * @return None.
       
   635  * 
       
   636  * The function updates, or creates if necessary, a parent entry's iChildIdArray with
       
   637  * the children entries passed to it in the form of a RPointerArray.
       
   638  * 1. Return if the block is NULL, i.e. the parent is not in the cache.
       
   639  * 2. Otherwise, find the parent sequentially.
       
   640  * 	2.1 If the parent is found:
       
   641  * 		2.1.1 If the parent already has a iChildIdArray, i.e. if GetChildren() has
       
   642  * 			   been performed on it, delete and create a new child array with the 
       
   643  * 			   entries passed. If iChildIdArray is NULL then GetChildren() has not been
       
   644  *			   performed on the entry yet, in which case append the passed children.
       
   645  */
       
   646 void CMsvCacheIndexTableEntry::UpdateChildMsvIdsL(RPointerArray<CMsvCacheEntry>& aEntries)
       
   647 	{
       
   648 	
       
   649 	// 1. Return if the block is NULL, i.e. the parent is not in the cache.
       
   650 	if(NULL == iBlockPtr)
       
   651 		{
       
   652 		return;
       
   653 		}
       
   654 	
       
   655 	// 2. Otherwise, find the parent sequentially.
       
   656 	TMsvId parentId = aEntries[0]->Entry().Parent();
       
   657 	TInt blockSize = Size();
       
   658 	for(TInt index = 0 ; index < blockSize ; ++index)
       
   659 		{
       
   660 		// 2.1 If the parent is found:
       
   661 		if((*iBlockPtr)[index]->Entry().Id() == parentId)
       
   662 			{
       
   663 			// 2.1.1 If the parent already has a iChildIdArray, i.e. if GetChildren() has
       
   664 			// been performed on it, delete and create a new child array with the 
       
   665 			// entries passed. If iChildIdArray is NULL then GetChildren() has not been
       
   666 			// performed on the entry yet, in which case append the passed children.
       
   667 			RArray<TMsvId>* childArr = (*iBlockPtr)[index]->ChildIdArray();
       
   668 			TInt entryCount = aEntries.Count();
       
   669 			if(NULL == childArr)
       
   670 				{
       
   671 				childArr = new(ELeave) RArray<TMsvId>;
       
   672 				(*iBlockPtr)[index]->SetChildIdArray(childArr);
       
   673 				}
       
   674 			else
       
   675 				{
       
   676 				childArr->Reset();
       
   677 				}
       
   678 			while(0 < entryCount)
       
   679 				{
       
   680 				TInt leave = childArr->Append(aEntries[--entryCount]->GetId());
       
   681 				if(KErrNone != leave)
       
   682 					{
       
   683 					childArr->Close();
       
   684 					delete childArr;
       
   685 					(*iBlockPtr)[index]->SetChildIdArray(NULL);
       
   686 					User::Leave(leave);
       
   687 					}
       
   688 				}
       
   689 			return;
       
   690 			} //if((*iBlockPtr)[index]->Entry().Parent() == parentId)
       
   691 		} //for(TInt index = 0 ; index < blockSize ; ++index)
       
   692 	}
       
   693 	
       
   694 	
       
   695 /**
       
   696  *SplitBlock
       
   697  *This will be called when the block size will be more than 120, this will split the block
       
   698  * into 2 blocks.	
       
   699  *@param aSplitBlock 	RPointerArray<CMsvCacheEntry>& that will be filled with CMsvCacheEntries,
       
   700  *@param aMaxId			The maximum TMsvId of the first block.		 
       
   701  *@return void
       
   702  *	
       
   703  */
       
   704 void CMsvCacheIndexTableEntry::SplitBlockL(RPointerArray<CMsvCacheEntry>& aSplitBlock)
       
   705 	{
       
   706 	TInt size = Size();
       
   707 	TInt i = size/2;
       
   708 	while(i < size)
       
   709 		{
       
   710 		aSplitBlock.AppendL((*iBlockPtr)[size/2]);
       
   711 		iBlockPtr->Remove(size/2);
       
   712 		i++;
       
   713 		}
       
   714 	}
       
   715 
       
   716 
       
   717 
       
   718 
       
   719 
       
   720 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
   721 #ifdef _DEBUG
       
   722 // To print message index cache.
       
   723 void CMsvCacheIndexTableEntry::Print(RFileLogger& aLogger)
       
   724 	{
       
   725 	_LIT(KId, "       ID: ");
       
   726 	_LIT(KParentId, "    ParentId: ");
       
   727 	TInt blockSize = Size();
       
   728 	for(TInt index=0; index<blockSize; ++index)
       
   729 		{
       
   730 		RBuf text;
       
   731 		text.Create(150);
       
   732 		text.Append(KId);
       
   733 		text.AppendNum((*iBlockPtr)[index]->Entry().Id());
       
   734 		text.Append(KParentId);
       
   735 		text.AppendNum((*iBlockPtr)[index]->Entry().Parent());
       
   736 		text.Append(_L("    VisibleEntry: "));
       
   737 		text.AppendNum((*iBlockPtr)[index]->Entry().VisibleFolderFlag());
       
   738 		text.Append(_L("	Complete flag:"));
       
   739 		text.AppendNum((*iBlockPtr)[index]->Entry().Complete());
       
   740 		text.Append(_L("    	Description:"));
       
   741 		text.Append((*iBlockPtr)[index]->Entry().iDetails);
       
   742 		aLogger.Write(text);
       
   743 		text.Close();
       
   744 		}
       
   745 	}
       
   746 #endif 		// #ifdef _DEBUG
       
   747 #endif		// #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)