--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/msgsrvnstore/server/src/msvcacheindextableentry.Cpp Mon Jan 18 20:36:02 2010 +0200
@@ -0,0 +1,747 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// CMSVCACHEINDEXTABLEENTRY.CPP
+// HEADER FILES
+//
+//
+
+#include "msvcacheindextableentry.h"
+#include "msventryfreepool.h"
+#include "msvcacheentry.h"
+
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+ #include "msvindexadapter.h"
+#endif
+
+/**
+ * FUNCTION DEFINITION
+ */
+
+
+//****************************
+//CMsvCacheIndexTableEntry
+//****************************
+
+/**
+ * NewL()
+ * @param None.
+ * @return The newly created index table entry
+ *
+ * It returns an instance of the CMsvCacheIndexTableEntry class, i.e. a newly
+ * constructed index table with no entries in it.
+ */
+CMsvCacheIndexTableEntry* CMsvCacheIndexTableEntry::NewL()
+ {
+ CMsvCacheIndexTableEntry *self = new(ELeave) CMsvCacheIndexTableEntry();
+ return self;
+ }
+
+
+/**
+ * NewL()
+ * @param CMsvCacheEntry& : a new cache entry
+ * @return The newly created index table entry
+ *
+ * It returns an instance of the CMsvCacheIndexTableEntry class with the passed entry
+ * added.
+ */
+CMsvCacheIndexTableEntry* CMsvCacheIndexTableEntry::NewL(CMsvCacheEntry*& aEntry)
+ {
+ CMsvCacheIndexTableEntry *self = CMsvCacheIndexTableEntry::NewLC(aEntry);
+ CleanupStack::Pop();
+ return self;
+ }
+
+
+/**
+ * NewLC()
+ * @param CMsvCacheEntry& : a new cache entry
+ * @return The newly created index table entry
+ *
+ * It returns an instance of the CMsvCacheIndexTableEntry class
+ * with the passed entry added. It leaves the object into cleanup stack.
+ */
+CMsvCacheIndexTableEntry* CMsvCacheIndexTableEntry::NewLC(CMsvCacheEntry*& aEntry)
+ {
+ CMsvCacheIndexTableEntry *self = new(ELeave) CMsvCacheIndexTableEntry();
+ CleanupStack::PushL(self);
+ self->AddEntryL(aEntry);
+ return self;
+ }
+
+
+
+
+/**
+ * NewL()
+ * @param RPointerArrayCMsvCacheEntry>& : RPointerArray reference to child entries
+ * @return The newly created index table entry
+ *
+ * It returns an instance of the CMsvCacheIndexTableEntry class filled with child
+ * entries.
+ */
+CMsvCacheIndexTableEntry* CMsvCacheIndexTableEntry::NewL(RPointerArray<CMsvCacheEntry>& aEntries, TInt aInitIndex /*(DEFALUT=0)*/, TInt aCount /* DEFAULT = -1*/)
+ {
+ CMsvCacheIndexTableEntry *self = CMsvCacheIndexTableEntry::NewLC(aEntries, aInitIndex, aCount);
+ CleanupStack::Pop();
+ return self;
+ }
+
+
+
+
+/**
+ * NewLC()
+ * @param RPointerArrayCMsvCacheEntry>& : RPointerArray reference to child entries
+ * @return The newly created index table entry
+ *
+ * It returns an instance of the CMsvCacheIndexTableEntry class filled with child
+ * entries. It leaves the object into cleanup stack.
+ */
+CMsvCacheIndexTableEntry* CMsvCacheIndexTableEntry::NewLC(RPointerArray<CMsvCacheEntry>& aEntries, TInt aInitIndex /*(DEFALUT=0)*/, TInt aCount /* DEFAULT = -1*/)
+ {
+ CMsvCacheIndexTableEntry *self = new(ELeave) CMsvCacheIndexTableEntry();
+ CleanupStack::PushL(self);
+ self->AddEntrySetL(aEntries, aInitIndex, aCount);
+ return self;
+ }
+
+
+
+
+/**
+ * CMsvCacheIndexTableEntry()
+ * @param None.
+ * @return None.
+ *
+ * Constructor
+ */
+CMsvCacheIndexTableEntry::CMsvCacheIndexTableEntry()
+:iMinMsvId(0), iMaxMsvId(0), iFlags(EMsvCacheIndexTableClearFlag)
+ {
+ iTimeStamp.HomeTime(); //set the timestamp to number of seconds since Epoc.
+ iBlockPtr = NULL;
+ }
+
+
+/**
+ * ~CMsvCacheIndexTableEntry()
+ * @param None.
+ * @return None.
+ *
+ * Destructor - releases the block to the cache free pool and sets it to NULL.
+ */
+CMsvCacheIndexTableEntry::~CMsvCacheIndexTableEntry()
+ {
+ //destructor should delete everything no matter if entries are locked or not
+ ReleaseBlock(ETrue);
+ }
+
+
+/**
+ * AddEntryL()
+ * @param CMsvCacheEntry& : reference to the CMsvCacheEntry to be added.
+ * @return None.
+ *
+ * The function adds an entry into the index table. The entity who passes the entry
+ * to the function will give up ownership of the same and hence cannot modify or
+ * delete it.
+ * 1. If the block is NULL, it creates a new one and appends the entry to the block
+ * and accordingly sets the TMsvId ranges.
+ * 2. If block is not NULL, then append the entry to it.
+ * 2.1 If the entry already exists in the block then release the old entry from the block and
+ * append the new one.
+ * 2.2 If the entry fits only at the end of the last block then we need to change
+ * the iMaxMsvid.
+ * If the indextable has not been created and if the folder has just one block, and this block contains
+ * random entries, then we may need to set the iMinMsvId.
+ */
+void CMsvCacheIndexTableEntry::AddEntryL(CMsvCacheEntry*& aEntry, TBool aReplace /* DEFAULT = EFalse*/)
+ {
+ TMsvId entryId = aEntry->GetId();
+ // 1. If the block is NULL, it creates a new one and appends the entry to the block
+ // and accordingly sets the TMsvId ranges.
+ if(NULL == iBlockPtr)
+ {
+ iBlockPtr = new(ELeave) RPointerArray<CMsvCacheEntry>;
+ iBlockPtr->AppendL(aEntry);
+ SetMinMsvIdRange(entryId);
+ SetMaxMsvIdRange(entryId);
+ } //if(NULL == iBlockPtr)
+
+ // 2. If block is not NULL:
+ else
+ {
+ // 2.1 If the entry already exists in the block then release the old entry from the
+ // block and append the new one.
+ TInt blockSize = Size();
+ for(TInt blockIndex = 0; blockIndex < blockSize; ++blockIndex)
+ {
+ if((*iBlockPtr)[blockIndex]->GetId() == aEntry->GetId())
+ {
+ if(!aReplace)
+ {
+ CMsvEntryFreePool::Instance()->ReleaseEntry(aEntry);
+ aEntry = (*iBlockPtr)[blockIndex];
+ return;
+ }
+ CMsvEntryFreePool::Instance()->ReleaseEntry((*iBlockPtr)[blockIndex]);
+ iBlockPtr->Remove(blockIndex);
+ iBlockPtr->Insert(aEntry, blockIndex);
+ return;
+ }
+ }
+ iBlockPtr->AppendL(aEntry);
+
+ // 2.2 If the entry fits only at the end of the last block then we need to
+ // change the iMaxMsvid.
+ // If the indextable has not been created and if the folder has just
+ // one block, and this block contains random entries, then we may need to
+ // set the iMinMsvId.
+ if(entryId > iMaxMsvId)
+ {
+ SetMaxMsvIdRange(entryId);
+ }
+
+ if(entryId < iMinMsvId)
+ {
+ SetMinMsvIdRange(entryId);
+ }
+ } //else
+ iTimeStamp.HomeTime();
+ }
+
+
+
+
+/**
+ * AddEntrySetL()
+ * @param RPointerArray<CMsvCacheEntry>& : reference to the new entry set to be added.
+ * These entries can either be immediate children
+ * or non-immediate children, but not both.
+ * @param TInt aInitIndex : Start index of the entry to be added in the entryList.
+ * @param TInt aCount : Number of entries that should be added.
+ * @return None.
+ *
+ * The function adds a set of entries to the index table. The caller who passes the
+ * array of entries to the function will give up ownership of the entries in the array.
+ * 1. When the block is NULL:
+ * 1.1 If children of a non-immediate folder are present in the array then set the
+ * grandchildren and dirty flags.
+ * 1.2 If there aren't, then clear the above two flags.
+ * 1.3 Assign the new entry set to the block, but reset the passed set so that
+ * the caller cannot modify or delete the cache entries.
+ * 2. When the block is not NULL:
+ * 2.1 If children of a non-immediate folder are present in the array then
+ * set the grandchildren flag and simply append entries to the block.
+ * 2.2 If there aren't, append entries avoiding duplication.
+ * 2.2.1 Search for each entry that is present in the current block in the
+ * new set passed. If the entry is present then release it from the
+ * current block. If not then append to the new set.
+ * 2.2.2 All entries are now in the passed array. Reset the current block,
+ * allocate space for it and copy the entries to it. Also reset the
+ * passed array so that callers do not have access to the cache
+ * entries after the addition.
+ * 3. Calculate and set the maximum and minimum TMsvId ranges in the newly added set.
+ */
+void CMsvCacheIndexTableEntry::AddEntrySetL(RPointerArray<CMsvCacheEntry>& aEntries, TInt aInitIndex /*(DEFAULT=0)*/, TInt aCount /* DEFAULT=-1 */)
+ {
+ // Add all entries if aCount is -1.
+ TInt arrSize = aEntries.Count();
+ if(-1 == aCount)
+ {
+ aCount = arrSize;
+ }
+ if(aInitIndex < 0 || aInitIndex >= arrSize)
+ {
+ return;
+ }
+
+ // 1. When the block is NULL:
+ if(NULL == iBlockPtr)
+ {
+ // Assign the new entry set to the block, but reset the passed set so that
+ // the caller cannot modify or delete the cache entries.
+ // Update the ranges of the block.
+
+ iBlockPtr = new(ELeave) RPointerArray<CMsvCacheEntry>;
+ for(TInt listIndex = 0; (listIndex < aCount) && (arrSize > listIndex+aInitIndex); ++listIndex)
+ {
+ iBlockPtr->AppendL(aEntries[listIndex+aInitIndex]);
+ }
+
+ } //if(NULL == iBlockPtr)
+
+ // 2. When the block is not NULL append the entries. If there is a duplicate entry,
+ // discard the new entry.
+ else
+ {
+ TBool entryFound = EFalse;
+ TInt blockSize = Size();
+ for(TInt listCount = 0; (listCount < aCount) && (arrSize > listCount+aInitIndex); ++listCount)
+ {
+ entryFound = EFalse;
+ for(TInt blockIndex = 0; blockIndex < blockSize; ++blockIndex)
+ {
+ if(aEntries[listCount+aInitIndex]->GetId() == (*iBlockPtr)[blockIndex]->GetId())
+ {
+ CMsvEntryFreePool::Instance()->ReleaseEntry(aEntries[listCount+aInitIndex]);
+ aEntries.Remove(listCount+aInitIndex);
+ aEntries.Insert((*iBlockPtr)[blockIndex], listCount+aInitIndex);
+ entryFound = ETrue;
+ break;
+ }
+ } //for()
+ if(!entryFound)
+ {
+ iBlockPtr->AppendL(aEntries[listCount+aInitIndex]);
+ }
+ } //for()
+ } //else
+ iTimeStamp.HomeTime();
+ }
+
+
+
+
+/**
+ * GetEntry()
+ * @param TMsvId : the TMsvId of the entry to be fetched.
+ * @param CMsvCacheEntry*& : output parameter for the entry.
+ * @return TBool.
+ *
+ * The function fetches the entry with the specified TMsvId.
+ * 1. If the block is NULL, there is no entry that can be fetched. Return EFalse.
+ * 2. Iterate through the block searching for the TMsvId and return ETrue for a hit
+ * 3. Return EFalse if the entry is not present in the block.
+ */
+TBool CMsvCacheIndexTableEntry::GetEntry(TMsvId aId, CMsvCacheEntry*& aEntry)
+ {
+ // 1. If the block is NULL, there is no entry that can be fetched. Return EFalse.
+ if(NULL == iBlockPtr)
+ {
+ aEntry = NULL;
+ return EFalse;
+ }
+
+ // 2. Iterate through the block searching for the TMsvId and return ETrue for a hit.
+ TInt blockSize = Size();
+ for(TInt index = 0 ; index < blockSize ; ++index)
+ {
+ if((*iBlockPtr)[index]->GetId() == aId)
+ {
+ aEntry = (*iBlockPtr)[index];
+ iTimeStamp.HomeTime();
+ return ETrue;
+ }
+ } //for
+
+ // 3. Return EFalse if the entry is not present in the block.
+ return EFalse;
+ }
+
+
+/**
+ * GetChildrenL()
+ * @param TMsvId : TMsvId of the parent entry of the entries to be fetched.
+ * @param RPointerArray<CMsvCacheEntry>*& : output parameter for the entries to be
+ * fetched.
+ * @return None.
+ *
+ * The function fetches a set of entries with the specified parent TMsvId.
+ * 1. Check if there are grandchildren present in the block.
+ * 1.1. If yes, then fetch only those entries with parent Id as aParentId.
+ * If the array of entries is NULL, then allocate space for it.
+ * 1.2. If not, then return a copy of the whole block.
+ */
+void CMsvCacheIndexTableEntry::GetChildrenL(TMsvId aParentId, RPointerArray<CMsvCacheEntry>& aEntries) /*const*/
+ {
+ // 1. Check if there are grandchildren present in the block.
+ if(IsGrandChildPresent())
+ {
+ // 1.1 If yes, then fetch only those entries with parent Id as aParentId.
+ // If the array of entries is NULL, then allocate space for it.
+ TInt blockSize = Size();
+ for(TInt index = 0 ; index < blockSize ; ++index)
+ {
+ if((*iBlockPtr)[index]->Entry().Parent() == aParentId)
+ {
+ aEntries.AppendL((*iBlockPtr)[index]);
+ }
+ }
+ } //if(IsGrandChildPresent())
+
+ else
+ {
+ // 1.2 If not, then return a copy of the whole block.
+ TInt blockSize = Size();
+ for(TInt index = 0 ; index < blockSize ; ++index)
+ {
+ aEntries.AppendL((*iBlockPtr)[index]);
+ }
+ } //else
+ iTimeStamp.HomeTime();
+ }
+
+
+/**
+ * DeleteEntryL()
+ * @param TMsvId : the TMsvId of the entry to be deleted.
+ * @param aParentIdOfEntry
+ * @param aForceDelete TBool, it indicates whether the entry needs to be locked while deleting.
+ * @return None.
+ *
+ * The function deletes an entry from the cache releasing the entry to the cache free
+ * pool. The function is called when the entry is being deleted from both the DB and
+ * cache.
+ * 1. Return if the block is NULL.
+ * 2. Iterate through the block searching for the TMsvId.
+ * 2.1 If the entry exists, remove it and release to the free pool. Deletion
+ * is possible only if the entry is locked in the cache, otherwise the function
+ * returns KErrAccessDenied.
+ * 2.1.1 If the entry deleted was the last entry in the block, delete the
+ * block.
+ * 3. Leave with KErrNotFound if the entry does not exist in the block.
+ */
+void CMsvCacheIndexTableEntry::DeleteEntryL(TMsvId aId, TMsvId& aParentIdOfEntry /*DEFAULT = NULL*/, TBool aForceDelete /*DEFAULT=EFalse*/)
+ {
+ // 1. Return if the block is NULL.
+ if(NULL == iBlockPtr)
+ {
+ User::Leave(KErrNotFound);
+ }
+
+ // 2. Iterate through the block searching for the TMsvId.
+ TInt blockSize = Size();
+ for(TInt index = 0 ; index < blockSize ; ++index)
+ {
+ // 2.1 If the entry exists, remove it and release to the free pool. Deletion
+ // is possible only if the entry is locked in the cache.
+ if((*iBlockPtr)[index]->GetId() == aId)
+ {
+ if(aForceDelete || (*iBlockPtr)[index]->IsEntryLocked())
+ {
+ aParentIdOfEntry = (*iBlockPtr)[index]->Entry().Parent();
+ CMsvEntryFreePool::Instance()->ReleaseEntry((*iBlockPtr)[index]);
+ iBlockPtr->Remove(index);
+ // 2.1.1. If the entry deleted was the last entry in the block,
+ // delete the block.
+ if(iBlockPtr->Count() == 0)
+ {
+ iBlockPtr->Close();
+ delete iBlockPtr;
+ iBlockPtr = NULL;
+ }
+ iTimeStamp.HomeTime();
+ }
+ else
+ {
+ User::Leave(KErrAccessDenied);
+ }
+ return;
+ }
+ } //for
+ // 3. Leave with KErrNotFound if the entry does not exist in the block.
+ User::Leave(KErrNotFound);
+ }
+
+
+/**
+ * ReleaseBlock()
+ * @param TBool: internally used flag which is used by destructor to forcibly swap out
+ * the block even if entries have been locked.
+ * @return TBool: EFalse if block cannot be released as a result of entries having been
+ * locked in the cache, ETrue if otherwise.
+ *
+ * The function releases a block to the cache free pool.
+ * 1. Return EFalse if any of the entries in the block have been locked. Do not
+ * swap out the block to the free pool if so.
+ * 2. No entries are locked and/or the block is to be swapped out forcibly.
+ * 2.1 Release the entries to the free pool.
+ * 2.2 Free the memory allocated to the block itself.
+ * 2.3 Set the dirty flag.
+ */
+TBool CMsvCacheIndexTableEntry::ReleaseBlock(TBool aForceRelease /*DEFAULT = EFalse*/)
+ {
+ if(NULL == iBlockPtr)
+ {
+ return ETrue;
+ }
+ // 1. Return EFalse if any of the entries in the block have been locked. Do not
+ // swap out the block to the free pool if so.
+ if(!aForceRelease)
+ {
+ TInt blockSize = Size();
+ for(TInt index = 0; index < blockSize; ++index)
+ {
+ if(!(*iBlockPtr)[index]->IsEntrySwappable())
+ {
+ return EFalse;
+ }
+ }
+ }
+
+ // 2. No entries are locked and the block can be swapped out safely.
+ CMsvEntryFreePool::Instance()->ReleaseEntrySet(*iBlockPtr);
+
+ iBlockPtr->Close();
+ delete iBlockPtr;
+ iBlockPtr = NULL;
+ SetDirty();
+ return ETrue;
+ }
+
+
+/**
+ * CompareOrder()
+ * @param const CMsvCacheEntry& : the first operand
+ * @param const CMsvCacheEntry& : the second operand
+ * @return TInt : the order (-1/0/+1)
+ *
+ * The function returns the order for the sort operation.
+ */
+static TInt CompareOrder(const CMsvCacheEntry& aFirst, const CMsvCacheEntry& aSecond)
+ {
+ return aFirst.GetId() - aSecond.GetId();
+ }
+
+
+/**
+ * SortBlockL()
+ * @param None.
+ * @return None.
+ *
+ * The function is called by a background active object to sort the index table
+ * according to TMsvIds of the entries.
+ * 1. Sort based on the order in the TLinearOrder package.
+ */
+void CMsvCacheIndexTableEntry::SortBlock()
+ {
+ if(iBlockPtr != NULL)
+ {
+ // 1. Sort based on the order in the TLinearOrder package.
+ TLinearOrder<CMsvCacheEntry> order(CompareOrder);
+ iBlockPtr->Sort(order);
+ }
+ }
+
+
+/**
+ * EntryExists()
+ * @param TMsvId : the Id of the entry to be checked for existence.
+ * @return TBool : success/failure.
+ *
+ * The function return EFalse if either the block is NULL or the entry does not exist.
+ * ETrue is returned for a hit.
+ */
+TBool CMsvCacheIndexTableEntry::EntryExists(TMsvId aId) const
+ {
+ if(NULL == iBlockPtr)
+ {
+ return EFalse;
+ }
+ TInt blockSize = Size();
+ for(TInt index = 0 ; index < blockSize ; ++index)
+ {
+ if(aId == (*iBlockPtr)[index]->GetId())
+ {
+ return ETrue;
+ }
+ } //for
+ return EFalse;
+ }
+
+
+/**
+ * UpdateChildMsvIdsL()
+ * @param TMsvId : TMsvId of the parent entry.
+ * @param TMsvId : TMsvId of the child entry.
+ * @param TBool : flag, set to ETrue if aChildId is to be added, and EFalse if it is
+ * to be removed from the parent's child array.
+ * @return None.
+ *
+ * The function updates the child array of the parent entry if it is not NULL.
+ * 1. Return if the block is NULL, i.e. the parent is not in the cache.
+ * 2. Iterate through the block searching for the parent entry.
+ * 2.1 If the iChildIdArray is not NULL:
+ * 2.1.1 If the child has to be added as a consequence of it being
+ * added to the cache, then append it to the child array.
+ * 2.1.2 If the child has to be removed as a consequence to the child
+ * entry being deleted, then remove it from the child array.
+ */
+void CMsvCacheIndexTableEntry::UpdateChildMsvIdsL(TMsvId aParentId, TMsvId aChildId, TBool aAdd /*DEFAULT = ETrue*/)
+ {
+ // 1. Return if the block is NULL, i.e. the parent is not in the cache.
+ if(NULL == iBlockPtr)
+ {
+ return;
+ }
+
+ // 2. Iterate through the block searching for the parent entry.
+ TInt blockSize = Size();
+ for(TInt index = 0 ; index < blockSize ; ++index)
+ {
+ if((*iBlockPtr)[index]->GetId() == aParentId)
+ {
+ RArray<TMsvId>* childArr = (*iBlockPtr)[index]->ChildIdArray();
+ // 2.1 If the iChildIdArray is not NULL: i.e GetChildren has been performed
+ if(childArr != NULL)
+ {
+ // 2.1.1 If the child has to be added as a consequence of it being
+ // added to the cache, then append it to the child array.
+ TInt arrSize = childArr->Count();
+ if(aAdd)
+ {
+ TInt index = childArr->Find(aChildId);
+ if(index == KErrNotFound)
+ {
+ childArr->AppendL(aChildId);
+ }
+ }
+
+ // 2.1.2 If the child has to be removed as a consequence to the child
+ // entry being deleted, then remove it from the child array.
+ else
+ {
+ TInt index = childArr->Find(aChildId);
+ if(index != KErrNotFound)
+ {
+ childArr->Remove(index);
+ }
+ }
+ } //if(((*iBlockPtr)[index]->ChildIdArray()) != NULL)
+ return;
+ } //if((*iBlockPtr)[index]->GetId() == aParentId)
+ } //for(TInt index = 0 ; index < Size() ; index++)
+}
+
+
+/**
+ * UpdateChildMsvIdsL()
+ * @param RPointerArray<CMsvCacheEntry>& : array of complete set of child
+ * CMsvCacheEntries sorted by TMsvId.
+ * @return None.
+ *
+ * The function updates, or creates if necessary, a parent entry's iChildIdArray with
+ * the children entries passed to it in the form of a RPointerArray.
+ * 1. Return if the block is NULL, i.e. the parent is not in the cache.
+ * 2. Otherwise, find the parent sequentially.
+ * 2.1 If the parent is found:
+ * 2.1.1 If the parent already has a iChildIdArray, i.e. if GetChildren() has
+ * been performed on it, delete and create a new child array with the
+ * entries passed. If iChildIdArray is NULL then GetChildren() has not been
+ * performed on the entry yet, in which case append the passed children.
+ */
+void CMsvCacheIndexTableEntry::UpdateChildMsvIdsL(RPointerArray<CMsvCacheEntry>& aEntries)
+ {
+
+ // 1. Return if the block is NULL, i.e. the parent is not in the cache.
+ if(NULL == iBlockPtr)
+ {
+ return;
+ }
+
+ // 2. Otherwise, find the parent sequentially.
+ TMsvId parentId = aEntries[0]->Entry().Parent();
+ TInt blockSize = Size();
+ for(TInt index = 0 ; index < blockSize ; ++index)
+ {
+ // 2.1 If the parent is found:
+ if((*iBlockPtr)[index]->Entry().Id() == parentId)
+ {
+ // 2.1.1 If the parent already has a iChildIdArray, i.e. if GetChildren() has
+ // been performed on it, delete and create a new child array with the
+ // entries passed. If iChildIdArray is NULL then GetChildren() has not been
+ // performed on the entry yet, in which case append the passed children.
+ RArray<TMsvId>* childArr = (*iBlockPtr)[index]->ChildIdArray();
+ TInt entryCount = aEntries.Count();
+ if(NULL == childArr)
+ {
+ childArr = new(ELeave) RArray<TMsvId>;
+ (*iBlockPtr)[index]->SetChildIdArray(childArr);
+ }
+ else
+ {
+ childArr->Reset();
+ }
+ while(0 < entryCount)
+ {
+ TInt leave = childArr->Append(aEntries[--entryCount]->GetId());
+ if(KErrNone != leave)
+ {
+ childArr->Close();
+ delete childArr;
+ (*iBlockPtr)[index]->SetChildIdArray(NULL);
+ User::Leave(leave);
+ }
+ }
+ return;
+ } //if((*iBlockPtr)[index]->Entry().Parent() == parentId)
+ } //for(TInt index = 0 ; index < blockSize ; ++index)
+ }
+
+
+/**
+ *SplitBlock
+ *This will be called when the block size will be more than 120, this will split the block
+ * into 2 blocks.
+ *@param aSplitBlock RPointerArray<CMsvCacheEntry>& that will be filled with CMsvCacheEntries,
+ *@param aMaxId The maximum TMsvId of the first block.
+ *@return void
+ *
+ */
+void CMsvCacheIndexTableEntry::SplitBlockL(RPointerArray<CMsvCacheEntry>& aSplitBlock)
+ {
+ TInt size = Size();
+ TInt i = size/2;
+ while(i < size)
+ {
+ aSplitBlock.AppendL((*iBlockPtr)[size/2]);
+ iBlockPtr->Remove(size/2);
+ i++;
+ }
+ }
+
+
+
+
+
+#if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
+#ifdef _DEBUG
+// To print message index cache.
+void CMsvCacheIndexTableEntry::Print(RFileLogger& aLogger)
+ {
+ _LIT(KId, " ID: ");
+ _LIT(KParentId, " ParentId: ");
+ TInt blockSize = Size();
+ for(TInt index=0; index<blockSize; ++index)
+ {
+ RBuf text;
+ text.Create(150);
+ text.Append(KId);
+ text.AppendNum((*iBlockPtr)[index]->Entry().Id());
+ text.Append(KParentId);
+ text.AppendNum((*iBlockPtr)[index]->Entry().Parent());
+ text.Append(_L(" VisibleEntry: "));
+ text.AppendNum((*iBlockPtr)[index]->Entry().VisibleFolderFlag());
+ text.Append(_L(" Complete flag:"));
+ text.AppendNum((*iBlockPtr)[index]->Entry().Complete());
+ text.Append(_L(" Description:"));
+ text.Append((*iBlockPtr)[index]->Entry().iDetails);
+ aLogger.Write(text);
+ text.Close();
+ }
+ }
+#endif // #ifdef _DEBUG
+#endif // #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)