mpx/collectionframework/collectionengine/src/mpxcollectioncache.cpp
changeset 0 a2952bb97e68
child 3 b425f12f328d
equal deleted inserted replaced
-1:000000000000 0:a2952bb97e68
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implements the collection cache
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDES
       
    20 #include <e32base.h>
       
    21 #include <mpxitemid.h>
       
    22 #include <mpxcmn.h>
       
    23 #include <mpxmedia.h>
       
    24 #include <mpxmediaarray.h>
       
    25 #include <mpxcollectionpath.h>
       
    26 #include <mpxmediageneraldefs.h>
       
    27 #include <mpxmediacontainerdefs.h>
       
    28 #include <mpxcollectionopenlresultdef.h>
       
    29 #include <mpxlog.h>
       
    30 #include "mpxcollectioncache.h"
       
    31 
       
    32 // CONSTANTS
       
    33 const TInt KMPXRootNodeId = 0;
       
    34 
       
    35 // ---------------------------------------------------------------------------
       
    36 // static function to compare two datablock items
       
    37 // used for sorting datablocks
       
    38 // ---------------------------------------------------------------------------
       
    39 //
       
    40 static TInt CompareOpenDataBlock( const TMPXOpenDataBlock& aFirst,
       
    41                                   const TMPXOpenDataBlock& aSecond )
       
    42     {
       
    43     return aFirst.iOffset > aSecond.iOffset;
       
    44     }
       
    45 
       
    46 
       
    47 /**
       
    48 * Encapsulates a node in the cache tree.
       
    49 */
       
    50 NONSHARABLE_CLASS(CMPXCollectionCacheNode) :
       
    51     public CBase
       
    52     {
       
    53 public:
       
    54     /**
       
    55     * Two phase constructor.
       
    56     */
       
    57     static CMPXCollectionCacheNode* NewL( const TMPXItemId aId );
       
    58 
       
    59     /**
       
    60     * Destructor.
       
    61     */
       
    62     virtual ~CMPXCollectionCacheNode();
       
    63 
       
    64     /**
       
    65     * Adds a child to the current node.
       
    66     * Ownership of the node is transferred
       
    67     */
       
    68     void AddChildL(CMPXCollectionCacheNode* aChild);
       
    69 
       
    70     /**
       
    71     * Removes a child from the current node.
       
    72     * Ownership of the node is not transferred
       
    73     */
       
    74     void RemoveChild(CMPXCollectionCacheNode& aChild);
       
    75 
       
    76     /**
       
    77     * Retrieves a child by ID. Returns NULL if not found.
       
    78     * Ownership of the node is not transferred.
       
    79     */
       
    80     CMPXCollectionCacheNode* GetChild(TMPXItemId aId);
       
    81 
       
    82     /**
       
    83     * Sets the results and attribute set for the current node.
       
    84     * @param aAttrs list of open attributes
       
    85     * @param aResults results to set in
       
    86     * @param aMediaFromOpen is the media from common
       
    87     */
       
    88     void SetResultsL(
       
    89         const TArray<TMPXAttribute>& aAttrs,
       
    90         CMPXMedia& aResults,
       
    91         TBool aMediaFromOpen );
       
    92 
       
    93     /**
       
    94     * Checks if the specified attribute set exists (is included) in the current
       
    95     * node attribute set.
       
    96     */
       
    97     TBool AttributesExist(const TArray<TMPXAttribute>& aAttrs);
       
    98 
       
    99     /**
       
   100     * Checks if the specified attribute set exists (is included) in the current
       
   101     * node attribute set.
       
   102     */
       
   103     TBool ContainerAttributesExist(const TArray<TMPXAttribute>& aAttrs);
       
   104     
       
   105     /**
       
   106     * Checks if the specified attribute exists (is included) in the current
       
   107     * node attribute set.
       
   108     * @param aAttribute attribute to look for
       
   109     * @param aArray array to check
       
   110     * @return ETrue if found, EFalse if not found
       
   111     */
       
   112     TBool AttributeExists(const TMPXAttribute& aAttribute, 
       
   113                           RArray<TMPXAttribute>& aArray );
       
   114     
       
   115     /**
       
   116     * Checks this node and all child nodes for invalidated data
       
   117     * @param aChangeItemId ID of the item modified
       
   118     * @param aArray array to store the list of affected nodes
       
   119     */
       
   120     void HandleChangeL( TMPXItemId aChangeItemId, 
       
   121                         RPointerArray<CMPXCollectionCacheNode>& aArray );
       
   122                         
       
   123 #ifdef _DEBUG
       
   124     /**
       
   125     * Prints the node.
       
   126     */
       
   127     void PrintNode(TBool aPrintChildren, TBool aPrintAtts);
       
   128 #endif
       
   129 
       
   130 private:
       
   131     /**
       
   132     * C++ constructor
       
   133     */
       
   134     CMPXCollectionCacheNode(TMPXItemId aId,
       
   135         CMPXCollectionCache::TCachePriority aPriority);
       
   136 
       
   137     /**
       
   138     * Second phase constructor.
       
   139     */
       
   140     void ConstructL();
       
   141 
       
   142     /**
       
   143     * Returns the child index for the specified ID or KErrNotFound if not found.
       
   144     */
       
   145     TInt IndexOfId(TMPXItemId aId);
       
   146 
       
   147     /**
       
   148     * Compares two media instances. If the instances refer to the same collection
       
   149     * item (they have the same general ID) returns ETrue, otherwise EFalse.
       
   150     */
       
   151     TBool CompareMediaItemsL(
       
   152         const CMPXMedia& aMedia1, 
       
   153         const CMPXMedia& aMedia2 );
       
   154 
       
   155     /**
       
   156     *  Comparison method for node IDs. Used when searching child nodes by ID.
       
   157     *  Ownership of nodes is not transferred.
       
   158     *  This method is used with the Find method of RPointerArray and 
       
   159     *  must be declared as follow:
       
   160     *  TBool *(aFunction)(const K *k, const T &t);
       
   161     */
       
   162     static TBool CompareIDs(
       
   163         const CMPXCollectionCacheNode* aNode1,
       
   164         const CMPXCollectionCacheNode& aNode2 );
       
   165 
       
   166     /**
       
   167     * Merge the data from two arrays
       
   168     * @param aExistingArray Old array with current data
       
   169     * @param aNewArray New arrary with data to merge
       
   170     */
       
   171     TBool DoMergeMediaArraysL( const CMPXMediaArray& aExistingArray, 
       
   172                                const CMPXMediaArray& aNewArray );
       
   173     
       
   174     /**
       
   175     * Merge the data from two arrays
       
   176     * @param aExistingArray Old array with current data
       
   177     * @param aNewArray New arrary with data to insert
       
   178     */
       
   179     void DoInsertMediaArraysL( CMPXMediaArray& aExistingArray, 
       
   180                                const CMPXMediaArray& aNewArray, 
       
   181                                const TMPXOpenDataBlock& aBlock );
       
   182 
       
   183     /**
       
   184     * Compact a list of open datablocks into larger chunks
       
   185     * @param aArray Array to compact
       
   186     */
       
   187     void DoMergeArrayL( RArray<TMPXOpenDataBlock>& aArray );
       
   188 
       
   189 public:
       
   190     TMPXItemId iId;                                 // node ID (same as path node ID)
       
   191     RArray<TMPXAttribute> iAttrs;                   // attribute set corresponding to the results
       
   192     RArray<TMPXAttribute> iContainerAttrs;          // attribute set corresponding to the container 
       
   193                                                     // of a result set
       
   194     CMPXMedia* iResults;                            // results
       
   195     CMPXCollectionCache::TCachePriority iPriority;  // node priority
       
   196     TTime iTime;                                    // last time the node was updated
       
   197     TInt iLevel;                                    // level of the node in the original path
       
   198 
       
   199     CMPXCollectionCacheNode* iParent;               // parent of the node (NULL for root)
       
   200     RPointerArray<CMPXCollectionCacheNode> iChildren;   // node children
       
   201     TBool iMediaFromOpenL;                          // whether or not this media was from an openl
       
   202     };
       
   203 
       
   204 // ============================ MEMBER FUNCTIONS ==============================
       
   205 
       
   206 // ----------------------------------------------------------------------------
       
   207 // CMPXCollectionCacheNode::NewL
       
   208 // ----------------------------------------------------------------------------
       
   209 //
       
   210 CMPXCollectionCacheNode* CMPXCollectionCacheNode::NewL(
       
   211     const TMPXItemId aId)
       
   212     {
       
   213     MPX_FUNC("CMPXCollectionCacheNode::NewL");
       
   214 
       
   215     CMPXCollectionCacheNode* self = new(ELeave)CMPXCollectionCacheNode(aId,
       
   216         CMPXCollectionCache::EPriorityNormal);
       
   217     CleanupStack::PushL(self);
       
   218     self->ConstructL();
       
   219     CleanupStack::Pop(self);
       
   220     return self;
       
   221     }
       
   222 
       
   223 // ----------------------------------------------------------------------------
       
   224 // CMPXCollectionCacheNode::~CMPXCollectionCacheNode
       
   225 // ----------------------------------------------------------------------------
       
   226 //
       
   227 CMPXCollectionCacheNode::~CMPXCollectionCacheNode()
       
   228     {
       
   229     MPX_FUNC("CMPXCollectionCacheNode::~CMPXCollectionCacheNode");
       
   230 
       
   231     iAttrs.Close();
       
   232     iContainerAttrs.Close();
       
   233     delete iResults;
       
   234 
       
   235     // delete all children
       
   236     iChildren.ResetAndDestroy();
       
   237     }
       
   238 
       
   239 // ----------------------------------------------------------------------------
       
   240 // CMPXCollectionCacheNode::CMPXCollectionCacheNode
       
   241 // ----------------------------------------------------------------------------
       
   242 //
       
   243 CMPXCollectionCacheNode::CMPXCollectionCacheNode(
       
   244     TMPXItemId aId,
       
   245     CMPXCollectionCache::TCachePriority aPriority) :
       
   246     iId(aId),
       
   247     iPriority(aPriority)
       
   248     {
       
   249     MPX_FUNC("CMPXCollectionCacheNode::CMPXCollectionCacheNode");
       
   250     }
       
   251 
       
   252 // ----------------------------------------------------------------------------
       
   253 // CMPXCollectionCacheNode::ConstructL
       
   254 // ----------------------------------------------------------------------------
       
   255 //
       
   256 void CMPXCollectionCacheNode::ConstructL()
       
   257     {
       
   258     MPX_FUNC("CMPXCollectionCacheNode::ConstructL");
       
   259     }
       
   260 
       
   261 // ----------------------------------------------------------------------------
       
   262 // CMPXCollectionCacheNode::AddChildL
       
   263 // ----------------------------------------------------------------------------
       
   264 //
       
   265 void CMPXCollectionCacheNode::AddChildL(
       
   266     CMPXCollectionCacheNode* aChild)
       
   267     {
       
   268     MPX_FUNC("CMPXCollectionCacheNode::AddChildL");
       
   269     aChild->iParent = this;
       
   270     iChildren.AppendL(aChild);
       
   271     }
       
   272 
       
   273 // ----------------------------------------------------------------------------
       
   274 // CMPXCollectionCacheNode::RemoveChild
       
   275 // ----------------------------------------------------------------------------
       
   276 //
       
   277 void CMPXCollectionCacheNode::RemoveChild(
       
   278     CMPXCollectionCacheNode& aChild)
       
   279     {
       
   280     MPX_FUNC("CMPXCollectionCacheNode::RemoveChild");
       
   281 
       
   282     TInt index = IndexOfId(aChild.iId);
       
   283     if (index != KErrNotFound)
       
   284         {
       
   285         // remove the child
       
   286         iChildren.Remove(index);
       
   287         }
       
   288     }
       
   289 
       
   290 // ----------------------------------------------------------------------------
       
   291 // CMPXCollectionCacheNode::GetChild
       
   292 // ----------------------------------------------------------------------------
       
   293 //
       
   294 CMPXCollectionCacheNode* CMPXCollectionCacheNode::GetChild(
       
   295     TMPXItemId aId)
       
   296     {
       
   297     MPX_FUNC("CMPXCollectionCacheNode::GetChild");
       
   298 
       
   299     CMPXCollectionCacheNode* child(NULL);
       
   300 
       
   301     TInt index = IndexOfId(aId);
       
   302     if (index != KErrNotFound)
       
   303         {
       
   304         child = iChildren[index];
       
   305         }
       
   306 
       
   307     return child;
       
   308     }
       
   309 
       
   310 // ----------------------------------------------------------------------------
       
   311 // CMPXCollectionCacheNode::SetResultsL
       
   312 // If results are already stored in the node try to merge the new results,
       
   313 // otherwise overwrite them.
       
   314 // ----------------------------------------------------------------------------
       
   315 //
       
   316 void CMPXCollectionCacheNode::SetResultsL(
       
   317     const TArray<TMPXAttribute>& aAttrs,
       
   318     CMPXMedia& aResults,
       
   319     TBool aMediaFromOpen )
       
   320     {
       
   321     MPX_FUNC("CMPXCollectionCacheNode::SetResultsL");
       
   322 
       
   323     // Problem if we did not have results from before, but
       
   324     // want to merge in new data. Plugins returning all results will
       
   325     // not contain KMPXCollectionOpenLResultRange in the media
       
   326     // therefore we do manual merging. If it does contain the attribute
       
   327     // That means it is from a subset, with a particular offset and block size
       
   328     //
       
   329     TMPXOpenDataBlock block;
       
   330     block.iOffset = KErrNotFound;
       
   331     if( aResults.IsSupported( KMPXCollectionOpenLResultRange ) )
       
   332         {
       
   333         block = aResults.ValueTObjectL<TMPXOpenDataBlock>( 
       
   334                                             KMPXCollectionOpenLResultRange );
       
   335         
       
   336         // If the results have not been cached before, 
       
   337         // we have nothing to merge
       
   338         //
       
   339         if( !iResults && block.iOffset != KErrNotFound )
       
   340             {
       
   341             User::Leave( KErrArgument );
       
   342             }
       
   343         }
       
   344             
       
   345     TBool overwrite(ETrue);
       
   346     
       
   347     // Merge
       
   348     if ( iResults )
       
   349         {
       
   350         // extract the arrays from the two media instances
       
   351         CMPXMediaArray* existingArray(NULL);
       
   352         if ( iResults->IsSupported(KMPXMediaArrayContents) )
       
   353             {
       
   354             existingArray = 
       
   355                         iResults->Value<CMPXMediaArray>(KMPXMediaArrayContents);
       
   356             User::LeaveIfNull(existingArray);
       
   357             }
       
   358 
       
   359         const CMPXMediaArray* newArray(NULL);
       
   360         if ( aResults.IsSupported( KMPXMediaArrayContents ))
       
   361             {
       
   362             newArray = aResults.Value<CMPXMediaArray>(KMPXMediaArrayContents);
       
   363             User::LeaveIfNull(const_cast<CMPXMediaArray*>(newArray));
       
   364             }
       
   365             
       
   366         // Only need to merge the two arrays if they exist, else it will just overwrite
       
   367         if ( existingArray && newArray && existingArray->Count())
       
   368             {
       
   369             if( block.iOffset == KErrNotFound )
       
   370                 {
       
   371                 overwrite = DoMergeMediaArraysL( *existingArray, 
       
   372                                                  *newArray );
       
   373                 }
       
   374             else // aOffset != KErrNotFound 
       
   375                 {
       
   376                 DoInsertMediaArraysL( *existingArray, 
       
   377                                       *newArray, 
       
   378                                       block );
       
   379                 
       
   380                 // These 2 attributes already merged
       
   381                 //
       
   382                 aResults.Delete( KMPXMediaArrayContents );
       
   383                 aResults.Delete( KMPXMediaArrayCount );
       
   384                 
       
   385                 // Merge container media
       
   386                 //
       
   387                 iResults->MergeMediaL( aResults );
       
   388                 
       
   389                 // Merge the root media
       
   390                 //
       
   391                 overwrite = EFalse;
       
   392                 }
       
   393             }
       
   394         else
       
   395             {
       
   396             iResults->MergeMediaL( aResults );
       
   397             overwrite = EFalse;
       
   398             }
       
   399         }
       
   400 
       
   401     if (overwrite)
       
   402         {
       
   403         // List of supported attributes is 
       
   404         // seperated to media w/ container from OpenL()
       
   405         // and media only from MediaL()
       
   406         //
       
   407         if( aMediaFromOpen )
       
   408             {
       
   409             iAttrs.Reset();
       
   410             ::CopyArrayL(aAttrs, iAttrs);
       
   411             }
       
   412         else
       
   413             {
       
   414             iContainerAttrs.Reset();
       
   415             ::CopyArrayL(aAttrs, iContainerAttrs);
       
   416             }
       
   417                 
       
   418         delete iResults;
       
   419         iResults = NULL;
       
   420         iResults = CMPXMedia::NewL( aResults );
       
   421         }
       
   422     else
       
   423         {
       
   424         // Update either the array list or the root media list
       
   425         //
       
   426         if( aMediaFromOpen )
       
   427             {
       
   428             // Add the attributes into the list
       
   429             for ( TInt attrIndex = 0; attrIndex < aAttrs.Count(); attrIndex++ )
       
   430                 {
       
   431                 const TMPXAttribute& attr = aAttrs[attrIndex];
       
   432                 if ( !AttributeExists( attr, iAttrs ))
       
   433                     {
       
   434                     iAttrs.AppendL( attr );
       
   435                     }
       
   436                 }    
       
   437             }
       
   438         else
       
   439             {
       
   440             // Add the attributes into the container list
       
   441             for ( TInt attrIndex = 0; attrIndex < aAttrs.Count(); attrIndex++ )
       
   442                 {
       
   443                 const TMPXAttribute& attr = aAttrs[attrIndex];
       
   444                 if ( !AttributeExists( attr, iContainerAttrs ))
       
   445                     {
       
   446                     iContainerAttrs.AppendL( attr );
       
   447                     }
       
   448                 }
       
   449             }
       
   450         }
       
   451 #ifdef _DEBUG
       
   452     MPX_DEBUG1("CMPXCollectionCacheNode::SetResultsL(): Attributes cached");
       
   453     for ( TInt k = 0; k < iAttrs.Count(); k++ )
       
   454         {
       
   455         MPX_DEBUG4("CMPXCollectionCacheNode::SetResultsL(): attr[%d] = {0x%x,0x%x}", 
       
   456                    k, iAttrs[k].ContentId(), iAttrs[k].AttributeId());
       
   457         }
       
   458 #endif
       
   459     }
       
   460 
       
   461 // ----------------------------------------------------------------------------
       
   462 // CMPXCollectionCacheNode::AttributesExist
       
   463 // ----------------------------------------------------------------------------
       
   464 //
       
   465 TBool CMPXCollectionCacheNode::AttributesExist(
       
   466     const TArray<TMPXAttribute>& aAttrs)
       
   467     {
       
   468     MPX_FUNC("CMPXCollectionCacheNode::AttributesExist");
       
   469 
       
   470     TBool exist(ETrue);
       
   471     if (0 == aAttrs.Count())
       
   472         {
       
   473         // no attributes specified, always exist
       
   474         exist = ETrue;
       
   475         }
       
   476     else if (0 == iAttrs.Count())
       
   477         {
       
   478         // no existing attributes, always do not exist
       
   479         exist = EFalse;
       
   480         }
       
   481     else
       
   482         {
       
   483         // both have valid number of attributes
       
   484         TInt count(aAttrs.Count());
       
   485         for (TInt index = 0; index < count; ++index)
       
   486             {
       
   487             if (!AttributeExists(aAttrs[index], iAttrs))
       
   488                 {
       
   489                 exist = EFalse;
       
   490                 break;
       
   491                 }
       
   492             }
       
   493         }
       
   494 
       
   495     return exist;
       
   496     }
       
   497 
       
   498 // ----------------------------------------------------------------------------
       
   499 // CMPXCollectionCacheNode::AttributesExist
       
   500 // ----------------------------------------------------------------------------
       
   501 //
       
   502 TBool CMPXCollectionCacheNode::ContainerAttributesExist(
       
   503     const TArray<TMPXAttribute>& aAttrs)
       
   504     {
       
   505     MPX_FUNC("CMPXCollectionCacheNode::ContainerAttributesExist");
       
   506 
       
   507     TBool exist(ETrue);
       
   508     if (0 == aAttrs.Count())
       
   509         {
       
   510         // no attributes specified, always exist
       
   511         exist = ETrue;
       
   512         }
       
   513     else if (0 == iContainerAttrs.Count())
       
   514         {
       
   515         // no existing attributes, always do not exist
       
   516         exist = EFalse;
       
   517         }
       
   518     else
       
   519         {
       
   520         // both have valid number of attributes
       
   521         TInt count(aAttrs.Count());
       
   522         for (TInt index = 0; index < count; ++index)
       
   523             {
       
   524             if (!AttributeExists(aAttrs[index], 
       
   525                                  iContainerAttrs))
       
   526                 {
       
   527                 exist = EFalse;
       
   528                 break;
       
   529                 }
       
   530             }
       
   531         }
       
   532 
       
   533     return exist;
       
   534     }
       
   535 
       
   536 // ----------------------------------------------------------------------------
       
   537 // CMPXCollectionCacheNode::AttributeExists
       
   538 // ----------------------------------------------------------------------------
       
   539 //
       
   540 TBool CMPXCollectionCacheNode::AttributeExists(
       
   541     const TMPXAttribute& aAttribute, 
       
   542     RArray<TMPXAttribute>& aArray)
       
   543     {
       
   544     MPX_FUNC("CMPXCollectionCacheNode::AttributeExists");
       
   545 
       
   546     TBool ret(ETrue);
       
   547 
       
   548     TUint content(aAttribute.ContentId());
       
   549     TUint attribute(aAttribute.AttributeId());
       
   550     TInt count(aArray.Count());
       
   551     
       
   552     // Have to do an exhaustive search of every bit
       
   553     // This is because clients can compress the content IDs
       
   554     //
       
   555     TUint32 mask(1); // 0x00000001
       
   556     while( mask != 0 )
       
   557         {
       
   558         TUint32 val(attribute&mask);
       
   559         if( val )
       
   560             {
       
   561             TInt i;
       
   562             for (i = 0; i < count; ++i)
       
   563                 {
       
   564                 if (aArray[i].ContentId() == content &&
       
   565                     (aArray[i].AttributeId() & val) )
       
   566                     {
       
   567                     // break out of for loop
       
   568                     break;
       
   569                     }
       
   570                 }
       
   571             if( i==count )
       
   572                 {
       
   573                 // break out of while loop if
       
   574                 // the particular bit is not found
       
   575                 ret = EFalse;
       
   576                 break; 
       
   577                 }
       
   578             }
       
   579         mask = mask<<1; // Check next bit
       
   580         }
       
   581     
       
   582     return ret;
       
   583     }
       
   584 
       
   585 // ----------------------------------------------------------------------------
       
   586 // Handles any changes to the collection cache
       
   587 // ----------------------------------------------------------------------------
       
   588 //
       
   589 void CMPXCollectionCacheNode::HandleChangeL( TMPXItemId aChangeItemId, 
       
   590                                 RPointerArray<CMPXCollectionCacheNode>& aArray )
       
   591     {
       
   592     // This node is affected
       
   593     // All child nodes are invalid!
       
   594     //
       
   595     TBool aOpen(ETrue);
       
   596     if( iId == aChangeItemId )
       
   597         {
       
   598         aArray.AppendL( this );
       
   599         aOpen=EFalse; // wiping out this node already
       
   600         }
       
   601     else if( iChildren.Count() )
       
   602         {
       
   603         TInt c( iChildren.Count() );
       
   604         for( TInt i=0; i<c; ++i )
       
   605             {
       
   606             // Next level maybe all MediaL() data 
       
   607             // in which case we do want to check this level's array
       
   608             //
       
   609             iChildren[i]->HandleChangeL( aChangeItemId, aArray );
       
   610             }
       
   611         }
       
   612         
       
   613     // Check the contents as well
       
   614     //
       
   615     if( aOpen )
       
   616         {
       
   617         // This is a leaf node, so we check the array
       
   618         //
       
   619         if( iResults && 
       
   620             iResults->IsSupported(KMPXMediaArrayContents) )
       
   621             {
       
   622             // Array not owned
       
   623             const CMPXMediaArray& ary =
       
   624                           *iResults->Value<CMPXMediaArray>(KMPXMediaArrayContents);
       
   625             User::LeaveIfNull(const_cast<CMPXMediaArray*>(&ary));
       
   626             TInt c(ary.Count() );
       
   627             
       
   628             // Check every media item, this *MAYBE* slow. May want to consider
       
   629             // caching all item IDs within each node for performance
       
   630             for( TInt i=0; i<c; ++i )
       
   631                 {
       
   632                 TMPXItemId id=KMPXInvalidItemId;
       
   633                 const CMPXMedia& m = *(ary.AtL(i));
       
   634                 
       
   635                 // Just to be safe
       
   636                 if( m.IsSupported( KMPXMediaGeneralId ) )
       
   637                     {
       
   638                     id=m.ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId);
       
   639                     }
       
   640                 
       
   641                 // If we match, add this as affected and return
       
   642                 if( id == aChangeItemId )
       
   643                     {
       
   644                     aArray.AppendL( this );
       
   645                     break;
       
   646                     }
       
   647                 } // for
       
   648             } // if iResults
       
   649         } // if no children
       
   650     }
       
   651     
       
   652 // ----------------------------------------------------------------------------
       
   653 // CMPXCollectionCacheNode::IndexOfId
       
   654 // ----------------------------------------------------------------------------
       
   655 //
       
   656 TInt CMPXCollectionCacheNode::IndexOfId(
       
   657     TMPXItemId aId)
       
   658     {
       
   659     MPX_FUNC("CMPXCollectionCacheNode::IndexOfId");
       
   660     TInt index( KErrNotFound );
       
   661 
       
   662     CMPXCollectionCacheNode* node( NULL );
       
   663     MPX_TRAPD(err, node = CMPXCollectionCacheNode::NewL( aId ));
       
   664     if ( KErrNone == err )
       
   665         {
       
   666         index = iChildren.Find(*node, CompareIDs);
       
   667         delete node;
       
   668         }
       
   669 
       
   670     return index;
       
   671     }
       
   672 
       
   673 // ----------------------------------------------------------------------------
       
   674 // CMPXCollectionCacheNode::CompareMediaItems
       
   675 // ----------------------------------------------------------------------------
       
   676 //
       
   677 TBool CMPXCollectionCacheNode::CompareMediaItemsL(
       
   678     const CMPXMedia& aItem1,
       
   679     const CMPXMedia& aItem2)
       
   680     {
       
   681     return aItem1.IsSupported(KMPXMediaGeneralId) &&
       
   682         aItem2.IsSupported(KMPXMediaGeneralId) &&
       
   683         (aItem1.ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId) ==
       
   684          aItem2.ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId));
       
   685     }
       
   686 
       
   687 // ----------------------------------------------------------------------------
       
   688 // CMPXCollectionCacheNode::CompareIDs
       
   689 // ----------------------------------------------------------------------------
       
   690 //
       
   691 TBool CMPXCollectionCacheNode::CompareIDs(
       
   692     const CMPXCollectionCacheNode* aNode1,
       
   693     const CMPXCollectionCacheNode& aNode2)
       
   694     {
       
   695     MPX_FUNC("CMPXCollectionCacheNode::CompareIDs");
       
   696     return aNode1->iId == aNode2.iId;
       
   697     }
       
   698 
       
   699 // ----------------------------------------------------------------------------
       
   700 // CMPXCollectionCacheNode::DoMergeMediaArraysL
       
   701 // ----------------------------------------------------------------------------
       
   702 //
       
   703 TBool CMPXCollectionCacheNode::DoMergeMediaArraysL( const CMPXMediaArray& aExistingArray,
       
   704                                                     const CMPXMediaArray& aNewArray )
       
   705     {
       
   706     TBool overwrite(ETrue);
       
   707     TInt newCount( aNewArray.Count() );
       
   708     for ( TInt arrayIndex = 0; arrayIndex < newCount; arrayIndex++ )
       
   709         {
       
   710         const CMPXMedia* newItem( (aNewArray).AtL(arrayIndex) );
       
   711         CMPXMedia* existingItem( NULL );
       
   712         TInt existingCount( aExistingArray.Count() );
       
   713         if ( arrayIndex < existingCount )
       
   714             {
       
   715             existingItem = aExistingArray.AtL(arrayIndex);
       
   716             }
       
   717         else
       
   718             {
       
   719             existingItem = aExistingArray.AtL(0);
       
   720             }
       
   721 
       
   722         MPX_ASSERT(newItem->IsSupported(KMPXMediaGeneralId));
       
   723         MPX_ASSERT(existingItem->IsSupported(KMPXMediaGeneralId));
       
   724 
       
   725         // try to match the items at the same index
       
   726         if ( CompareMediaItemsL( *newItem, *existingItem ))
       
   727             {
       
   728             existingItem->MergeMediaL( *newItem );
       
   729             overwrite = EFalse;
       
   730             }
       
   731         else
       
   732             {
       
   733             // items do not match, try linear search
       
   734             TBool found(EFalse);
       
   735             for ( TInt i = 0; i < existingCount && !found; ++i )
       
   736                 {
       
   737                 CMPXMedia* item( aExistingArray.AtL(i) );
       
   738                 // Already compared existing item so skip it
       
   739                 if ( item != existingItem )
       
   740                     {
       
   741                     if ( CompareMediaItemsL( *newItem, *item ))
       
   742                         {
       
   743                         // found the item
       
   744                         item->MergeMediaL( *newItem );
       
   745                         overwrite = EFalse;
       
   746                         found = ETrue;
       
   747                         }
       
   748                     }
       
   749                 }
       
   750             }
       
   751         }
       
   752     return overwrite;
       
   753     }
       
   754 
       
   755 // ----------------------------------------------------------------------------
       
   756 // CMPXCollectionCacheNode::DoInsertMediaArraysL
       
   757 // ----------------------------------------------------------------------------
       
   758 //
       
   759 void CMPXCollectionCacheNode::DoInsertMediaArraysL( CMPXMediaArray& aExistingArray, 
       
   760                                                     const CMPXMediaArray& aNewArray, 
       
   761                                                     const TMPXOpenDataBlock& aBlock )
       
   762     {
       
   763     // Overflow checking. Make sure array indexes are correct
       
   764     //
       
   765     TInt newCount( aNewArray.Count() );
       
   766     if( aBlock.iOffset + newCount > aExistingArray.Count() )
       
   767         {
       
   768         User::Leave( KErrArgument );
       
   769         }
       
   770     
       
   771     // Merge all results by inserting into the existing array
       
   772     //
       
   773     for( TInt i=0; i<newCount; ++i )
       
   774         {
       
   775         aExistingArray.Set(*aNewArray.AtL(i),aBlock.iOffset+i);
       
   776         }
       
   777 
       
   778 
       
   779     // Update the container information about what has been read
       
   780     RArray<TMPXOpenDataBlock> datablocks;
       
   781     CleanupClosePushL( datablocks );
       
   782     if( iResults && 
       
   783         iResults->IsSupported(KMPXCollectionOpenLAllResultRange) )
       
   784         {
       
   785         // De-serialize from global data, would be good to have global arrays
       
   786         //
       
   787         const TDesC& buf = iResults->ValueText(KMPXCollectionOpenLAllResultRange);
       
   788         CBufBase* buffer(NULL);
       
   789         MPXUser::CreateBufferL( buf, buffer );
       
   790         CleanupStack::PushL( buffer );
       
   791         ::CreateFromBufferL( *buffer, datablocks );
       
   792         CleanupStack::PopAndDestroy( buffer );
       
   793         }
       
   794     
       
   795     // Append, sort and merge the array for more effient access
       
   796     //
       
   797     datablocks.AppendL( aBlock );
       
   798     
       
   799     // Sort and merge the data array
       
   800     //
       
   801     datablocks.Sort( CompareOpenDataBlock );
       
   802     DoMergeArrayL( datablocks );
       
   803     
       
   804     // Package it and store in media
       
   805     // Store the block list
       
   806     //
       
   807     CBufBase* buffer(NULL);
       
   808     ::CreateBufferL( datablocks.Array(), buffer );
       
   809     CleanupStack::PushL( buffer );
       
   810     TPtr8 ptr8 = buffer->Ptr(0);
       
   811     TPtrC ptr = MPXUser::Ptr( ptr8 );
       
   812     iResults->SetTextValueL( KMPXCollectionOpenLAllResultRange, ptr );
       
   813     CleanupStack::PopAndDestroy( buffer );
       
   814     
       
   815     CleanupStack::PopAndDestroy( &datablocks );
       
   816     }
       
   817 
       
   818 // ----------------------------------------------------------------------------
       
   819 // Compact the datablocks
       
   820 // ----------------------------------------------------------------------------
       
   821 //
       
   822 void CMPXCollectionCacheNode::DoMergeArrayL( RArray<TMPXOpenDataBlock>& aArray )
       
   823     {
       
   824     // O(n^2) complexity here is OK, Merging keeps the number of items 
       
   825     // very small. Less than 3 items are alive at a time
       
   826     //
       
   827     RArray<TMPXOpenDataBlock> newArray;
       
   828     CleanupClosePushL( newArray );
       
   829     
       
   830     TInt c1 = aArray.Count();
       
   831     for( TInt i=0; i<c1; ++i )
       
   832         {
       
   833         TBool updated(EFalse);
       
   834         TMPXOpenDataBlock& curBlock = aArray[i];
       
   835         
       
   836         TInt c2( newArray.Count() );
       
   837         for( TInt j=0; j<c2; ++j )
       
   838             {
       
   839             TMPXOpenDataBlock& mergedBlock = newArray[j];
       
   840             if( mergedBlock.iOffset == curBlock.iOffset + curBlock.iSize )
       
   841                 {
       
   842                 mergedBlock.iOffset = curBlock.iOffset;
       
   843                 mergedBlock.iSize += curBlock.iSize;
       
   844                 updated = ETrue;
       
   845                 break;
       
   846                 }
       
   847             else if( mergedBlock.iOffset + mergedBlock.iSize == curBlock.iOffset )
       
   848                 {
       
   849                 mergedBlock.iSize += curBlock.iSize;
       
   850                 updated = ETrue;
       
   851                 break;
       
   852                 }
       
   853             }
       
   854         
       
   855         if( !updated )
       
   856             {
       
   857             newArray.AppendL( curBlock );
       
   858             }
       
   859         }
       
   860         
       
   861     aArray.Reset();
       
   862     TInt c3( newArray.Count() );
       
   863     for( TInt i=0; i<c3; ++i )
       
   864         {
       
   865         aArray.AppendL( newArray[i] );
       
   866         MPX_DEBUG3("Order: %i %i", newArray[i].iOffset, newArray[i].iSize );
       
   867         }
       
   868     CleanupStack::PopAndDestroy( &newArray );
       
   869     }
       
   870                                  
       
   871 #ifdef _DEBUG
       
   872 
       
   873 // ----------------------------------------------------------------------------
       
   874 // CMPXCollectionCacheNode::PrintNode
       
   875 // ----------------------------------------------------------------------------
       
   876 //
       
   877 void CMPXCollectionCacheNode::PrintNode(
       
   878     TBool aPrintChildren,
       
   879     TBool aPrintAtts )
       
   880     {
       
   881     TBuf<30> buf;
       
   882     _LIT(KFormatString, "%-B%:0%J%:1%T%:2%S%:3%+B");
       
   883     TRAP_IGNORE( iTime.FormatL( buf, KFormatString ));
       
   884     // use RDebug directly since there is no MPX_DEBUG with 6 parameters.
       
   885     RDebug::Print(_L("+Id: %08X, Level: %d, Priority: %d, Time: %S"),
       
   886         iId.iId1, iLevel, iPriority, &buf);
       
   887     MPX_DEBUG2("CMPXCollectionCacheNode::PrintNode(): iMediaFromOpenL = %d", 
       
   888                 iMediaFromOpenL);
       
   889     
       
   890     if ( aPrintAtts )
       
   891         {
       
   892         for ( TInt j = 0; j < iAttrs.Count(); j++ )
       
   893             {
       
   894             TMPXAttribute att( iAttrs[j] );
       
   895             MPX_DEBUG4("CMPXCollectionCacheNode::PrintNode(): attr[%d] = {0x%x,0x%x}", 
       
   896                                     j, att.ContentId(), att.AttributeId());
       
   897             TMPXAttributeType type( iResults->Type( att ));
       
   898             if ( EMPXTypeText == type )
       
   899                 {
       
   900                 MPX_DEBUG2("CMPXCollectionCacheNode::PrintNode(): Text = %S", 
       
   901                                                     &(iResults->ValueText( att )));
       
   902                 }
       
   903             else if ( EMPXTypeTInt == type )
       
   904                 {
       
   905                 TInt val(0);
       
   906                 TRAP_IGNORE(val = (iResults->ValueTObjectL<TInt>( att )));
       
   907                 MPX_DEBUG2("CMPXCollectionCacheNode::PrintNode(): TInt = %d", 
       
   908                            val);
       
   909                 }
       
   910             }
       
   911         }
       
   912 
       
   913     if ( aPrintChildren )
       
   914         {
       
   915         TInt children( iChildren.Count() );
       
   916         for ( TInt index = 0; index < children; ++index )
       
   917             {
       
   918             iChildren[index]->PrintNode( ETrue, aPrintAtts );
       
   919             }
       
   920         }
       
   921     }
       
   922 
       
   923 #endif
       
   924 
       
   925 // ----------------------------------------------------------------------------
       
   926 // CMPXCollectionCache::NewL
       
   927 // ----------------------------------------------------------------------------
       
   928 //
       
   929 CMPXCollectionCache* CMPXCollectionCache::NewL(
       
   930     TInt aMaximumSizeRatio /* = -1 */)
       
   931     {
       
   932     MPX_FUNC("CMPXCollectionCache::NewL");
       
   933 
       
   934     CMPXCollectionCache* self = new(ELeave) CMPXCollectionCache( aMaximumSizeRatio );
       
   935     CleanupStack::PushL(self);
       
   936     self->ConstructL();
       
   937     CleanupStack::Pop(self);
       
   938     return self;
       
   939     }
       
   940 
       
   941 // ----------------------------------------------------------------------------
       
   942 // CMPXCollectionCache::~CMPXCollectionCache
       
   943 // ----------------------------------------------------------------------------
       
   944 //
       
   945 CMPXCollectionCache::~CMPXCollectionCache()
       
   946     {
       
   947     MPX_FUNC("CMPXCollectionCache::~CMPXCollectionCache");
       
   948 
       
   949     // delete the entire cache
       
   950     delete iRoot;
       
   951     }
       
   952 
       
   953 // ----------------------------------------------------------------------------
       
   954 // CMPXCollectionCache::Add
       
   955 // ----------------------------------------------------------------------------
       
   956 //
       
   957 CMPXMedia* CMPXCollectionCache::AddL(
       
   958     const CMPXCollectionPath& aPath,
       
   959     const TArray<TMPXAttribute>& aAttrs,
       
   960     CMPXMedia& aResults,
       
   961     TBool aMediaFromOpenL, 
       
   962     TCachePriority aPriority)
       
   963     {
       
   964     MPX_FUNC("CMPXCollectionCache::DoAddL");
       
   965     MPX_DEBUG_PATH(aPath);
       
   966     
       
   967     CMPXMedia* ret( &aResults );
       
   968 
       
   969     //if OOM then clear current cache and don't add to cache
       
   970     TBool toCache = ManageCacheSizeL();
       
   971     
       
   972     //!media in array should support KMPXMediaGeneralId otherwise we don't cache it
       
   973     if(toCache && aResults.IsSupported(KMPXMediaArrayContents))
       
   974         {
       
   975         const CMPXMediaArray* resultsArray(
       
   976                     aResults.Value<CMPXMediaArray>(KMPXMediaArrayContents));
       
   977         User::LeaveIfNull(const_cast<CMPXMediaArray*>(resultsArray));
       
   978         TInt arrCount(resultsArray->Count());
       
   979         for(TInt arrInd = 0; arrInd < arrCount; ++arrInd)
       
   980             {
       
   981             const CMPXMedia* curItem(resultsArray->AtL(arrInd));
       
   982             if(!curItem->IsSupported(KMPXMediaGeneralId))
       
   983                 {
       
   984                 MPX_DEBUG1("CMPXCollectionCache::AddL: Missing MediaGeneralId - caching skipped");
       
   985                 toCache = EFalse;
       
   986                 break;
       
   987                 }
       
   988             }
       
   989         }
       
   990     
       
   991     if (toCache && aResults.IsSupported(KMPXMediaGeneralNonPermissibleActions ) )
       
   992         {
       
   993         // check for auto playlist, it should not be cached
       
   994         TMPXGeneralNonPermissibleActions attr(
       
   995                 aResults.ValueTObjectL<TMPXGeneralNonPermissibleActions>( 
       
   996                 KMPXMediaGeneralNonPermissibleActions ) );
       
   997         if ( attr & EMPXCache )
       
   998             {
       
   999             toCache = EFalse;
       
  1000             }
       
  1001         }                                        
       
  1002 
       
  1003     if(toCache)
       
  1004         {
       
  1005         // get the corresponding node, create if not available
       
  1006         CMPXCollectionCacheNode* node = NodeFromPathL(aPath, ETrue);
       
  1007 
       
  1008         // update the node
       
  1009         node->SetResultsL( aAttrs, aResults, aMediaFromOpenL );
       
  1010         node->iMediaFromOpenL = node->iMediaFromOpenL || aMediaFromOpenL;
       
  1011 
       
  1012         // set the priority and the "last updated" timestamp
       
  1013         node->iPriority = aPriority;
       
  1014         node->iLevel = aPath.Levels();
       
  1015         node->iTime.HomeTime();
       
  1016 
       
  1017         ret = node->iResults;
       
  1018         }
       
  1019 #ifdef _DEBUG
       
  1020     PrintTree( ETrue );
       
  1021 #endif
       
  1022     return ret;
       
  1023     }
       
  1024 
       
  1025 // ----------------------------------------------------------------------------
       
  1026 // CMPXCollectionCache::GetL
       
  1027 // ----------------------------------------------------------------------------
       
  1028 //
       
  1029 CMPXMedia* CMPXCollectionCache::GetL(
       
  1030     const CMPXCollectionPath& aPath,
       
  1031     const TArray<TMPXAttribute>& aAttrs,
       
  1032     TBool aMediaFromOpenL /* = EFalse */ )
       
  1033     {
       
  1034     MPX_FUNC("CMPXCollectionCache::GetL");
       
  1035     MPX_DEBUG_PATH(aPath);
       
  1036 
       
  1037     CMPXMedia* results(NULL);
       
  1038 
       
  1039     // get the corresponding node, do not create if not available
       
  1040     CMPXCollectionCacheNode* node = NodeFromPathL(aPath, EFalse);
       
  1041 
       
  1042     TInt selCount = aPath.Selection().Count();
       
  1043 
       
  1044     // Check if node exists and attributes match
       
  1045     // If we are calling from openL() or mediaL() on multiple items, we check the array
       
  1046     // attributes. If we are calling from MediaL() with a single item
       
  1047     // we check the container attributes
       
  1048     //
       
  1049     if ( (aMediaFromOpenL || selCount )
       
  1050           && node && node->AttributesExist(aAttrs))
       
  1051         {
       
  1052         // Check if it needs to be a media from openl
       
  1053         // If not just return the results.  But if it needs to be a media from
       
  1054         // OpenL, then need to check if the results are actually from an OpenL
       
  1055         if ( (aMediaFromOpenL && node->iMediaFromOpenL) ||
       
  1056              !aMediaFromOpenL )
       
  1057             {
       
  1058             results = node->iResults;
       
  1059             }
       
  1060         }
       
  1061     else if( node && node->ContainerAttributesExist(aAttrs) )
       
  1062         {
       
  1063         // Here we end from a MediaL call, we need to check if there are items selected
       
  1064         // in this case NodeFromPathL result may be ivalid as it using only focused item
       
  1065         // so we will pass that call to plugin and ignore found node from cache in that case
       
  1066         if(selCount == 0)
       
  1067             {
       
  1068             results = node->iResults;
       
  1069             }
       
  1070         }
       
  1071 
       
  1072     // note that NULL is returned for nodes without results
       
  1073     // (created empty to link to other nodes)
       
  1074     return results;
       
  1075     }
       
  1076 
       
  1077 // ----------------------------------------------------------------------------
       
  1078 // CMPXCollectionCache::RemoveL
       
  1079 // ----------------------------------------------------------------------------
       
  1080 //
       
  1081 void CMPXCollectionCache::RemoveL(
       
  1082     const CMPXCollectionPath& aPath)
       
  1083     {
       
  1084     MPX_FUNC("CMPXCollectionCache::RemoveL(CMPXCollectionPath)");
       
  1085     MPX_DEBUG_PATH(aPath);
       
  1086 
       
  1087     // get the corresponding node, do not create if not available
       
  1088     CMPXCollectionCacheNode* node( NodeFromPathL( aPath, EFalse ));
       
  1089 
       
  1090     // if node exists
       
  1091     if ( node )
       
  1092         {
       
  1093         // delete it and its children
       
  1094         RemoveNode( node );
       
  1095 #ifdef _DEBUG
       
  1096         PrintTree( ETrue );
       
  1097 #endif
       
  1098         }
       
  1099     }
       
  1100 
       
  1101 // ----------------------------------------------------------------------------
       
  1102 // CMPXCollectionCache::Reset
       
  1103 // ----------------------------------------------------------------------------
       
  1104 //
       
  1105 void CMPXCollectionCache::Reset()
       
  1106     {
       
  1107     MPX_FUNC("CMPXCollectionCache::ClearCache");
       
  1108     iRoot->iChildren.ResetAndDestroy();
       
  1109     iRoot->iAttrs.Reset();
       
  1110     }
       
  1111 
       
  1112 // ----------------------------------------------------------------------------
       
  1113 // CMPXCollectionCache::HandleChangeL()
       
  1114 // ----------------------------------------------------------------------------
       
  1115 //
       
  1116 void CMPXCollectionCache::HandleChangeL( TUid aCollectionId, TMPXItemId aChangeItemId )
       
  1117     {
       
  1118     // First get the cache node associated with the collection
       
  1119     // If the node exists, then we recursively get every node to handle the change
       
  1120     //
       
  1121     TMPXItemId root( aCollectionId.iUid );
       
  1122     CMPXCollectionCacheNode* rootNode = iRoot->GetChild( root );
       
  1123     
       
  1124     // Array does not own any of the objects
       
  1125     RPointerArray<CMPXCollectionCacheNode> affectedNodes; 
       
  1126     CleanupClosePushL( affectedNodes );
       
  1127     if( rootNode )
       
  1128         {
       
  1129         // Iteratively check every node
       
  1130         //
       
  1131         rootNode->HandleChangeL( aChangeItemId, 
       
  1132                                  affectedNodes );
       
  1133         }
       
  1134         
       
  1135     // Remove all affected nodes
       
  1136     TInt c( affectedNodes.Count() ); 
       
  1137     if( c )
       
  1138         {
       
  1139         for(TInt i=0; i<c; ++i )
       
  1140             {
       
  1141             // FYI:
       
  1142             // Child nodes are always inserted before their parents
       
  1143             // Otherwise this will ASSERT
       
  1144             RemoveNode(affectedNodes[i]);
       
  1145             }
       
  1146         }
       
  1147     
       
  1148     CleanupStack::PopAndDestroy( &affectedNodes );
       
  1149     }
       
  1150 
       
  1151 // ----------------------------------------------------------------------------
       
  1152 // CMPXCollectionCache::CMPXCollectionCache
       
  1153 // ----------------------------------------------------------------------------
       
  1154 //
       
  1155 CMPXCollectionCache::CMPXCollectionCache(
       
  1156     TInt aMaximumSizeRatio ) :
       
  1157     iMaximumSizeRatio( aMaximumSizeRatio )
       
  1158     {
       
  1159     MPX_FUNC("CMPXCollectionCache::CMPXCollectionCache");
       
  1160     }
       
  1161 
       
  1162 // ----------------------------------------------------------------------------
       
  1163 // CMPXCollectionCache::ConstructL
       
  1164 // ----------------------------------------------------------------------------
       
  1165 //
       
  1166 void CMPXCollectionCache::ConstructL()
       
  1167     {
       
  1168     MPX_FUNC("CMPXCollectionCache::ConstructL");
       
  1169     iRoot = CMPXCollectionCacheNode::NewL(KMPXRootNodeId);
       
  1170     }
       
  1171 
       
  1172 // ----------------------------------------------------------------------------
       
  1173 // CMPXCollectionCache::NodeFromPathL
       
  1174 // ----------------------------------------------------------------------------
       
  1175 //
       
  1176 CMPXCollectionCacheNode* CMPXCollectionCache::NodeFromPathL(
       
  1177     const CMPXCollectionPath& aPath,
       
  1178     TBool aCreateNodes /* = EFalse */)
       
  1179     {
       
  1180     MPX_FUNC("CMPXCollectionCache::NodeFromPathL");
       
  1181 
       
  1182     CMPXCollectionCacheNode* crtNode(iRoot);
       
  1183 
       
  1184     TInt count(aPath.Levels());
       
  1185     for (TInt level = 0; level < count; ++level)
       
  1186         {
       
  1187         TMPXItemId id = aPath.Id(level);
       
  1188         CMPXCollectionCacheNode* childNode = crtNode->GetChild(id);
       
  1189         if (!childNode)
       
  1190             {
       
  1191             if (aCreateNodes)
       
  1192                 {
       
  1193                 // create the child node and add it
       
  1194                 childNode = CMPXCollectionCacheNode::NewL(id);
       
  1195                 CleanupStack::PushL(childNode);
       
  1196                 crtNode->AddChildL(childNode);	// ownership transferred
       
  1197                 CleanupStack::Pop(childNode);
       
  1198                 }
       
  1199             else
       
  1200                 {
       
  1201                 // exit and return NULL
       
  1202                 crtNode = NULL;
       
  1203                 break;
       
  1204                 }
       
  1205             }
       
  1206 
       
  1207         // move to the next level
       
  1208         crtNode = childNode;
       
  1209         }
       
  1210 
       
  1211     return crtNode;
       
  1212     }
       
  1213 
       
  1214 // ----------------------------------------------------------------------------
       
  1215 // CMPXCollectionCache::RemoveNode
       
  1216 // ----------------------------------------------------------------------------
       
  1217 //
       
  1218 void CMPXCollectionCache::RemoveNode(
       
  1219     CMPXCollectionCacheNode* aNode)
       
  1220     {
       
  1221     MPX_FUNC("CMPXCollectionCache::RemoveNode");
       
  1222     MPX_ASSERT( aNode );
       
  1223 
       
  1224 
       
  1225     // remove from parent node
       
  1226     aNode->iParent->RemoveChild(*aNode);
       
  1227 
       
  1228     // delete the node and its children
       
  1229     delete aNode;
       
  1230     }
       
  1231 
       
  1232 // ----------------------------------------------------------------------------
       
  1233 // CMPXCollectionCache::ManageCacheSizeL
       
  1234 // ----------------------------------------------------------------------------
       
  1235 //
       
  1236 TBool CMPXCollectionCache::ManageCacheSizeL()
       
  1237     {
       
  1238     MPX_FUNC("CMPXCollectionCache::ManageCacheSizeL");
       
  1239     
       
  1240     TBool addToCache(ETrue);
       
  1241     TInt totalMemory(0);
       
  1242     TInt usedMemory(0);
       
  1243     CMPXMedia::HeapMemoryInfoL( totalMemory, usedMemory );
       
  1244     TInt ratio( (usedMemory * 100) / totalMemory );
       
  1245     MPX_DEBUG4("ManageCacheSizeL : ratio=%d, total=%d, used=%d",ratio,totalMemory,usedMemory);
       
  1246     if(ratio > iMaximumSizeRatio)
       
  1247         {
       
  1248         // clear cache to free all memory we can
       
  1249         Reset();
       
  1250         addToCache = EFalse;
       
  1251         }
       
  1252         
       
  1253     return addToCache;
       
  1254     }
       
  1255 
       
  1256 
       
  1257 #ifdef _DEBUG
       
  1258 
       
  1259 // ----------------------------------------------------------------------------
       
  1260 // CMPXCollectionCache::PrintTree
       
  1261 // ----------------------------------------------------------------------------
       
  1262 //
       
  1263 void CMPXCollectionCache::PrintTree( TBool aPrintAtts /*= EFalse */ )
       
  1264     {
       
  1265     MPX_FUNC("CMPXCollectionCache::PrintTree");
       
  1266     iRoot->PrintNode( ETrue, aPrintAtts);
       
  1267     }
       
  1268 
       
  1269 #endif
       
  1270 
       
  1271 // End of file