os/kernelhwsrv/userlibandfileserver/fileserver/sfat32/sl_leafdir_cache.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// f32\sfat\sl_leafdir_cache.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include "sl_std.h"
sl@0
    19
#include "sl_leafdir_cache.h"
sl@0
    20
sl@0
    21
sl@0
    22
sl@0
    23
sl@0
    24
/**
sl@0
    25
Get the lru list count
sl@0
    26
sl@0
    27
@return the count of lru list
sl@0
    28
*/
sl@0
    29
TInt CLeafDirTree::LruCount() const 
sl@0
    30
	{
sl@0
    31
	return iLruList.Count();
sl@0
    32
	}
sl@0
    33
sl@0
    34
/**
sl@0
    35
Count currently cached items
sl@0
    36
sl@0
    37
@return the number of currently cached items
sl@0
    38
*/
sl@0
    39
TInt CLeafDirCache::CacheCount() const 
sl@0
    40
	{
sl@0
    41
	return iTree->LruCount();
sl@0
    42
	}
sl@0
    43
sl@0
    44
//---------------------------------------------------------------------------------------------------------------------------------
sl@0
    45
/**
sl@0
    46
Default constructor of TDirPosition, a data structure that represents a location of directory
sl@0
    47
*/
sl@0
    48
TLeafDirData::TLeafDirData()
sl@0
    49
             :iClusterNum(0),iMRUPos(0,0)
sl@0
    50
	{
sl@0
    51
	}
sl@0
    52
sl@0
    53
/**
sl@0
    54
Constructor of TDirPosition, a data structure that represents a location of directory
sl@0
    55
sl@0
    56
@param  aClusterNum		the cluster number of the directory stores   
sl@0
    57
*/
sl@0
    58
TLeafDirData::TLeafDirData(TUint aClusterNum)
sl@0
    59
             :iClusterNum(aClusterNum),iMRUPos(0,0)
sl@0
    60
	{
sl@0
    61
	}
sl@0
    62
sl@0
    63
/**
sl@0
    64
Constructor of TDirPosition, a data structure that represents a location of directory
sl@0
    65
sl@0
    66
@param  aClusterNum		the cluster number of the directory stores   
sl@0
    67
*/
sl@0
    68
TLeafDirData::TLeafDirData(TUint aClusterNum, const TEntryPos& aMRUPos)
sl@0
    69
             :iClusterNum(aClusterNum),iMRUPos(aMRUPos.Cluster(), aMRUPos.Pos())
sl@0
    70
	{
sl@0
    71
	}
sl@0
    72
sl@0
    73
sl@0
    74
sl@0
    75
/**
sl@0
    76
Factory fucntion of tree nodes
sl@0
    77
sl@0
    78
@param  aOwnerTree	a pointer of the tree that owns this node   
sl@0
    79
@param  aPathName	the directory path this node represents
sl@0
    80
@param  aDirPos		the location of the directory this node represents   
sl@0
    81
@param  aType		the type of the node   
sl@0
    82
*/
sl@0
    83
CLeafDirTreeNode* CLeafDirTreeNode::NewL(CLeafDirTree* aOwnerTree, const TDesC& aPathName, const TLeafDirData& aDirPos, TLeafDirTreeNodeType aType)
sl@0
    84
	{
sl@0
    85
	CLeafDirTreeNode* self = new(ELeave) CLeafDirTreeNode(aDirPos, aType);
sl@0
    86
	CleanupStack::PushL(self);
sl@0
    87
	self->ConstructL(aOwnerTree, aPathName);
sl@0
    88
	CleanupStack::Pop();
sl@0
    89
	return self;
sl@0
    90
	}
sl@0
    91
sl@0
    92
/**
sl@0
    93
Constructor of tree nodes
sl@0
    94
sl@0
    95
@param  aDirPos		the location of the directory this node represents   
sl@0
    96
@param  aType		the type of the node   
sl@0
    97
*/
sl@0
    98
CLeafDirTreeNode::CLeafDirTreeNode(const TLeafDirData& aDirPos, TLeafDirTreeNodeType aType)
sl@0
    99
                  :iParent(NULL), iLeafDirData(aDirPos), iNodeType(aType)
sl@0
   100
	{
sl@0
   101
	}
sl@0
   102
sl@0
   103
/**
sl@0
   104
2nd phase constructor of tree nodes
sl@0
   105
sl@0
   106
@param  aOwnerTree	a pointer of the tree that owns this node   
sl@0
   107
@param  aPathName	the directory path this node represents
sl@0
   108
*/
sl@0
   109
void CLeafDirTreeNode::ConstructL(CLeafDirTree* aOwnerTree, const TDesC& aPath)
sl@0
   110
	{
sl@0
   111
	if (aOwnerTree == NULL)
sl@0
   112
		{
sl@0
   113
		ASSERT(0);
sl@0
   114
		User::Leave(KErrArgument);
sl@0
   115
		}
sl@0
   116
	iOwnerTree = aOwnerTree;
sl@0
   117
	iPath.CreateL(aPath);
sl@0
   118
#ifdef _DEBUG
sl@0
   119
	iOwnerTree->AddToObjectContainerL(this);
sl@0
   120
#endif //_DEBUG
sl@0
   121
	}
sl@0
   122
sl@0
   123
/**
sl@0
   124
Destructor of tree nodes
sl@0
   125
sl@0
   126
@pre	The node should already be removed from its parent before being deleted
sl@0
   127
*/
sl@0
   128
CLeafDirTreeNode::~CLeafDirTreeNode()
sl@0
   129
	{
sl@0
   130
#ifdef _DEBUG
sl@0
   131
	TRAPD(err, iOwnerTree->RemoveFromObjectContainerL(this));
sl@0
   132
	ASSERT(err == KErrNone);
sl@0
   133
#endif // _DEBUG
sl@0
   134
	iPath.Close();
sl@0
   135
	iChildren.Close();
sl@0
   136
	}
sl@0
   137
sl@0
   138
/**
sl@0
   139
Set type of the node
sl@0
   140
sl@0
   141
@param  aType	the type to be set
sl@0
   142
*/
sl@0
   143
void CLeafDirTreeNode::SetType(const CLeafDirTreeNode::TLeafDirTreeNodeType aType)
sl@0
   144
	{
sl@0
   145
	// Root node can not be reset type
sl@0
   146
	if (iNodeType == CLeafDirTreeNode::ERoot)
sl@0
   147
		return;
sl@0
   148
	iNodeType = aType;
sl@0
   149
	}
