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