|
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 |