sl@0
   150
sl@0
   151
/**
sl@0
   152
Set path of the directory the node represents
sl@0
   153
sl@0
   154
@param  aPath	the path to be set   
sl@0
   155
*/
sl@0
   156
void CLeafDirTreeNode::SetPathL(const TDesC& aPath)
sl@0
   157
	{
sl@0
   158
	ASSERT(aPath.Length() > 0);
sl@0
   159
	if (iPath.Length() < aPath.Length())
sl@0
   160
		{
sl@0
   161
		TInt err = iPath.ReAlloc(aPath.Length());
sl@0
   162
		ASSERT(err==KErrNone);
sl@0
   163
		User::LeaveIfError(err);
sl@0
   164
		}
sl@0
   165
    iPath = aPath;
sl@0
   166
	}
sl@0
   167
sl@0
   168
/**
sl@0
   169
Removes from the children list, sets aNode's parent NULL, does not delete aNode
sl@0
   170
sl@0
   171
@param  aNode	the node to be removed   
sl@0
   172
*/
sl@0
   173
TInt CLeafDirTreeNode::RemoveChild(CLeafDirTreeNode* aNode)
sl@0
   174
	{
sl@0
   175
	ASSERT(aNode);
sl@0
   176
	if (aNode->IsRoot())
sl@0
   177
		{
sl@0
   178
		ASSERT(0);
sl@0
   179
		return KErrArgument;
sl@0
   180
		}
sl@0
   181
	
sl@0
   182
	if (iChildren.Count() > 0)
sl@0
   183
		{
sl@0
   184
		for (TInt i = iChildren.Count() - 1; i >= 0; i--)
sl@0
   185
			{
sl@0
   186
			if (iChildren[i] == aNode)
sl@0
   187
				{
sl@0
   188
				iChildren.Remove(i);
sl@0
   189
				aNode->SetParent(NULL);
sl@0
   190
				return KErrNone;
sl@0
   191
				}
sl@0
   192
			}
sl@0
   193
		}
sl@0
   194
	return KErrNotFound;
sl@0
   195
	}
sl@0
   196
sl@0
   197
/**
sl@0
   198
Add a new child node to self
sl@0
   199
sl@0
   200
@pre	aNode should have been removed from its original parent
sl@0
   201
@param  aNode	the node to be added   
sl@0
   202
*/
sl@0
   203
void CLeafDirTreeNode::MakeItChildL(CLeafDirTreeNode* aNode)
sl@0
   204
	{
sl@0
   205
	ASSERT(aNode->Parent() == NULL);
sl@0
   206
	if (aNode->IsRoot())
sl@0
   207
		{
sl@0
   208
		ASSERT(0);
sl@0
   209
		User::Leave(KErrArgument);
sl@0
   210
		}
sl@0
   211
	iChildren.AppendL(aNode);
sl@0
   212
	aNode->SetParent(this);
sl@0
   213
	}
sl@0
   214
sl@0
   215
sl@0
   216
/**
sl@0
   217
Factory function of CLeafDirTree
sl@0
   218
sl@0
   219
@param  aLimit	the maximum number of 'leaf' nodes allowed of the tree   
sl@0
   220
*/
sl@0
   221
CLeafDirTree* CLeafDirTree::NewL(TUint32 aSize)
sl@0
   222
	{
sl@0
   223
	CLeafDirTree* self = new(ELeave) CLeafDirTree(aSize);
sl@0
   224
	CleanupStack::PushL(self);
sl@0
   225
	self->ConstructL();
sl@0
   226
	CleanupStack::Pop();
sl@0
   227
	return self;
sl@0
   228
	}
sl@0
   229
sl@0
   230
/**
sl@0
   231
Constructor of CLeafDirTree
sl@0
   232
sl@0
   233
@param  aLimit	the maximum number of 'leaf' nodes allowed of the tree   
sl@0
   234
*/
sl@0
   235
CLeafDirTree::CLeafDirTree(TUint32 aSize)
sl@0
   236
:iSize(aSize)
sl@0
   237
	{
sl@0
   238
	}
sl@0
   239
sl@0
   240
_LIT(KRootDirPath, "\\");
sl@0
   241
/**
sl@0
   242
2nd phase constructor of CLeafDirTree
sl@0
   243
*/
sl@0
   244
void CLeafDirTree::ConstructL()
sl@0
   245
	{
sl@0
   246
	TLeafDirData rootDirPos(0);
sl@0
   247
	CLeafDirTreeNode* root = CLeafDirTreeNode::NewL(this, KRootDirPath, rootDirPos, CLeafDirTreeNode::ERoot);
sl@0
   248
	iRoot = root;
sl@0
   249
	iRoot->SetType(CLeafDirTreeNode::ERoot);
sl@0
   250
	}
sl@0
   251
sl@0
   252
/**
sl@0
   253
Destructor of CLeafDirTree
sl@0
   254
*/
sl@0
   255
CLeafDirTree::~CLeafDirTree()
sl@0
   256
	{
sl@0
   257
	Reset();
sl@0
   258
	delete iRoot;
sl@0
   259
	iLruList.Close();
sl@0
   260
sl@0
   261
#ifdef _DEBUG
sl@0
   262
	iContainer.Close();
sl@0
   263
#endif //_DEBUG
sl@0
   264
	}
sl@0
   265
sl@0
   266
/**
sl@0
   267
Free all the nodes from the tree except root node
sl@0
   268
*/
sl@0
   269
void CLeafDirTree::Reset()
sl@0
   270
	{
sl@0
   271
	TInt err = KErrNone;
sl@0
   272
	TRAP(err, DeleteSubTreeL(iRoot));
sl@0
   273
	ASSERT(err == KErrNone);
sl@0
   274
	}
sl@0
   275
sl@0
   276
/**
sl@0
   277
Search for a node by directory path
sl@0
   278
sl@0
   279
@param	aPath		the path as the key to search in the tree
sl@0
   280
@param	aNodeFound	in return, the node found 
sl@0
   281
@param	aDirPos		the location of the directory
sl@0
   282
@return	KErrNone 	if a node found
sl@0
   283
		KErrNotFound if no node is found
sl@0
   284
*/
sl@0
   285
TInt CLeafDirTree::Search(const TDesC& aPath, CLeafDirTreeNode*& aNodeFound, TLeafDirData& aDirPos)
sl@0
   286
	{
sl@0
   287
	return (DoSearch(aPath, iRoot, aNodeFound, aDirPos));
sl@0
   288
	}
