First public contribution.
1 // Copyright (c) 2008-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 the License "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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // f32\sfat\sl_leafdir_cache.cpp
19 #include "sl_leafdir_cache.h"
25 Get the lru list count
27 @return the count of lru list
29 TInt CLeafDirTree::LruCount() const
31 return iLruList.Count();
35 Count currently cached items
37 @return the number of currently cached items
39 TInt CLeafDirCache::CacheCount() const
41 return iTree->LruCount();
44 //---------------------------------------------------------------------------------------------------------------------------------
46 Default constructor of TDirPosition, a data structure that represents a location of directory
48 TLeafDirData::TLeafDirData()
49 :iClusterNum(0),iMRUPos(0,0)
54 Constructor of TDirPosition, a data structure that represents a location of directory
56 @param aClusterNum the cluster number of the directory stores
58 TLeafDirData::TLeafDirData(TUint aClusterNum)
59 :iClusterNum(aClusterNum),iMRUPos(0,0)
64 Constructor of TDirPosition, a data structure that represents a location of directory
66 @param aClusterNum the cluster number of the directory stores
68 TLeafDirData::TLeafDirData(TUint aClusterNum, const TEntryPos& aMRUPos)
69 :iClusterNum(aClusterNum),iMRUPos(aMRUPos.Cluster(), aMRUPos.Pos())
76 Factory fucntion of tree nodes
78 @param aOwnerTree a pointer of the tree that owns this node
79 @param aPathName the directory path this node represents
80 @param aDirPos the location of the directory this node represents
81 @param aType the type of the node
83 CLeafDirTreeNode* CLeafDirTreeNode::NewL(CLeafDirTree* aOwnerTree, const TDesC& aPathName, const TLeafDirData& aDirPos, TLeafDirTreeNodeType aType)
85 CLeafDirTreeNode* self = new(ELeave) CLeafDirTreeNode(aDirPos, aType);
86 CleanupStack::PushL(self);
87 self->ConstructL(aOwnerTree, aPathName);
93 Constructor of tree nodes
95 @param aDirPos the location of the directory this node represents
96 @param aType the type of the node
98 CLeafDirTreeNode::CLeafDirTreeNode(const TLeafDirData& aDirPos, TLeafDirTreeNodeType aType)
99 :iParent(NULL), iLeafDirData(aDirPos), iNodeType(aType)
104 2nd phase constructor of tree nodes
106 @param aOwnerTree a pointer of the tree that owns this node
107 @param aPathName the directory path this node represents
109 void CLeafDirTreeNode::ConstructL(CLeafDirTree* aOwnerTree, const TDesC& aPath)
111 if (aOwnerTree == NULL)
114 User::Leave(KErrArgument);
116 iOwnerTree = aOwnerTree;
117 iPath.CreateL(aPath);
119 iOwnerTree->AddToObjectContainerL(this);
124 Destructor of tree nodes
126 @pre The node should already be removed from its parent before being deleted
128 CLeafDirTreeNode::~CLeafDirTreeNode()
131 TRAPD(err, iOwnerTree->RemoveFromObjectContainerL(this));
132 ASSERT(err == KErrNone);
141 @param aType the type to be set
143 void CLeafDirTreeNode::SetType(const CLeafDirTreeNode::TLeafDirTreeNodeType aType)
145 // Root node can not be reset type
146 if (iNodeType == CLeafDirTreeNode::ERoot)
152 Set path of the directory the node represents
154 @param aPath the path to be set
156 void CLeafDirTreeNode::SetPathL(const TDesC& aPath)
158 ASSERT(aPath.Length() > 0);
159 if (iPath.Length() < aPath.Length())
161 TInt err = iPath.ReAlloc(aPath.Length());
162 ASSERT(err==KErrNone);
163 User::LeaveIfError(err);
169 Removes from the children list, sets aNode's parent NULL, does not delete aNode
171 @param aNode the node to be removed
173 TInt CLeafDirTreeNode::RemoveChild(CLeafDirTreeNode* aNode)
182 if (iChildren.Count() > 0)
184 for (TInt i = iChildren.Count() - 1; i >= 0; i--)
186 if (iChildren[i] == aNode)
189 aNode->SetParent(NULL);
198 Add a new child node to self
200 @pre aNode should have been removed from its original parent
201 @param aNode the node to be added
203 void CLeafDirTreeNode::MakeItChildL(CLeafDirTreeNode* aNode)
205 ASSERT(aNode->Parent() == NULL);
209 User::Leave(KErrArgument);
211 iChildren.AppendL(aNode);
212 aNode->SetParent(this);
217 Factory function of CLeafDirTree
219 @param aLimit the maximum number of 'leaf' nodes allowed of the tree
221 CLeafDirTree* CLeafDirTree::NewL(TUint32 aSize)
223 CLeafDirTree* self = new(ELeave) CLeafDirTree(aSize);
224 CleanupStack::PushL(self);
231 Constructor of CLeafDirTree
233 @param aLimit the maximum number of 'leaf' nodes allowed of the tree
235 CLeafDirTree::CLeafDirTree(TUint32 aSize)
240 _LIT(KRootDirPath, "\\");
242 2nd phase constructor of CLeafDirTree
244 void CLeafDirTree::ConstructL()
246 TLeafDirData rootDirPos(0);
247 CLeafDirTreeNode* root = CLeafDirTreeNode::NewL(this, KRootDirPath, rootDirPos, CLeafDirTreeNode::ERoot);
249 iRoot->SetType(CLeafDirTreeNode::ERoot);
253 Destructor of CLeafDirTree
255 CLeafDirTree::~CLeafDirTree()
267 Free all the nodes from the tree except root node
269 void CLeafDirTree::Reset()
272 TRAP(err, DeleteSubTreeL(iRoot));
273 ASSERT(err == KErrNone);
277 Search for a node by directory path
279 @param aPath the path as the key to search in the tree
280 @param aNodeFound in return, the node found
281 @param aDirPos the location of the directory
282 @return KErrNone if a node found
283 KErrNotFound if no node is found
285 TInt CLeafDirTree::Search(const TDesC& aPath, CLeafDirTreeNode*& aNodeFound, TLeafDirData& aDirPos)
287 return (DoSearch(aPath, iRoot, aNodeFound, aDirPos));
291 Search for a node by directory path, start from children of aNodeToStart but do not include aNodeToStart.
293 @param aPath the path as the key to search in the tree
294 @param aNodeToStart the node whose children to start with
295 @param aNodeFound in return, the node found
296 @param aDirPos the location of the directory
297 @return KErrNone if a node found
298 KErrNotFound if no node is found
300 TInt CLeafDirTree::DoSearch(const TDesC& aPath, CLeafDirTreeNode* aNodeToStart, CLeafDirTreeNode*& aNodeFound, TLeafDirData& aLeafDirData)
302 RPointerArray<CLeafDirTreeNode> currentLevel = aNodeToStart->Children();
303 TInt currentPos = currentLevel.Count() - 1;
304 // Current path in search
306 currentPath.Set(aPath);
307 while (currentLevel.Count() > 0 && currentPos >= 0)
309 CLeafDirTreeNode* currentNode = currentLevel[currentPos];
310 TPtrC currentNodePath;
311 currentNodePath.Set(currentNode->Path());
312 TInt foundPos = currentPath.FindF(currentNodePath);
313 // If current child's path is part of the searching path,
315 // E.g.: current child's path = "1\2\3\", searching path = "1\2\3\5\".
316 if (foundPos == 0 && currentNodePath.Length() < currentPath.Length())
318 currentPath.Set(currentPath.Mid(currentNodePath.Length()));
319 currentLevel = currentNode->Children();
320 currentPos = currentLevel.Count() - 1;
323 // If current child's path matches current searching path,
324 // check the node type.
325 else if (foundPos == 0 && currentNodePath.Length() == currentPath.Length())
327 if (currentNode->IsPureIntermediary())
328 // If found is 'pure intermediary', it is not cached.
332 // Otherwise, we have got a cache hit!
333 MakeMostRecentlyUsed(currentNode);
334 aNodeFound = currentNode;
335 aLeafDirData = currentNode->LeafDirData();
338 // else, go through current level
341 // If there is no child or we have not found any matching node,
342 // return KErrNotFound
347 Find the longest common 'path' between two paths.
348 Note: not the longest common 'string'.
352 @return the length of the longest common path found
353 KErrNotFound if no node is found
355 TInt FindLongestCommonPath(const TDesC& aPathA, const TDesC& aPathB)
357 const TInt compareLength = Min(aPathA.Length(), aPathB.Length());
358 if (compareLength <= 0)
363 TInt lastPathDelimiterPos = KErrNotFound;
364 while (i < compareLength && aPathA[i] == aPathB[i])
366 if (aPathA[i] == '\\')
368 lastPathDelimiterPos = i;
377 return lastPathDelimiterPos;
381 Insert a new node to the tree according to the path
383 @param aPath the path of the new node to be inserted
384 @param aDirPos the position of the new node to be inserted
385 @param aNodeInserted in return, the node that has been successfully inserted
387 void CLeafDirTree::InsertL(const TDesC& aPath, const TLeafDirData& aLeafDirData, CLeafDirTreeNode*& aNodeInserted)
389 ASSERT(aPath.Length() > 0);
390 // aPath should always start and end with a '\\'.
391 if (aPath[0] == '\\' && aPath[aPath.Length() - 1] =='\\')
393 if (aPath.Length() > 1)
396 path.Set(aPath.Mid(1));
397 DoInsertL(iRoot, path, aLeafDirData, aNodeInserted);
403 User::Leave(KErrBadName);
408 Implementation of the insertion algorithm
410 @param aNodeToStart the node whose children to start with
411 @param aPath the path of the new node to be inserted
412 @param aDirPos the position of the new node to be inserted
413 @param aNodeInserted in return, the node that has been successfully inserted
415 void CLeafDirTree::DoInsertL(CLeafDirTreeNode* aNodeToStart, const TDesC& aPath, const TLeafDirData& aLeafDirData, CLeafDirTreeNode*& aNodeInserted)
417 CLeafDirTreeNode* currentParent = aNodeToStart;
419 RPointerArray<CLeafDirTreeNode> currentLevel = aNodeToStart->Children();
420 TInt currentPos = currentLevel.Count() - 1;
422 currentPath.Set(aPath);
423 while (currentLevel.Count() > 0 && currentPos >= 0)
425 CLeafDirTreeNode* currentNode = currentLevel[currentPos];
426 TPtrC currentNodePath;
427 currentNodePath.Set(currentNode->Path());
429 // If current node is contained by aPath.
430 // E.g.: current node = "1\2\3\", currentPath = "1\2\3\5\"
431 // In this case, we need to go to next level,
432 // discard logged position (currentPos) in this level as we don't need to come back.
433 foundPos = currentPath.FindF(currentNodePath);
434 if (foundPos == 0 && currentNodePath.Length() < currentPath.Length())
436 currentParent = currentNode;
437 currentLevel = currentNode->Children();
438 currentPos = currentLevel.Count() - 1;
439 currentPath.Set(currentPath.Mid(currentNodePath.Length()));
443 // If current node's path contains aPath
444 // E.g.: current node = "1\2\3\4\", currentPath = "1\2\3\"
445 // We need to split current node to two nodes and return.
446 foundPos = currentNodePath.FindF(currentPath);
447 if (foundPos == 0 && currentNodePath.Length() > currentPath.Length())
449 CLeafDirTreeNode* newNode = CLeafDirTreeNode::NewL(this, currentPath, aLeafDirData, CLeafDirTreeNode::ELeafIntermediary);
450 currentParent->MakeItChildL(newNode);
453 restPath.Set(currentNodePath.Mid(currentPath.Length()));
454 currentNode->SetPathL(restPath);
455 currentParent->RemoveChild(currentNode);
457 newNode->MakeItChildL(currentNode);
458 AddOntoLruL(newNode);
459 aNodeInserted = newNode;
463 // If current node's path equals aPath,
464 // change the node type if it is necessary
465 if (foundPos == 0 && currentNodePath.Length() == currentPath.Length())
467 // Check node type, if already cached, update Lru list and return.
468 if (currentNode->IsLeaf() || currentNode->IsLeafIntermediary())
470 currentNode->SetLeafDirData(aLeafDirData);
471 aNodeInserted = currentNode;
472 MakeMostRecentlyUsed(currentNode);
475 // If it has not been cached yet, i.e., it is a 'pure intermediary' node,
476 // cache the node and put it onto Lru list
477 else if(currentNode->IsPureIntermediary())
479 currentNode->SetLeafDirData(aLeafDirData);
480 currentNode->SetType(CLeafDirTreeNode::ELeafIntermediary);
481 AddOntoLruL(currentNode);
482 aNodeInserted = currentNode;
487 // If none of above is the case (i.e. haven't found exact match or paths
488 // are not contained by each other), we need to find the first common part
489 // between each child and aPath to share path data.
490 foundPos = FindLongestCommonPath(currentNodePath, currentPath);
491 // If a common part of path is found, we need to create a pure intermediary node to share
492 // the common part of path data, and create a new leaf node for the target path.
496 commonPath.Set(currentNodePath.Left(foundPos + 1));
498 currentNodePath.Set(currentNodePath.Mid(foundPos + 1));
500 newLeafPath.Set(currentPath.Mid(foundPos + 1));
502 // Add new pureintermediary node, set it as child of current parent
503 TLeafDirData dummyPos(0);
504 CLeafDirTreeNode* newPureIntermediaryNode = CLeafDirTreeNode::NewL(this, commonPath, dummyPos, CLeafDirTreeNode::EPureIntermediary);
505 currentParent->MakeItChildL(newPureIntermediaryNode);
507 // Remove current child from aNodeToStart, do not need to change
508 // node type of aNodeToStart
509 currentParent->RemoveChild(currentNode);
511 // Modify current pathData, make it child of new node
512 newPureIntermediaryNode->MakeItChildL(currentNode);
513 currentNode->SetPathL(currentNodePath);
515 // Add new leaf node as a child of the new pure intermediary node
516 CLeafDirTreeNode* newLeafNode = CLeafDirTreeNode::NewL(this, newLeafPath, aLeafDirData, CLeafDirTreeNode::ELeaf);
517 newPureIntermediaryNode->MakeItChildL(newLeafNode);
518 aNodeInserted = newLeafNode;
519 AddOntoLruL(newLeafNode);
523 // Otherwise, move on within this level.
527 // No match case found, add a new node straight on at current level
528 CLeafDirTreeNode* newNode = CLeafDirTreeNode::NewL(this, currentPath, aLeafDirData, CLeafDirTreeNode::ELeaf);
530 if (currentParent->IsLeaf()) // might be the root node
532 currentParent->SetType(CLeafDirTreeNode::ELeafIntermediary);
534 currentParent->MakeItChildL(newNode);
535 aNodeInserted = newNode;
536 AddOntoLruL(newNode);
540 Remove nodes with a specific position from the tree
541 Note: multiple nodes may have the same position value, as directories can be accessed
542 by both long names and short names:
543 E.g.: "\\LongDirName01\\LongDirName02\\LongDirName03\\"
544 "\\LongDirName01\\LongDirName02\\LONGDI~1\\"
545 "\\LongDirName01\\LONGDI~1\\LongDirName03\\"
546 "\\LONGDI~1\\LongDirName02\\LongDirName03\\"
548 @param aDirPos the position of the nodes to be removed
550 void CLeafDirTree::RemoveDirL(const TLeafDirData& aDirPos)
552 // remove alias nodes in cache
553 for (TInt i = iLruList.Count() - 1; i >= 0; i--)
555 if (iLruList[i]->StartClusterNum() == aDirPos.iClusterNum)
557 RemoveFromCacheL(iLruList[i]);
564 Update the MRU entry position of the tree nodes.
565 @param aLeafDirData contains the index of the cache node and the new MRU entry position
567 void CLeafDirTree::UpdateMRUPos(const TLeafDirData& aLeafDirData)
569 // update alias nodes in cache
570 for (TInt i = iLruList.Count() - 1; i >= 0; i--)
572 if (iLruList[i]->StartClusterNum() == aLeafDirData.iClusterNum)
574 iLruList[i]->SetLeafDirData(aLeafDirData);
580 Remove a 'leaf' node, i.e. a leaf node or leaf intermediary node.
582 @param aNodeTodelete the node to be removed
584 void CLeafDirTree::RemoveFromCacheL(CLeafDirTreeNode* aNodeToDelete)
586 ASSERT(aNodeToDelete->IsLeaf() || aNodeToDelete->IsLeafIntermediary());
587 CLeafDirTreeNode* parent = aNodeToDelete->Parent();
588 // Deleting 'leaf intermediary' nodes:
589 if (aNodeToDelete->IsLeafIntermediary())
591 // If there is no child, error! The 'tree' is corrupted.
592 if (aNodeToDelete->Children().Count() == 0)
595 User::Leave(KErrCorrupt);
597 // If there is only one child, 'promote' the child, delete self
598 else if (aNodeToDelete->Children().Count() == 1)
600 CLeafDirTreeNode* child = (aNodeToDelete->Children())[0];
601 TFileName newPath = aNodeToDelete->Path();
602 newPath.Append(child->Path());
603 child->SetPathL(newPath);
604 aNodeToDelete->RemoveChild(child);
605 parent->MakeItChildL(child);
607 parent->RemoveChild(aNodeToDelete);
608 RemoveFromLru(aNodeToDelete);
609 delete aNodeToDelete;
612 // If there are more than one child, just change node type to 'pure intermediary',
613 // but remove self from Lru list.
616 aNodeToDelete->SetType(CLeafDirTreeNode::EPureIntermediary);
617 RemoveFromLru(aNodeToDelete);
621 // Deleting 'leaf' nodes:
624 // If 'parent' is a 'leaf intermediary' node
625 if (parent->IsLeafIntermediary())
627 // If there is no other sibling, change parent's node type to 'leaf',
628 // otherwise, leave parent's type as 'leaf intermediary'
629 if (parent->Children().Count() == 1)
631 parent->SetType(CLeafDirTreeNode::ELeaf);
633 parent->RemoveChild(aNodeToDelete);
634 RemoveFromLru(aNodeToDelete);
635 delete aNodeToDelete;
638 // If 'parent' is 'pure intermediary'
639 else if (parent->IsPureIntermediary())
641 // If there is no sibling nodes, the tree is corrupted,
642 // as 'pure intermediary' node should always have more than one child.
643 if (parent->Children().Count() <= 1)
646 User::Leave(KErrCorrupt);
648 // If there is only one sibling node, we need to merge the sibling node
650 else if (parent->Children().Count() == 2)
652 // Promote the sibling node, delete both parent and self
653 CLeafDirTreeNode* sibling = (parent->Children())[0] ;
654 if (sibling == aNodeToDelete)
656 sibling = (parent->Children())[1];
658 TFileName newPath = aNodeToDelete->Parent()->Path();
659 newPath.Append(sibling->Path());
660 sibling->SetPathL(newPath);
661 parent->RemoveChild(sibling);
662 parent->Parent()->MakeItChildL(sibling);
664 parent->RemoveChild(aNodeToDelete);
665 RemoveFromLru(aNodeToDelete);
666 delete aNodeToDelete;
667 aNodeToDelete = NULL;
669 parent->Parent()->RemoveChild(parent);
673 // Else if there are more than 2 sibling nodes, simply delete self.
676 parent->RemoveChild(aNodeToDelete);
677 RemoveFromLru(aNodeToDelete);
678 delete aNodeToDelete;
679 aNodeToDelete = NULL;
683 // If 'parent' is root node, delete self straightaway
684 else if (aNodeToDelete->Parent()->IsRoot())
686 aNodeToDelete->Parent()->RemoveChild(aNodeToDelete);
687 RemoveFromLru(aNodeToDelete);
688 delete aNodeToDelete;
689 aNodeToDelete = NULL;
692 // If 'parent' is 'leaf', the tree is corrupted.
693 else if (aNodeToDelete->Parent()->IsLeaf())
696 User::Leave(KErrCorrupt);
702 Find the leftest node
703 Note: the leftest node must be a 'leaf' node
705 @param aNodeToStart a node whose children to start with
706 @return the leftest node
708 CLeafDirTreeNode* CLeafDirTree::FindLeftestLeafNode(CLeafDirTreeNode* aNodeToStart) const
710 CLeafDirTreeNode* current = aNodeToStart;
711 while (current->Children().Count() > 0)
713 current = (current->Children())[0];
719 Delete all nodes derived from aNodeToStart, except itself.
721 @param aNodeToStart a node whose children to start with
723 void CLeafDirTree::DeleteSubTreeL(CLeafDirTreeNode* aNodeToStart)
725 while(aNodeToStart->Children().Count() > 0)
727 CLeafDirTreeNode* aLeafNode = FindLeftestLeafNode(aNodeToStart);
728 RemoveFromCacheL(aLeafNode);
733 Make the a node most recent used in LRU list
735 @param aNodeUsed the node to be made MRU
737 TInt CLeafDirTree::MakeMostRecentlyUsed(CLeafDirTreeNode* aNodeUsed)
739 for(TInt i = 0; i < iLruList.Count(); i++)
741 if (aNodeUsed == iLruList[i])
750 iLruList.Insert(aNodeUsed, 0);
759 Check cache limit, remove least-used cached item when necessary.
761 void CLeafDirTree::CheckLimitL()
763 const TInt cacheSize = iSize;
764 while (iLruList.Count() > cacheSize)
766 CLeafDirTreeNode* lruNode = LruNode();
767 RemoveFromCacheL(lruNode);
773 Add new node onto cache list
775 @param aNodeToAdd the new node to be added onto cache list
777 void CLeafDirTree::AddOntoLruL(CLeafDirTreeNode* aNodeToAdd)
779 if (aNodeToAdd == NULL)
782 User::Leave(KErrArgument);
785 TInt r = iLruList.Insert(aNodeToAdd, 0);
789 User::Leave(KErrArgument);
795 Remove a node from cached list.
797 @param aNodeToRemove the node to be removed from the cache list
799 TInt CLeafDirTree::RemoveFromLru(CLeafDirTreeNode* aNodeToRemove)
801 for (TInt i = 0; i < iLruList.Count(); i++)
803 if (aNodeToRemove == iLruList[i])
813 Return the least-recent-used node.
815 @return the least recent used node on cache
817 CLeafDirTreeNode* CLeafDirTree::LruNode()
819 if (iLruList.Count() > 0)
821 return iLruList[iLruList.Count() - 1];
827 Factory function of CLeafDirCache
829 @param aLimit the cache size
831 CLeafDirCache* CLeafDirCache::NewL(TUint32 aLimit)
833 CLeafDirCache* self = new(ELeave) CLeafDirCache(aLimit);
834 CleanupStack::PushL(self);
836 CleanupStack::Pop(self);
841 2nd phase constructor of CLeafDirCache
843 void CLeafDirCache::ConstructL()
845 CLeafDirTree* tree = CLeafDirTree::NewL(iSize);
850 Destructor of CLeafDirCache
852 CLeafDirCache::~CLeafDirCache()
858 Constructor of CLeafDirCache
860 @param aLimit the cache size
862 CLeafDirCache::CLeafDirCache(TUint32 aSize)
868 Reset cache, delete all memory allocated
870 void CLeafDirCache::Reset()
876 Cache interface for searching operations.
878 @param aPath the path of the directory to search for
879 @param aDirPos the location of the direcotry found
880 @return KErrNone if a cached direcotry is found,
881 KErrBadName if the path is incorrect, otherwise
882 other system wide error code
884 TInt CLeafDirCache::FindInCache(const TDesC& aPath, TLeafDirData& aLeafDirData) const
886 if (aPath[0] == '\\')
889 path.Set(aPath.Mid(1));
890 CLeafDirTreeNode* dummy = NULL;
891 return (iTree->Search(path, dummy, aLeafDirData));
900 Cache interface for insertion operations.
902 @param aPath the path of the directory to be added
903 @param aDirPos the location of the direcotry to be added
905 void CLeafDirCache::AddToCacheL(const TDesC& aPath, const TLeafDirData& aDirPos)
907 if (aPath.Length() == 1 && aPath[0] == '\\')
910 CLeafDirTreeNode* dummy = NULL;
911 iTree->InsertL(aPath, aDirPos, dummy);
915 Cache interface for deletion oeprations.
916 Remove all the cached directories with the same specfied position
918 @param aDirPos the location of the direcotry to be removed
920 void CLeafDirCache::RemoveDirL(const TLeafDirData& aDirPos)
922 iTree->RemoveDirL(aDirPos);
926 Update the MRU entry position of the cached leaf dir.
927 @param aLeafDirData contains a cluster number as the index of the leaf dir and the new MRU entry position
929 void CLeafDirCache::UpdateMRUPos(const TLeafDirData& aLeafDirData)
931 iTree->UpdateMRUPos(aLeafDirData);
934 * Helper functions of CLeafDirTree for debugging & testing use
938 All node created will be added to the container of its owner tree, so that we can calculate
939 the number of objects created.
941 @param aNodeToAdd the newly created node to be add to object container
943 void CLeafDirTree::AddToObjectContainerL(CLeafDirTreeNode* aNodeToAdd)
945 iContainer.AppendL(aNodeToAdd);
949 A node is removed from object container if it is deleted.
951 @param aNodeToRemove the node to be deleted
953 void CLeafDirTree::RemoveFromObjectContainerL(CLeafDirTreeNode* aNodeToRemove)
955 for (TInt i = 0; i < iContainer.Count(); i++)
957 if (aNodeToRemove == iContainer[i])
959 iContainer.Remove(i);
964 User::Leave(KErrNotFound);
968 Print out current tree content
970 void CLeafDirTree::DumpTreeContentL() const
972 RPointerArray<CLeafDirTreeNode>* nodeStack = new(ELeave) RPointerArray<CLeafDirTreeNode>(4);
975 const TUint32 debugRegister = DebugRegister();
976 fs.SetDebugRegister(debugRegister|KFSYS);
979 nodeStack->Insert(iRoot, 0);
980 while(nodeStack->Count() > 0)
982 CLeafDirTreeNode* current = (*nodeStack)[0];
983 if (current->Parent() != NULL)
985 __PRINT3(_L("(\"%S\") -> \"%S\" : (%d)\n"), ¤t->Parent()->Path(), ¤t->Path(), current->StartClusterNum());
989 __PRINT2(_L("\"%S\" : (%d)\n"), ¤t->Path(), current->StartClusterNum());
992 nodeStack->Remove(0);
994 TInt currentCount = current->Children().Count();
995 if (currentCount > 0)
997 RPointerArray<CLeafDirTreeNode> children = current->Children();
998 for (TInt i = 0; i < currentCount; i++)
1000 nodeStack->Insert(children[i], 0);
1006 fs.SetDebugRegister(debugRegister);
1013 Print out current cache content
1015 void CLeafDirCache::DumpCacheContentL() const
1017 iTree->DumpTreeContentL();
1021 Count of all the nodes
1023 TInt CLeafDirCache::NodeCount() const
1025 return iTree->ObjectCount();