sl@0
   289
sl@0
   290
/**
sl@0
   291
Search for a node by directory path, start from children of aNodeToStart but do not include aNodeToStart.
sl@0
   292
sl@0
   293
@param	aPath			the path as the key to search in the tree
sl@0
   294
@param	aNodeToStart	the node whose children to start with 
sl@0
   295
@param	aNodeFound		in return, the node found 
sl@0
   296
@param	aDirPos			the location of the directory
sl@0
   297
@return	KErrNone 		if a node found
sl@0
   298
		KErrNotFound 	if no node is found
sl@0
   299
*/
sl@0
   300
TInt CLeafDirTree::DoSearch(const TDesC& aPath, CLeafDirTreeNode* aNodeToStart, CLeafDirTreeNode*& aNodeFound, TLeafDirData& aLeafDirData)
sl@0
   301
	{
sl@0
   302
	RPointerArray<CLeafDirTreeNode> currentLevel = aNodeToStart->Children();
sl@0
   303
	TInt currentPos = currentLevel.Count() - 1;
sl@0
   304
	// Current path in search
sl@0
   305
	TPtrC currentPath;
sl@0
   306
	currentPath.Set(aPath);
sl@0
   307
	while (currentLevel.Count() > 0 && currentPos >= 0)
sl@0
   308
		{
sl@0
   309
		CLeafDirTreeNode* currentNode = currentLevel[currentPos];
sl@0
   310
		TPtrC currentNodePath;
sl@0
   311
		currentNodePath.Set(currentNode->Path());
sl@0
   312
		TInt foundPos = currentPath.FindF(currentNodePath);
sl@0
   313
		// If current child's path is part of the searching path, 
sl@0
   314
		// 	go to next level
sl@0
   315
		// 	E.g.: current child's path = "1\2\3\", searching path = "1\2\3\5\".
sl@0
   316
		if (foundPos == 0 && currentNodePath.Length() < currentPath.Length())
sl@0
   317
			{
sl@0
   318
			currentPath.Set(currentPath.Mid(currentNodePath.Length()));
sl@0
   319
			currentLevel = currentNode->Children();
sl@0
   320
			currentPos = currentLevel.Count() - 1;
sl@0
   321
			continue;
sl@0
   322
			}
sl@0
   323
		// If current child's path matches current searching path,
sl@0
   324
		// 	check the node type.
sl@0
   325
		else if (foundPos == 0 && currentNodePath.Length() == currentPath.Length())
sl@0
   326
			{
sl@0
   327
			if (currentNode->IsPureIntermediary())
sl@0
   328
			// If found is 'pure intermediary', it is not cached. 
sl@0
   329
				{
sl@0
   330
				return KErrNotFound;
sl@0
   331
				}
sl@0
   332
			// Otherwise, we have got a cache hit!
sl@0
   333
			MakeMostRecentlyUsed(currentNode);
sl@0
   334
			aNodeFound = currentNode;
sl@0
   335
			aLeafDirData = currentNode->LeafDirData();
sl@0
   336
			return KErrNone;
sl@0
   337
			}
sl@0
   338
		// else, go through current level
sl@0
   339
		currentPos--;
sl@0
   340
		}
sl@0
   341
	// If there is no child or we have not found any matching node,
sl@0
   342
	//	return KErrNotFound
sl@0
   343
	return KErrNotFound;
sl@0
   344
	}
sl@0
   345
sl@0
   346
/**
sl@0
   347
Find the longest common 'path' between two paths.
sl@0
   348
Note: not the longest common 'string'.
sl@0
   349
sl@0
   350
@param	aPathA	path A
sl@0
   351
@param	aPathB	path B 
sl@0
   352
@return		the length of the longest common path found
sl@0
   353
			KErrNotFound 	if no node is found
sl@0
   354
*/
sl@0
   355
TInt FindLongestCommonPath(const TDesC& aPathA, const TDesC& aPathB)
sl@0
   356
	{
sl@0
   357
	const TInt compareLength = Min(aPathA.Length(), aPathB.Length());
sl@0
   358
	if (compareLength <= 0)
sl@0
   359
		{
sl@0
   360
		return KErrArgument;
sl@0
   361
		}
sl@0
   362
	TInt i = 0;
sl@0
   363
	TInt lastPathDelimiterPos = KErrNotFound;
sl@0
   364
	while (i < compareLength && aPathA[i] == aPathB[i])
sl@0
   365
		{
sl@0
   366
		if (aPathA[i] == '\\')
sl@0
   367
			{
sl@0
   368
			lastPathDelimiterPos = i;
sl@0
   369
			}
sl@0
   370
		i++;
sl@0
   371
		}
sl@0
   372
	
sl@0
   373
	if (i == 0)
sl@0
   374
		{
sl@0
   375
		return KErrNotFound;
sl@0
   376
		}
sl@0
   377
	return lastPathDelimiterPos;
sl@0
   378
	}
sl@0
   379
sl@0
   380
/**
sl@0
   381
Insert a new node to the tree according to the path 
sl@0
   382
sl@0
   383
@param	aPath			the path of the new node to be inserted
sl@0
   384
@param	aDirPos 		the position of the new node to be inserted
sl@0
   385
@param	aNodeInserted 	in return, the node that has been successfully inserted
sl@0
   386
*/
sl@0
   387
void CLeafDirTree::InsertL(const TDesC& aPath, const TLeafDirData& aLeafDirData, CLeafDirTreeNode*& aNodeInserted)
sl@0
   388
	{
sl@0
   389
	ASSERT(aPath.Length() > 0);
sl@0
   390
	// aPath should always start and end with a '\\'.
sl@0
   391
	if (aPath[0] == '\\' && aPath[aPath.Length() - 1] =='\\')
sl@0
   392
		{
sl@0
   393
		if (aPath.Length() > 1)
sl@0
   394
			{
sl@0
   395
			TPtrC path;
sl@0
   396
			path.Set(aPath.Mid(1));
sl@0
   397
			DoInsertL(iRoot, path, aLeafDirData, aNodeInserted);
sl@0
   398
			}
sl@0
   399
		}
sl@0
   400
	else
sl@0
   401
		{
sl@0
   402
		ASSERT(0);
sl@0
   403
		User::Leave(KErrBadName);
sl@0
   404
		}
sl@0
   405
	}
sl@0
   406
sl@0
   407
/**
sl@0
   408
Implementation of the insertion algorithm 
sl@0
   409
sl@0
   410
@param	aNodeToStart	the node whose children to start with
sl@0
   411
@param	aPath			the path of the new node to be inserted
sl@0
   412
@param	aDirPos 		the position of the new node to be inserted
sl@0
   413
@param	aNodeInserted 	in return, the node that has been successfully inserted
sl@0
   414
*/
sl@0
   415
void CLeafDirTree::DoInsertL(CLeafDirTreeNode* aNodeToStart, const TDesC& aPath, const TLeafDirData& aLeafDirData, CLeafDirTreeNode*& aNodeInserted)
sl@0
   416
	{
sl@0
   417
	CLeafDirTreeNode* currentParent = aNodeToStart;
sl@0
   418
	TInt foundPos = 0;
sl@0
   419
	RPointerArray<CLeafDirTreeNode> currentLevel = aNodeToStart->Children();
sl@0
   420
	TInt currentPos = currentLevel.Count() - 1;
sl@0
   421
	TPtrC currentPath;
sl@0
   422
	currentPath.Set(aPath);
sl@0
   423
	while (currentLevel.Count() > 0 && currentPos >= 0)
sl@0
   424
		{
sl@0
   425
		CLeafDirTreeNode* currentNode = currentLevel[currentPos];
sl@0
   426
		TPtrC currentNodePath;
sl@0
   427
		currentNodePath.Set(currentNode->Path());
sl@0
   428
sl@0
   429
		// If current node is contained by aPath.
sl@0
   430
		// 	E.g.: current node = "1\2\3\", currentPath = "1\2\3\5\"
sl@0
   431
		//	In this case, we need to go to next level,
sl@0
   432
		//	discard logged position (currentPos) in this level as we don't need to come back.
sl@0
   433
		foundPos = currentPath.FindF(currentNodePath);
sl@0
   434
		if (foundPos == 0 && currentNodePath.Length() < currentPath.Length())
sl@0
   435
			{
sl@0
   436
			currentParent = currentNode;
sl@0
   437
			currentLevel = currentNode->Children();
sl@0
   438
			currentPos = currentLevel.Count() - 1;
sl@0
   439
			currentPath.Set(currentPath.Mid(currentNodePath.Length()));
sl@0
   440
			continue;
sl@0
   441
			}
sl@0
   442
sl@0
   443
		// If current node's path contains aPath 
sl@0
   444
		// 	E.g.: current node = "1\2\3\4\", currentPath = "1\2\3\"
sl@0
   445
		//	We need to split current node to two nodes and return.
sl@0
   446
		foundPos = currentNodePath.FindF(currentPath);
sl@0
   447
		if (foundPos == 0 && currentNodePath.Length() > currentPath.Length())
sl@0
   448
			{
sl@0
   449
			CLeafDirTreeNode* newNode = CLeafDirTreeNode::NewL(this, currentPath, aLeafDirData, CLeafDirTreeNode::ELeafIntermediary);
sl@0
   450
			currentParent->MakeItChildL(newNode);
sl@0
   451
			
sl@0
   452
			TPtrC restPath;
sl@0
   453
			restPath.Set(currentNodePath.Mid(currentPath.Length()));
sl@0
   454
			currentNode->SetPathL(restPath);
sl@0
   455
			currentParent->RemoveChild(currentNode);
sl@0
   456
			
sl@0
   457
			newNode->MakeItChildL(currentNode);
sl@0
   458
			AddOntoLruL(newNode);
sl@0
   459
			aNodeInserted = newNode;
sl@0
   460
			return;
sl@0
   461
			}
sl@0
   462
sl@0
   463
		// If current node's path equals aPath,
sl@0
   464
		//	change the node type if it is necessary
sl@0
   465
		if (foundPos == 0 && currentNodePath.Length() == currentPath.Length())
sl@0
   466
			{
sl@0
   467
			// Check node type, if already cached, update Lru list and return.
sl@0
   468
			if (currentNode->IsLeaf() || currentNode->IsLeafIntermediary())
sl@0
   469
				{
sl@0
   470
				currentNode->SetLeafDirData(aLeafDirData);
sl@0
   471
				aNodeInserted = currentNode;
sl@0
   472
				MakeMostRecentlyUsed(currentNode);
sl@0
   473
				return;
sl@0
   474
				}
sl@0
   475
			// If it has not been cached yet, i.e., it is a 'pure intermediary' node,
sl@0
   476
			//	cache the node and put it onto Lru list
sl@0
   477
			else if(currentNode->IsPureIntermediary())
sl@0
   478
				{
sl@0
   479
				currentNode->SetLeafDirData(aLeafDirData);
sl@0
   480
				currentNode->SetType(CLeafDirTreeNode::ELeafIntermediary);
sl@0
   481
				AddOntoLruL(currentNode);
sl@0
   482
				aNodeInserted = currentNode;
sl@0
   483
				return;
sl@0
   484
				}
sl@0
   485
			}
sl@0
   486
		
sl@0
   487
		// If none of above is the case (i.e. haven't found exact match or paths 
sl@0
   488
		//	are not contained by each other), we need to find the first common part 
sl@0
   489
		//	between each child and aPath to share path data.
sl@0
   490
		foundPos = FindLongestCommonPath(currentNodePath, currentPath);
sl@0
   491
		// If a common part of path is found, we need to create a pure intermediary node to share
sl@0
   492
		//	the common part of path data, and create a new leaf node for the target path.
sl@0
   493
		if (foundPos > 0)
sl@0
   494
			{
sl@0
   495
			TPtrC commonPath;
sl@0
   496
			commonPath.Set(currentNodePath.Left(foundPos + 1));
sl@0
   497
sl@0
   498
			currentNodePath.Set(currentNodePath.Mid(foundPos + 1));
sl@0
   499
			TPtrC newLeafPath;
sl@0
   500
			newLeafPath.Set(currentPath.Mid(foundPos + 1));
sl@0
   501
sl@0
   502
			// Add new pureintermediary node, set it as child of current parent
sl@0
   503
			TLeafDirData dummyPos(0);
sl@0
   504
			CLeafDirTreeNode* newPureIntermediaryNode = CLeafDirTreeNode::NewL(this, commonPath, dummyPos, CLeafDirTreeNode::EPureIntermediary);
sl@0
   505
			currentParent->MakeItChildL(newPureIntermediaryNode);
sl@0
   506
sl@0
   507
			// Remove current child from aNodeToStart, do not need to change
sl@0
   508
			//	node type of aNodeToStart
sl@0
   509
			currentParent->RemoveChild(currentNode);
sl@0
   510
sl@0
   511
			// Modify current pathData, make it child of new node
sl@0
   512
			newPureIntermediaryNode->MakeItChildL(currentNode);
sl@0
   513
			currentNode->SetPathL(currentNodePath);
sl@0
   514
sl@0
   515
			// Add new leaf node as a child of the new pure intermediary node
sl@0
   516
			CLeafDirTreeNode* newLeafNode = CLeafDirTreeNode::NewL(this, newLeafPath, aLeafDirData, CLeafDirTreeNode::ELeaf);
sl@0
   517
			newPureIntermediaryNode->MakeItChildL(newLeafNode);
sl@0
   518
			aNodeInserted = newLeafNode;
sl@0
   519
			AddOntoLruL(newLeafNode);
sl@0
   520
			return;
sl@0
   521
			}
sl@0
   522
sl@0
   523
		// Otherwise, move on within this level.
sl@0
   524
		currentPos--;
sl@0
   525
		}
sl@0
   526
	
sl@0
   527
	// No match case found, add a new node straight on at current level
sl@0
   528
	CLeafDirTreeNode* newNode = CLeafDirTreeNode::NewL(this, currentPath, aLeafDirData, CLeafDirTreeNode::ELeaf);
sl@0
   529
sl@0
   530
	if (currentParent->IsLeaf())		// might be the root node
sl@0
   531
		{
sl@0
   532
		currentParent->SetType(CLeafDirTreeNode::ELeafIntermediary);
sl@0
   533
		}
sl@0
   534
	currentParent->MakeItChildL(newNode);
sl@0
   535
	aNodeInserted = newNode;
sl@0
   536
	AddOntoLruL(newNode);
sl@0
   537
	}
sl@0
   538
sl@0
   539
/**
sl@0
   540
Remove nodes with a specific position from the tree  
sl@0
   541
Note: multiple nodes may have the same position value, as directories can be accessed
sl@0
   542
	by both long names and short names:
sl@0
   543
E.g.: 	"\\LongDirName01\\LongDirName02\\LongDirName03\\"
sl@0
   544
		"\\LongDirName01\\LongDirName02\\LONGDI~1\\"
sl@0
   545
		"\\LongDirName01\\LONGDI~1\\LongDirName03\\"
sl@0
   546
		"\\LONGDI~1\\LongDirName02\\LongDirName03\\"
sl@0
   547
sl@0
   548
@param	aDirPos 	the position of the nodes to be removed
sl@0
   549
*/
sl@0
   550
void CLeafDirTree::RemoveDirL(const TLeafDirData& aDirPos)
sl@0
   551
	{
sl@0
   552
	// remove alias nodes in cache
sl@0
   553
	for (TInt i = iLruList.Count() - 1; i >= 0; i--)
sl@0
   554
		{
sl@0
   555
		if (iLruList[i]->StartClusterNum() == aDirPos.iClusterNum)
sl@0
   556
			{
sl@0
   557
			RemoveFromCacheL(iLruList[i]);
sl@0
   558
			}
sl@0
   559
		}
sl@0
   560
	}
sl@0
   561
sl@0
   562
sl@0
   563
/**
sl@0
   564
Update the MRU entry position of the tree nodes.
sl@0
   565
@param	aLeafDirData	contains the index of the cache node and the new MRU entry position 
sl@0
   566
*/
sl@0
   567
void CLeafDirTree::UpdateMRUPos(const TLeafDirData& aLeafDirData)
sl@0
   568
	{
sl@0
   569
	// update alias nodes in cache
sl@0
   570
	for (TInt i = iLruList.Count() - 1; i >= 0; i--)
sl@0
   571
		{
sl@0
   572
		if (iLruList[i]->StartClusterNum() == aLeafDirData.iClusterNum)
sl@0
   573
			{
sl@0
   574
			iLruList[i]->SetLeafDirData(aLeafDirData);
sl@0
   575
			}
sl@0
   576
		}
sl@0
   577
	}
sl@0
   578
sl@0
   579
/**
sl@0
   580
Remove a 'leaf' node, i.e. a leaf node or leaf intermediary node.
sl@0
   581
sl@0
   582
@param	aNodeTodelete the node to be removed
sl@0
   583
*/
sl@0
   584
void CLeafDirTree::RemoveFromCacheL(CLeafDirTreeNode* aNodeToDelete)
sl@0
   585
	{
sl@0
   586
	ASSERT(aNodeToDelete->IsLeaf() || aNodeToDelete->IsLeafIntermediary());
sl@0
   587
	CLeafDirTreeNode* parent = aNodeToDelete->Parent(); 
sl@0
   588
	// Deleting 'leaf intermediary' nodes:
sl@0
   589
	if (aNodeToDelete->IsLeafIntermediary())
sl@0
   590
		{
sl@0
   591
		// If there is no child, error! The 'tree' is corrupted.
sl@0
   592
		if (aNodeToDelete->Children().Count() == 0)
sl@0
   593
			{
sl@0
   594
			ASSERT(0);
sl@0
   595
			User::Leave(KErrCorrupt);
sl@0
   596
			}
sl@0
   597
		// If there is only one child, 'promote' the child, delete self
sl@0
   598
		else if (aNodeToDelete->Children().Count() == 1)
sl@0
   599
			{
sl@0
   600
			CLeafDirTreeNode* child = (aNodeToDelete->Children())[0];
sl@0
   601
			TFileName newPath = aNodeToDelete->Path();
sl@0
   602
			newPath.Append(child->Path());
sl@0
   603
			child->SetPathL(newPath);
sl@0
   604
			aNodeToDelete->RemoveChild(child);
sl@0
   605
			parent->MakeItChildL(child);
sl@0
   606
sl@0
   607
			parent->RemoveChild(aNodeToDelete);
sl@0
   608
			RemoveFromLru(aNodeToDelete);
sl@0
   609
			delete aNodeToDelete;
sl@0
   610
			return;
sl@0
   611
			}
sl@0
   612
		// If there are more than one child, just change node type to 'pure intermediary',
sl@0
   613
		//	but remove self from Lru list.
sl@0
   614
		else
sl@0
   615
			{
sl@0
   616
			aNodeToDelete->SetType(CLeafDirTreeNode::EPureIntermediary);
sl@0
   617
			RemoveFromLru(aNodeToDelete);
sl@0
   618
			return;
sl@0
   619
			}
sl@0
   620
		}
sl@0
   621
	// Deleting 'leaf' nodes:
sl@0
   622
	else
sl@0
   623
		{
sl@0
   624
		// If 'parent' is a 'leaf intermediary' node
sl@0
   625
		if (parent->IsLeafIntermediary())
sl@0
   626
			{
sl@0
   627
			// If there is no other sibling, change parent's node type to 'leaf',
sl@0
   628
			//  otherwise, leave parent's type as 'leaf intermediary' 
sl@0
   629
			if (parent->Children().Count() == 1)
sl@0
   630
				{
sl@0
   631
				parent->SetType(CLeafDirTreeNode::ELeaf);
sl@0
   632
				}
sl@0
   633
			parent->RemoveChild(aNodeToDelete);
sl@0
   634
			RemoveFromLru(aNodeToDelete);
sl@0
   635
			delete aNodeToDelete;
sl@0
   636
			return;
sl@0
   637
			}
sl@0
   638
		// If 'parent' is 'pure intermediary'
sl@0
   639
		else if (parent->IsPureIntermediary())
sl@0
   640
			{
sl@0
   641
			// If there is no sibling nodes, the tree is corrupted,
sl@0
   642
			//	as 'pure intermediary' node should always have more than one child.
sl@0
   643
			if (parent->Children().Count() <= 1)
sl@0
   644
				{
sl@0
   645
				ASSERT(0);
sl@0
   646
				User::Leave(KErrCorrupt);
sl@0
   647
				}
sl@0
   648
			// If there is only one sibling node, we need to merge the sibling node
sl@0
   649
			//	to 'parent'.
sl@0
   650
			else if (parent->Children().Count() == 2)
sl@0
   651
				{
sl@0
   652
				// Promote the sibling node, delete both parent and self
sl@0
   653
				CLeafDirTreeNode* sibling = (parent->Children())[0] ;
sl@0
   654
				if (sibling == aNodeToDelete)
sl@0
   655
					{
sl@0
   656
					sibling = (parent->Children())[1];
sl@0
   657
					}
sl@0
   658
				TFileName newPath = aNodeToDelete->Parent()->Path();
sl@0
   659
				newPath.Append(sibling->Path());
sl@0
   660
				sibling->SetPathL(newPath);
sl@0
   661
				parent->RemoveChild(sibling);
sl@0
   662
				parent->Parent()->MakeItChildL(sibling);
sl@0
   663
				
sl@0
   664
				parent->RemoveChild(aNodeToDelete);
sl@0
   665
				RemoveFromLru(aNodeToDelete);
sl@0
   666
				delete aNodeToDelete;
sl@0
   667
				aNodeToDelete = NULL;
sl@0
   668
sl@0
   669
				parent->Parent()->RemoveChild(parent);
sl@0
   670
				delete parent;
sl@0
   671
				return;
sl@0
   672
				}
sl@0
   673
			// Else if there are more than 2 sibling nodes, simply delete self.
sl@0
   674
			else
sl@0
   675
				{
sl@0
   676
				parent->RemoveChild(aNodeToDelete);
sl@0
   677
				RemoveFromLru(aNodeToDelete);
sl@0
   678
				delete aNodeToDelete;
sl@0
   679
				aNodeToDelete = NULL;
sl@0
   680
				return;
sl@0
   681
				}
sl@0
   682
			}
sl@0
   683
		// If 'parent' is root node, delete self straightaway
sl@0
   684
		else if (aNodeToDelete->Parent()->IsRoot())
sl@0
   685
			{
sl@0
   686
			aNodeToDelete->Parent()->RemoveChild(aNodeToDelete);
sl@0
   687
			RemoveFromLru(aNodeToDelete);
sl@0
   688
			delete aNodeToDelete;
sl@0
   689
			aNodeToDelete = NULL;
sl@0
   690
			return;
sl@0
   691
			}
sl@0
   692
		// If 'parent' is 'leaf', the tree is corrupted. 
sl@0
   693
		else if (aNodeToDelete->Parent()->IsLeaf())
sl@0
   694
			{
sl@0
   695
			ASSERT(0);
sl@0
   696
			User::Leave(KErrCorrupt);
sl@0
   697
			}
sl@0
   698
		}
sl@0
   699
	}
sl@0
   700
sl@0
   701
/**
sl@0
   702
Find the leftest node
sl@0
   703
Note: the leftest node must be a 'leaf' node
sl@0
   704
sl@0
   705
@param	aNodeToStart	a node whose children to start with
sl@0
   706
@return the leftest node
sl@0
   707
*/
sl@0
   708
CLeafDirTreeNode* CLeafDirTree::FindLeftestLeafNode(CLeafDirTreeNode* aNodeToStart) const
sl@0
   709
	{
sl@0
   710
	CLeafDirTreeNode* current = aNodeToStart;
sl@0
   711
	while (current->Children().Count() > 0)
sl@0
   712
		{
sl@0
   713
		current = (current->Children())[0];
sl@0
   714
		}
sl@0
   715
	return current;
sl@0
   716
	}
sl@0
   717
sl@0
   718
/**
sl@0
   719
Delete all nodes derived from aNodeToStart, except itself.
sl@0
   720
sl@0
   721
@param	aNodeToStart	a node whose children to start with
sl@0
   722
*/
sl@0
   723
void CLeafDirTree::DeleteSubTreeL(CLeafDirTreeNode* aNodeToStart)
sl@0
   724
	{
sl@0
   725
	while(aNodeToStart->Children().Count() > 0)
sl@0
   726
		{
sl@0
   727
		CLeafDirTreeNode* aLeafNode = FindLeftestLeafNode(aNodeToStart);
sl@0
   728
		RemoveFromCacheL(aLeafNode);
sl@0
   729
		}
sl@0
   730
	}
sl@0
   731
sl@0
   732
/**
sl@0
   733
Make the a node most recent used in LRU list
sl@0
   734
sl@0
   735
@param	aNodeUsed	the node to be made MRU
sl@0
   736
*/
sl@0
   737
TInt CLeafDirTree::MakeMostRecentlyUsed(CLeafDirTreeNode* aNodeUsed)
sl@0
   738
	{
sl@0
   739
	for(TInt i = 0; i < iLruList.Count(); i++)
sl@0
   740
		{
sl@0
   741
		if (aNodeUsed == iLruList[i])
sl@0
   742
			{
sl@0
   743
			if (i == 0)
sl@0
   744
				{
sl@0
   745
				return KErrNone;
sl@0
   746
				}
sl@0
   747
			else
sl@0
   748
				{
sl@0
   749
				iLruList.Remove(i);
sl@0
   750
				iLruList.Insert(aNodeUsed, 0);
sl@0
   751
				return KErrNone;
sl@0
   752
				}
sl@0
   753
			}
sl@0
   754
		}
sl@0
   755
	return KErrNotFound;
sl@0
   756
	}
sl@0
   757
sl@0
   758
/**
sl@0
   759
Check cache limit, remove least-used cached item when necessary.
sl@0
   760
*/
sl@0
   761
void CLeafDirTree::CheckLimitL()
sl@0
   762
	{
sl@0
   763
	const TInt cacheSize = iSize;
sl@0
   764
	while (iLruList.Count() > cacheSize)
sl@0
   765
		{
sl@0
   766
		CLeafDirTreeNode* lruNode = LruNode();
sl@0
   767
		RemoveFromCacheL(lruNode);
sl@0
   768
		}
sl@0
   769
	return;
sl@0
   770
	}
sl@0
   771
sl@0
   772
/**
sl@0
   773
Add new node onto cache list
sl@0
   774
sl@0
   775
@param	aNodeToAdd	the new node to be added onto cache list
sl@0
   776
*/
sl@0
   777
void CLeafDirTree::AddOntoLruL(CLeafDirTreeNode* aNodeToAdd)
sl@0
   778
	{
sl@0
   779
	if (aNodeToAdd == NULL)
sl@0
   780
		{
sl@0
   781
		ASSERT(0);
sl@0
   782
		User::Leave(KErrArgument);
sl@0
   783
		}
sl@0
   784
	
sl@0
   785
	TInt r = iLruList.Insert(aNodeToAdd, 0);
sl@0
   786
	if (r != KErrNone)
sl@0
   787
		{
sl@0
   788
		ASSERT(0);
sl@0
   789
		User::Leave(KErrArgument);
sl@0
   790
		}
sl@0
   791
	CheckLimitL();
sl@0
   792
	}
sl@0
   793
sl@0
   794
/**
sl@0
   795
Remove a node from cached list.
sl@0
   796
sl@0
   797
@param	aNodeToRemove	the node to be removed from the cache list
sl@0
   798
*/
sl@0
   799
TInt CLeafDirTree::RemoveFromLru(CLeafDirTreeNode* aNodeToRemove)
sl@0
   800
	{
sl@0
   801
	for (TInt i = 0; i < iLruList.Count(); i++)
sl@0
   802
		{
sl@0
   803
		if (aNodeToRemove == iLruList[i])
sl@0
   804
			{
sl@0
   805
			iLruList.Remove(i);
sl@0
   806
			return KErrNone;
sl@0
   807
			}
sl@0
   808
		}
sl@0
   809
	return KErrNotFound;
sl@0
   810
	}
sl@0
   811
sl@0
   812
/**
sl@0
   813
Return the least-recent-used node.
sl@0
   814
sl@0
   815
@return	the least recent used node on cache
sl@0
   816
*/
sl@0
   817
CLeafDirTreeNode* CLeafDirTree::LruNode()
sl@0
   818
	{
sl@0
   819
	if (iLruList.Count() > 0)
sl@0
   820
		{
sl@0
   821
		return iLruList[iLruList.Count() - 1];
sl@0
   822
		}
sl@0
   823
	return NULL;
sl@0
   824
	}
sl@0
   825
sl@0
   826
/*
sl@0
   827
Factory function of CLeafDirCache
sl@0
   828
sl@0
   829
@param	aLimit	the cache size 
sl@0
   830
*/
sl@0
   831
CLeafDirCache* CLeafDirCache::NewL(TUint32 aLimit)
sl@0
   832
	{
sl@0
   833
	CLeafDirCache* self = new(ELeave) CLeafDirCache(aLimit);
sl@0
   834
	CleanupStack::PushL(self);
sl@0
   835
	self->ConstructL();
sl@0
   836
	CleanupStack::Pop(self);
sl@0
   837
	return self;
sl@0
   838
	}
sl@0
   839
sl@0
   840
/*
sl@0
   841
2nd phase constructor of CLeafDirCache
sl@0
   842
*/
sl@0
   843
void CLeafDirCache::ConstructL()
sl@0
   844
	{
sl@0
   845
	CLeafDirTree* tree = CLeafDirTree::NewL(iSize);
sl@0
   846
	iTree = tree;
sl@0
   847
	}
sl@0
   848
sl@0
   849
/*
sl@0
   850
Destructor of CLeafDirCache
sl@0
   851
*/
sl@0
   852
CLeafDirCache::~CLeafDirCache()
sl@0
   853
	{
sl@0
   854
	delete iTree;
sl@0
   855
	}
sl@0
   856
sl@0
   857
/*
sl@0
   858
Constructor of CLeafDirCache
sl@0
   859
sl@0
   860
@param aLimit the cache size
sl@0
   861
*/
sl@0
   862
CLeafDirCache::CLeafDirCache(TUint32 aSize)
sl@0
   863
              :iSize(aSize)
sl@0
   864
	{
sl@0
   865
	}
sl@0
   866
sl@0
   867
/*
sl@0
   868
Reset cache, delete all memory allocated
sl@0
   869
*/
sl@0
   870
void CLeafDirCache::Reset()
sl@0
   871
	{
sl@0
   872
	iTree->Reset();
sl@0
   873
	}
sl@0
   874
sl@0
   875
/*
sl@0
   876
Cache interface for searching operations.
sl@0
   877
sl@0
   878
@param	aPath	the path of the directory to search for
sl@0
   879
@param	aDirPos	the location of the direcotry found
sl@0
   880
@return	KErrNone if a cached direcotry is found,
sl@0
   881
		KErrBadName if the path is incorrect, otherwise 
sl@0
   882
		other system wide error code
sl@0
   883
*/
sl@0
   884
TInt CLeafDirCache::FindInCache(const TDesC& aPath, TLeafDirData& aLeafDirData) const 
sl@0
   885
	{
sl@0
   886
	if (aPath[0] == '\\')
sl@0
   887
		{
sl@0
   888
		TPtrC path;
sl@0
   889
		path.Set(aPath.Mid(1));
sl@0
   890
		CLeafDirTreeNode* dummy = NULL;
sl@0
   891
		return (iTree->Search(path, dummy, aLeafDirData));
sl@0
   892
		}
sl@0
   893
	else
sl@0
   894
		{
sl@0
   895
		return KErrBadName;
sl@0
   896
		}
sl@0
   897
	}
sl@0
   898
sl@0
   899
/*
sl@0
   900
Cache interface for insertion operations.
sl@0
   901
sl@0
   902
@param	aPath	the path of the directory to be added
sl@0
   903
@param	aDirPos	the location of the direcotry to be added
sl@0
   904
*/
sl@0
   905
void CLeafDirCache::AddToCacheL(const TDesC& aPath, const TLeafDirData& aDirPos)
sl@0
   906
	{
sl@0
   907
	if (aPath.Length() == 1 && aPath[0] == '\\')
sl@0
   908
		return;
sl@0
   909
sl@0
   910
	CLeafDirTreeNode* dummy = NULL;
sl@0
   911
	iTree->InsertL(aPath, aDirPos, dummy);
sl@0
   912
	}
sl@0
   913
sl@0
   914
/*
sl@0
   915
Cache interface for deletion oeprations.
sl@0
   916
Remove all the cached directories with the same specfied position
sl@0
   917
sl@0
   918
@param	aDirPos	the location of the direcotry to be removed
sl@0
   919
*/
sl@0
   920
void CLeafDirCache::RemoveDirL(const TLeafDirData& aDirPos)
sl@0
   921
	{
sl@0
   922
	iTree->RemoveDirL(aDirPos);
sl@0
   923
	}
sl@0
   924
sl@0
   925
/**
sl@0
   926
Update the MRU entry position of the cached leaf dir.
sl@0
   927
@param	aLeafDirData	contains a cluster number as the index of the leaf dir and the new MRU entry position 
sl@0
   928
*/
sl@0
   929
void CLeafDirCache::UpdateMRUPos(const TLeafDirData& aLeafDirData)
sl@0
   930
	{
sl@0
   931
	iTree->UpdateMRUPos(aLeafDirData);
sl@0
   932
	}
sl@0
   933
/*
sl@0
   934
 * Helper functions of CLeafDirTree for debugging & testing use
sl@0
   935
 */
sl@0
   936
#ifdef _DEBUG
sl@0
   937
/*
sl@0
   938
All node created will be added to the container of its owner tree, so that we can calculate
sl@0
   939
	the number of objects created.
sl@0
   940
sl@0
   941
@param	aNodeToAdd	the newly created node to be add to object container 
sl@0
   942
*/
sl@0
   943
void CLeafDirTree::AddToObjectContainerL(CLeafDirTreeNode* aNodeToAdd)
sl@0
   944
	{
sl@0
   945
	iContainer.AppendL(aNodeToAdd);
sl@0
   946
	}
sl@0
   947
sl@0
   948
/*
sl@0
   949
A node is removed from object container if it is deleted.
sl@0
   950
sl@0
   951
@param	aNodeToRemove	the node to be deleted 
sl@0
   952
*/
sl@0
   953
void CLeafDirTree::RemoveFromObjectContainerL(CLeafDirTreeNode* aNodeToRemove)
sl@0
   954
	{
sl@0
   955
	for (TInt i = 0; i < iContainer.Count(); i++)
sl@0
   956
		{
sl@0
   957
		if (aNodeToRemove == iContainer[i])
sl@0
   958
			{
sl@0
   959
			iContainer.Remove(i);
sl@0
   960
			return;
sl@0
   961
			}
sl@0
   962
		}
sl@0
   963
	ASSERT(0);
sl@0
   964
	User::Leave(KErrNotFound);
sl@0
   965
	}
sl@0
   966
sl@0
   967
/*
sl@0
   968
Print out current tree content
sl@0
   969
*/
sl@0
   970
void CLeafDirTree::DumpTreeContentL() const
sl@0
   971
	{
sl@0
   972
	RPointerArray<CLeafDirTreeNode>* nodeStack = new(ELeave) RPointerArray<CLeafDirTreeNode>(4);
sl@0
   973
	RFs fs;
sl@0
   974
	fs.Connect();
sl@0
   975
	const TUint32 debugRegister = DebugRegister();
sl@0
   976
	fs.SetDebugRegister(debugRegister|KFSYS);
sl@0
   977
	if (iRoot != NULL)
sl@0
   978
		{
sl@0
   979
		nodeStack->Insert(iRoot, 0);
sl@0
   980
		while(nodeStack->Count() > 0)
sl@0
   981
			{
sl@0
   982
			CLeafDirTreeNode* current = (*nodeStack)[0];
sl@0
   983
			if (current->Parent() != NULL)
sl@0
   984
				{
sl@0
   985
				__PRINT3(_L("(\"%S\") -> \"%S\" : (%d)\n"), &current->Parent()->Path(), &current->Path(), current->StartClusterNum());
sl@0
   986
				}
sl@0
   987
			else
sl@0
   988
				{
sl@0
   989
				__PRINT2(_L("\"%S\" : (%d)\n"), &current->Path(), current->StartClusterNum());				
sl@0
   990
				}
sl@0
   991
sl@0
   992
			nodeStack->Remove(0);
sl@0
   993
			
sl@0
   994
			TInt currentCount = current->Children().Count();
sl@0
   995
			if (currentCount > 0)
sl@0
   996
				{
sl@0
   997
				RPointerArray<CLeafDirTreeNode> children = current->Children();
sl@0
   998
				for (TInt i = 0; i < currentCount; i++)
sl@0
   999
					{
sl@0
  1000
					nodeStack->Insert(children[i], 0);
sl@0
  1001
					}
sl@0
  1002
				}
sl@0
  1003
			}
sl@0
  1004
		}
sl@0
  1005
sl@0
  1006
	fs.SetDebugRegister(debugRegister);
sl@0
  1007
	fs.Close();
sl@0
  1008
	nodeStack->Close();
sl@0
  1009
	delete nodeStack;
sl@0
  1010
	}
sl@0
  1011
sl@0
  1012
/*
sl@0
  1013
Print out current cache content
sl@0
  1014
*/
sl@0
  1015
void CLeafDirCache::DumpCacheContentL() const
sl@0
  1016
	{
sl@0
  1017
	iTree->DumpTreeContentL();
sl@0
  1018
	}
sl@0
  1019
sl@0
  1020
/*
sl@0
  1021
Count of all the nodes
sl@0
  1022
*/
sl@0
  1023
TInt CLeafDirCache::NodeCount() const
sl@0
  1024
	{
sl@0
  1025
	return iTree->ObjectCount();
sl@0
  1026
	}
sl@0
  1027
#endif // _DEBUG
sl@0
  1028