|
1 /* |
|
2 * Copyright (c) 2006 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 CNcdNodeCacheCleaner class |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "ncdnodecachecleaner.h" |
|
20 |
|
21 #include "ncdnodeidentifierutils.h" |
|
22 #include "ncdnodemanager.h" |
|
23 #include "ncdnodedbmanager.h" |
|
24 #include "ncdnodefactory.h" |
|
25 #include "ncdnodeidentifiereditor.h" |
|
26 #include "ncdnodeimpl.h" |
|
27 #include "ncdnodefolder.h" |
|
28 #include "ncdrootnode.h" |
|
29 #include "ncdnodemetadataimpl.h" |
|
30 #include "ncdnodelink.h" |
|
31 #include "ncdnodeiconimpl.h" |
|
32 #include "ncdnodescreenshotimpl.h" |
|
33 #include "ncdnodeidentifier.h" |
|
34 #include "ncdchildentity.h" |
|
35 #include "catalogsconstants.h" |
|
36 #include "ncdproviderdefines.h" |
|
37 #include "catalogsutils.h" |
|
38 #include "ncdgeneralmanager.h" |
|
39 |
|
40 #include "catalogsdebug.h" |
|
41 |
|
42 |
|
43 |
|
44 // Uncomment this if the node cache cleaner should be turned off. |
|
45 // For example, when debugging other functionalities. |
|
46 //#define NCD_NODE_CACHE_CLEANER_TURN_OFF |
|
47 |
|
48 |
|
49 #ifdef CATALOGS_BUILD_CONFIG_DEBUG |
|
50 // Uncomment this if the array prints should be printed when the |
|
51 // debug mode is on. This is set optional because the array print |
|
52 // may take a long time when data is written into the log file. |
|
53 //#define NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
54 #endif |
|
55 |
|
56 |
|
57 // These priority values are used for this active object. |
|
58 // The default value is used when normal cleaning is done |
|
59 const CActive::TPriority KDefaultCleaningPriority( CActive::EPriorityIdle ); |
|
60 // This priority value is used if the database size has been exceeded |
|
61 // and the cleaning should be done with the higher priority |
|
62 const CActive::TPriority KIncreasedCleaningPriority( CActive::EPriorityLow ); |
|
63 // This priority value is used if the database size has been exceeded |
|
64 // too much and the cleaning should be done with really high priority. |
|
65 // This will slow down the other actions even more because cleaning |
|
66 // takes more time. |
|
67 const CActive::TPriority KMaxCleaningPriority( CActive::EPriorityStandard ); |
|
68 |
|
69 // The max db size value is divided by this number to get the |
|
70 // value for the limit until which the db is freed after max size |
|
71 // has been reached and cleaning started. |
|
72 const TInt KMaxSizeDivider( 2 ); |
|
73 |
|
74 // If the db size is over double the accepted db size, then the max cleaning |
|
75 // priority should be used. Because most likely the lower priority does not work |
|
76 // efficiently enough |
|
77 const TInt KMaxDbSizeRatio( 2 ); |
|
78 |
|
79 // The checking of the database should be done at least in some time intervals |
|
80 // even if the db size has not been exceeded. |
|
81 const TTimeIntervalMinutes KCheckPeriod( 60 ); |
|
82 |
|
83 |
|
84 |
|
85 CNcdNodeCacheCleaner* CNcdNodeCacheCleaner::NewL( CNcdGeneralManager& aGeneralManager, |
|
86 CNcdNodeDbManager& aNodeDbManager, |
|
87 TInt aDbDefaultMaxSize, |
|
88 CNcdNodeFactory& aNodeFactory ) |
|
89 { |
|
90 CNcdNodeCacheCleaner* self = |
|
91 CNcdNodeCacheCleaner::NewLC( aGeneralManager, |
|
92 aNodeDbManager, |
|
93 aDbDefaultMaxSize, |
|
94 aNodeFactory ); |
|
95 CleanupStack::Pop( self ); |
|
96 return self; |
|
97 } |
|
98 |
|
99 CNcdNodeCacheCleaner* CNcdNodeCacheCleaner::NewLC( CNcdGeneralManager& aGeneralManager, |
|
100 CNcdNodeDbManager& aNodeDbManager, |
|
101 TInt aDbDefaultMaxSize, |
|
102 CNcdNodeFactory& aNodeFactory ) |
|
103 { |
|
104 CNcdNodeCacheCleaner* self = |
|
105 new( ELeave ) CNcdNodeCacheCleaner( aGeneralManager, |
|
106 aNodeDbManager, |
|
107 aDbDefaultMaxSize, |
|
108 aNodeFactory ); |
|
109 CleanupStack::PushL( self ); |
|
110 self->ConstructL(); |
|
111 return self; |
|
112 } |
|
113 |
|
114 |
|
115 |
|
116 CNcdNodeCacheCleaner::CNcdNodeCacheCleaner( CNcdGeneralManager& aGeneralManager, |
|
117 CNcdNodeDbManager& aNodeDbManager, |
|
118 TInt aDbDefaultMaxSize, |
|
119 CNcdNodeFactory& aNodeFactory ) |
|
120 : CActive( KDefaultCleaningPriority ), |
|
121 iGeneralManager( aGeneralManager ), |
|
122 iNodeManager( aGeneralManager.NodeManager() ), |
|
123 iNodeDbManager( aNodeDbManager ), |
|
124 iDbMaxSize( aDbDefaultMaxSize ), |
|
125 iNodeFactory( aNodeFactory ), |
|
126 // EFalse by default so that we don't clean anything even in error situations |
|
127 // for clients that don't allow it |
|
128 iAllowCleaning( EFalse ), |
|
129 iIncreasePriority( KDefaultCleaningPriority ), |
|
130 iLastCleanupTime( 0 ) |
|
131 { |
|
132 } |
|
133 |
|
134 |
|
135 void CNcdNodeCacheCleaner::ConstructL() |
|
136 { |
|
137 // These values have to be set. |
|
138 |
|
139 // These types will be removed from the db. |
|
140 |
|
141 // iNodeCleanupTypes are used to search the node items from db. |
|
142 // This array is only for node type. So, it contains only one value. |
|
143 iNodeCleanupTypes.AppendL( NcdNodeClassIds::ENcdNode ); |
|
144 |
|
145 // Meta cleanup types are also removed from the db. |
|
146 // These types use the metadata identifier to remove the items |
|
147 // from db |
|
148 iMetaCleanupTypes.AppendL( NcdNodeClassIds::ENcdMetaData ); |
|
149 |
|
150 // These types should be permanent info |
|
151 // or not to be removed by this cleaner for some other reason. |
|
152 // Uncomment these if specifications change. |
|
153 //iMetaCleanupTypes.Append( NcdNodeClassIds::ENcdNodeUserData ); |
|
154 //iMetaCleanupTypes.Append( NcdNodeClassIds::ENcdSubscriptionsData ); |
|
155 |
|
156 |
|
157 // Special cleanup types are removed from the db. |
|
158 // But node or metadata ids cannot be directly used for these. |
|
159 // They require special handling to get the right ids. |
|
160 iIconCleanupTypes.AppendL( NcdNodeClassIds::ENcdIconData ); |
|
161 |
|
162 iScreenshotCleanupTypes.AppendL( NcdNodeClassIds::ENcdScreenshotData ); |
|
163 |
|
164 |
|
165 // These namespaces should not be cleaned by this cleaner |
|
166 iDoNotCleanNameSpaces = new(ELeave) CPtrCArray( KListGranularity ); |
|
167 iDoNotCleanNameSpaces->AppendL( |
|
168 NcdProviderDefines::KDownloadNamespace() ); |
|
169 iDoNotCleanNameSpaces->AppendL( |
|
170 NcdProviderDefines::KSubscriptionNamespace() ); |
|
171 iDoNotCleanNameSpaces->AppendL( |
|
172 NcdProviderDefines::KPreviewStorageNamespace() ); |
|
173 |
|
174 // Because this is an active object, we need to inform |
|
175 // scheduler about it. |
|
176 CActiveScheduler::Add( this ); |
|
177 } |
|
178 |
|
179 |
|
180 CNcdNodeCacheCleaner::~CNcdNodeCacheCleaner() |
|
181 { |
|
182 DLTRACEIN(("")); |
|
183 |
|
184 // It is always safe to call Cancel for active object |
|
185 // when destructor is called. |
|
186 Cancel(); |
|
187 |
|
188 // This object is automatically removed from the active scheduler when |
|
189 // this object is deleted. |
|
190 |
|
191 // Delete member variables that are owned by this class object here. |
|
192 |
|
193 iNodeCleanupTypes.Reset(); |
|
194 iMetaCleanupTypes.Reset(); |
|
195 iIconCleanupTypes.Reset(); |
|
196 |
|
197 iScreenshotCleanupTypes.Reset(); |
|
198 iCleanupIdentifiers.ResetAndDestroy(); |
|
199 iAllDbStorageNodeItems.ResetAndDestroy(); |
|
200 iAllDbIconItems.ResetAndDestroy(); |
|
201 |
|
202 iAllDbScreenshotItems.ResetAndDestroy(); |
|
203 iDbMetaIdentifiers.ResetAndDestroy(); |
|
204 iWaitingIdentifiers.ResetAndDestroy(); |
|
205 iWaitingParentIdentifiers.ResetAndDestroy(); |
|
206 iDoNotRemoves.ResetAndDestroy(); |
|
207 iRootChildren.ResetAndDestroy(); |
|
208 iBundleChildren.ResetAndDestroy(); |
|
209 |
|
210 // Notice that this delete also deletes the objects owned by the array. |
|
211 delete iDoNotCleanNameSpaces; |
|
212 |
|
213 DLTRACEOUT(("")); |
|
214 } |
|
215 |
|
216 |
|
217 TInt CNcdNodeCacheCleaner::NodeIdentifierArraySortById( const CNcdNodeIdentifier& aNodeId1, |
|
218 const CNcdNodeIdentifier& aNodeId2 ) |
|
219 { |
|
220 //DLTRACEIN(("")); |
|
221 |
|
222 TInt depth1( 0 ); |
|
223 TInt depth2( 0 ); |
|
224 TInt trapError1( KErrNone ); |
|
225 TInt trapError2( KErrNone ); |
|
226 |
|
227 TRAP( trapError1, depth1 = NcdNodeIdentifierEditor::NodeDepthL( aNodeId1 ) ); |
|
228 TRAP( trapError2, depth2 = NcdNodeIdentifierEditor::NodeDepthL( aNodeId2 ) ); |
|
229 |
|
230 // Decide the order according to the depth. If the identifier is not |
|
231 // an actual nodeidentifier. Then insert it to the beginning of the array |
|
232 // and sort those identifiers by their lengths. |
|
233 |
|
234 if ( trapError1 == KErrNone && trapError2 == KErrNone ) |
|
235 { |
|
236 // Both of the given identifiers were for the node. |
|
237 |
|
238 // This function returns zero if depths are equal and lengths are equal. |
|
239 TInt order( depth1 - depth2 ); |
|
240 if ( depth1 == depth2 ) |
|
241 { |
|
242 // Depths are equal. So, check if the id lengths differ. |
|
243 // If nodeid1 is shorter, then it should be first in the array. |
|
244 // If they are equal length then the order does not matter. |
|
245 // If the node1 is longer, then node2 should be first. |
|
246 order = aNodeId1.NodeId().Length() - aNodeId2.NodeId().Length(); |
|
247 } |
|
248 |
|
249 // Negative number if depth1 is smaller. |
|
250 // Positive number if id1 is greater. |
|
251 return order; |
|
252 } |
|
253 else if ( trapError1 != KErrNone && trapError2 != KErrNone ) |
|
254 { |
|
255 // Because neither was not a node, use the id length to get the |
|
256 // order. This way the shortest will be the first one etc. |
|
257 DLERROR(("Neither was node")); |
|
258 DASSERT( trapError1 == KErrArgument ); |
|
259 DASSERT( trapError2 == KErrArgument ); |
|
260 |
|
261 return aNodeId1.NodeId().Length() - aNodeId2.NodeId().Length(); |
|
262 } |
|
263 else if ( trapError1 != KErrNone ) |
|
264 { |
|
265 // Here we should get only the KErrArgument that informs that the |
|
266 // aNodeId1 was not an actual node id. It is most likely some metadata id. |
|
267 // Insert these in the beginning of the array. So, return negative number |
|
268 DLERROR(("aNodeId1 not node")); |
|
269 DASSERT( trapError1 == KErrArgument ); |
|
270 return -1; |
|
271 } |
|
272 else |
|
273 { |
|
274 DLERROR(("aNodeId2 not node")); |
|
275 // Here we should get only the KErrArgument that informs that the |
|
276 // aNodeId2 was not an actual node id. It is most likely some metadata id. |
|
277 // Insert these in the beginning of the array. So, return positive number |
|
278 DASSERT( trapError2 == KErrArgument ); |
|
279 return 1; |
|
280 } |
|
281 } |
|
282 |
|
283 |
|
284 const TUid& CNcdNodeCacheCleaner::ClientUid() const |
|
285 { |
|
286 return iGeneralManager.FamilyId(); |
|
287 } |
|
288 |
|
289 |
|
290 CNcdNodeCacheCleaner::TCleanupState CNcdNodeCacheCleaner::CleanupState() const |
|
291 { |
|
292 return iCleanupState; |
|
293 } |
|
294 |
|
295 |
|
296 void CNcdNodeCacheCleaner::SetAllowCleaning( TBool aAllow ) |
|
297 { |
|
298 DLTRACEIN(("")); |
|
299 if ( aAllow != AllowCleaning() |
|
300 && !aAllow ) |
|
301 { |
|
302 DLINFO(("Cancel on going operation because cleaning is not allowed anymore.")) |
|
303 Cancel(); |
|
304 } |
|
305 iAllowCleaning = aAllow; |
|
306 } |
|
307 |
|
308 |
|
309 TBool CNcdNodeCacheCleaner::AllowCleaning() const |
|
310 { |
|
311 return iAllowCleaning; |
|
312 } |
|
313 |
|
314 |
|
315 void CNcdNodeCacheCleaner::StartCleanupL() |
|
316 { |
|
317 DLTRACEIN(("")); |
|
318 |
|
319 // Set the last cleanup time here. So, next automatic start will |
|
320 // occure after the specified period. |
|
321 iLastCleanupTime.HomeTime(); |
|
322 |
|
323 #ifdef NCD_NODE_CACHE_CLEANER_TURN_OFF |
|
324 // Nothing to do here. Because cleaning should not be done. |
|
325 DLWARNING(("*** CNcdNodeCacheCleaner turned off ***")); |
|
326 #warning *** CNcdNodeCacheCleaner turned off *** |
|
327 return; |
|
328 #endif |
|
329 |
|
330 if ( !AllowCleaning() ) |
|
331 { |
|
332 DLINFO(("Cleaning is not allowed.")); |
|
333 return; |
|
334 } |
|
335 |
|
336 if ( CleanupState() != ENotStarted |
|
337 || IsActive() ) |
|
338 { |
|
339 DLINFO(("Cleaning already started")); |
|
340 return; |
|
341 } |
|
342 |
|
343 if ( iResetPriority ) |
|
344 { |
|
345 // The priority may have been increased before. |
|
346 // But it has been marked to be resetted when possible. |
|
347 // So, reset it here. We come here only if Cancel was |
|
348 // called when the object was active. |
|
349 SetPriority( KDefaultCleaningPriority ); |
|
350 iResetPriority = EFalse; |
|
351 } |
|
352 |
|
353 // Update the node items list. |
|
354 // This is an initial list that will be used when the nodes are examined. |
|
355 // The node items list should not be updated anywhere else but here or |
|
356 // in the start clean excess function. If the array is updated somewhere else, it |
|
357 // may result an infinite loop if some deepest nodes cannot be removed when |
|
358 // excess cleaning is done and those nodes are in the end of the list all the time. |
|
359 // Notice, that it does not matter if all the nodes are not check this time. They |
|
360 // will be checked next time cleaning is started. Also, if some nodes are missing |
|
361 // in the list, wrong nodes will not be deleted because parent and child checks |
|
362 // are done by using the other array such as do not remove and wait arrays. |
|
363 SetAllDbStorageNodeItemsL(); |
|
364 |
|
365 // Cleaning special cases is the first thing to do when cleanup is started. |
|
366 iCleanupState = ECleaningSpecialCases; |
|
367 |
|
368 // Mark this active object to be ready for action. |
|
369 // Instead of using some other class object to do the job, |
|
370 // this active object handles everything itself. New job |
|
371 // is started everytime when the RunL is called until there is |
|
372 // nothing to be done. Or, until user cancels or stops the action. |
|
373 iStatus = KRequestPending; |
|
374 |
|
375 // Let the active object know that RunL can be called when the |
|
376 // action is completed. |
|
377 SetActive(); |
|
378 |
|
379 // Because there is not anything special to be done here. |
|
380 // Set the action complete. So, the RunL will be called. |
|
381 TRequestStatus* ptrStatus = &iStatus; |
|
382 User::RequestComplete( ptrStatus, KErrNone ); |
|
383 |
|
384 DLTRACEOUT(("")); |
|
385 } |
|
386 |
|
387 |
|
388 void CNcdNodeCacheCleaner::StopCleanup() |
|
389 { |
|
390 DLTRACEIN(("")); |
|
391 |
|
392 if ( CleanupState() != ENotStarted |
|
393 || IsActive() ) |
|
394 { |
|
395 DLINFO(("Stop cleanup")); |
|
396 Cancel(); |
|
397 } |
|
398 |
|
399 DLTRACEOUT(("")); |
|
400 } |
|
401 |
|
402 |
|
403 void CNcdNodeCacheCleaner::CheckDbSizeL() |
|
404 { |
|
405 DLTRACEIN(("")); |
|
406 |
|
407 // If the db size has been exceeded, then |
|
408 // start the cleaning operation. |
|
409 // This function may be called for example |
|
410 // when new nodes have been added to the db. |
|
411 TInt dbSize( |
|
412 NodeDbManager().StorageSizeL( ClientUid(), |
|
413 *iDoNotCleanNameSpaces ) ); |
|
414 |
|
415 TTime currentTime; |
|
416 currentTime.HomeTime(); |
|
417 TBool timePassed( EFalse ); |
|
418 if ( iLastCleanupTime + KCheckPeriod < currentTime ) |
|
419 { |
|
420 timePassed = ETrue; |
|
421 } |
|
422 |
|
423 // Start cleaning if the database size is too large |
|
424 // or if it is too long time from the last cleanup. |
|
425 if ( DbMaxSize() < dbSize ) |
|
426 { |
|
427 DLINFO(("Too much data in db: %d", dbSize)); |
|
428 |
|
429 // Because the db size has been exceeded we want to clean |
|
430 // the db with higher priority than usually. |
|
431 // When the cleanup finishes, the priority should be set back |
|
432 // to lower level. |
|
433 if ( IsActive() ) |
|
434 { |
|
435 if ( DbMaxSize() * KMaxDbSizeRatio < dbSize ) |
|
436 { |
|
437 DLINFO(("Highest priority should be used db size is way too big")); |
|
438 // Set the priority to max, the next time RunL is called |
|
439 // because the cleaner is not doing its work efficiently enough |
|
440 iIncreasePriority = KMaxCleaningPriority; |
|
441 } |
|
442 else |
|
443 { |
|
444 DLINFO(("Increased priority should be used")); |
|
445 // Set the priority higher, the next time |
|
446 // RunL is called. The db size is too large but does not |
|
447 // exceed the "panic" level. |
|
448 iIncreasePriority = KIncreasedCleaningPriority; |
|
449 } |
|
450 } |
|
451 else if ( DbMaxSize() * KMaxDbSizeRatio < dbSize ) |
|
452 { |
|
453 DLINFO(("Not active. Max priority set")); |
|
454 SetPriority( KMaxCleaningPriority ); |
|
455 } |
|
456 else |
|
457 { |
|
458 DLINFO(("Not active. Increased priority set")); |
|
459 SetPriority( KIncreasedCleaningPriority ); |
|
460 } |
|
461 |
|
462 // To be sure that the cleanup does not reset the priority. |
|
463 // No need to reset it because new values have been given above. |
|
464 iResetPriority = EFalse; |
|
465 |
|
466 // Start the actual cleaning. |
|
467 StartCleanupL(); |
|
468 } |
|
469 else if ( timePassed ) |
|
470 { |
|
471 DLINFO(("Time passed")); |
|
472 // Start the actual cleaning but no need to increase the priority. |
|
473 StartCleanupL(); |
|
474 } |
|
475 |
|
476 DLTRACEOUT(("")); |
|
477 } |
|
478 |
|
479 |
|
480 void CNcdNodeCacheCleaner::AddCleanupIdentifiersL( const RPointerArray<CNcdNodeIdentifier>& aIdentifiers ) |
|
481 { |
|
482 DLTRACEIN(("")); |
|
483 |
|
484 for ( TInt i = 0; i < aIdentifiers.Count(); ++i ) |
|
485 { |
|
486 AddCleanupIdentifierL( *aIdentifiers[ i ] ); |
|
487 } |
|
488 |
|
489 DLTRACEOUT(("")); |
|
490 } |
|
491 |
|
492 void CNcdNodeCacheCleaner::AddCleanupIdentifierL( const CNcdNodeIdentifier& aIdentifier ) |
|
493 { |
|
494 DLTRACEIN(("")); |
|
495 DLNODEID(( aIdentifier )); |
|
496 if ( ContainsIdentifier( aIdentifier, iDoNotRemoves ) ) |
|
497 { |
|
498 // Do not remove list already contains the given identifier. |
|
499 // So, insert the given identifier to the wait list. |
|
500 // Notice that identifier should be left also into the do not remove list. |
|
501 AddIdentifierL( aIdentifier, iWaitingIdentifiers ); |
|
502 } |
|
503 else if ( !NcdNodeIdentifierUtils::ContainsIdentifier( |
|
504 aIdentifier, iWaitingIdentifiers ) && |
|
505 !NcdNodeIdentifierUtils::ContainsIdentifier( |
|
506 aIdentifier, iWaitingParentIdentifiers ) ) |
|
507 { |
|
508 // Just insert the given identifier into the cleanup list unless |
|
509 // it already existed in some waiting array or in do not remove list. |
|
510 AddIdentifierL( aIdentifier, iCleanupIdentifiers ); |
|
511 } |
|
512 |
|
513 // No need to check the waiting parents, because it will be checked when items |
|
514 // are going to be removed. |
|
515 |
|
516 DLTRACEOUT(("")); |
|
517 } |
|
518 |
|
519 |
|
520 void CNcdNodeCacheCleaner::RemoveCleanupIdentifiers( const RPointerArray<CNcdNodeIdentifier>& aIdentifiers ) |
|
521 { |
|
522 DLTRACEIN(("")); |
|
523 |
|
524 for ( TInt i = 0; i < aIdentifiers.Count(); ++i ) |
|
525 { |
|
526 RemoveCleanupIdentifier( *aIdentifiers[ i ] ); |
|
527 } |
|
528 |
|
529 DLTRACEOUT(("")); |
|
530 } |
|
531 |
|
532 void CNcdNodeCacheCleaner::RemoveCleanupIdentifier( const CNcdNodeIdentifier& aIdentifier ) |
|
533 { |
|
534 DLTRACEIN(("")); |
|
535 |
|
536 // If wait list contains the given identifier. |
|
537 // So, remove the given identifier from the wait list. |
|
538 RemoveIdentifier( aIdentifier, iWaitingIdentifiers ); |
|
539 |
|
540 // If wait list contains the given identifier. |
|
541 // So, remove the given identifier from the wait list. |
|
542 RemoveIdentifier( aIdentifier, iWaitingParentIdentifiers ); |
|
543 |
|
544 // Remove the given identifier from cleanup list |
|
545 RemoveIdentifier( aIdentifier, iCleanupIdentifiers ); |
|
546 |
|
547 DLTRACEOUT(("")); |
|
548 } |
|
549 |
|
550 |
|
551 void CNcdNodeCacheCleaner::AddDoNotRemoveIdentifiersL( |
|
552 const RPointerArray<CNcdNodeIdentifier>& aIdentifiers, |
|
553 TBool aCanRemoveParent ) |
|
554 { |
|
555 DLTRACEIN(("")); |
|
556 |
|
557 // Check if the identifiers should be inserted into the waiting or do not remove |
|
558 // array. |
|
559 for ( TInt i = 0; i < aIdentifiers.Count(); ++i ) |
|
560 { |
|
561 AddDoNotRemoveIdentifierL( *aIdentifiers[ i ], aCanRemoveParent ); |
|
562 } |
|
563 |
|
564 DLTRACEOUT(("")); |
|
565 } |
|
566 |
|
567 void CNcdNodeCacheCleaner::AddDoNotRemoveIdentifierL( |
|
568 const CNcdNodeIdentifier& aIdentifier, |
|
569 TBool aCanRemoveParent ) |
|
570 { |
|
571 DLTRACEIN(("")); |
|
572 DLNODEID(( aIdentifier )); |
|
573 |
|
574 if ( RemoveIdentifier( aIdentifier, iCleanupIdentifiers ) ) |
|
575 { |
|
576 // Cleanup list already contained the given identifier. |
|
577 // So, insert the given identifier to the wait list. |
|
578 AddIdentifierL( aIdentifier, iWaitingIdentifiers ); |
|
579 } |
|
580 |
|
581 // Insert the given identifier into the do not remove list. |
|
582 // It should be ther until RemoveDoNotRemoveIdentifiers is used. |
|
583 // So, even if identifier is in waiting list it will be also, |
|
584 // in the do not remove list. |
|
585 |
|
586 // Compare given identifier to the identifiers in the array. |
|
587 TInt i = 0; |
|
588 for ( ; i < iDoNotRemoves.Count(); ++i ) |
|
589 { |
|
590 if ( iDoNotRemoves[ i ]->Key().Equals( aIdentifier ) ) |
|
591 { |
|
592 // Flag is only updated if it goes from EFalse -> ETrue |
|
593 if ( aCanRemoveParent ) |
|
594 { |
|
595 DLTRACE(( _L("Updating parent removal flag for: %S"), |
|
596 &iDoNotRemoves[ i ]->Key().NodeId() )); |
|
597 // The given identifier was found from the array |
|
598 // update |
|
599 iDoNotRemoves[ i ]->SetValue( ETrue ); |
|
600 } |
|
601 break; |
|
602 } |
|
603 } |
|
604 |
|
605 |
|
606 if ( i == iDoNotRemoves.Count() ) |
|
607 { |
|
608 DLTRACE(("Adding a non-removable identifier")); |
|
609 CNcdNodeIdentifier* id = CNcdNodeIdentifier::NewLC( aIdentifier ); |
|
610 // ownership is transferred |
|
611 CDoNotRemoveIdentifier* pair = new ( ELeave ) |
|
612 CDoNotRemoveIdentifier( id, aCanRemoveParent ); |
|
613 CleanupStack::Pop( id ); |
|
614 |
|
615 CleanupStack::PushL( pair ); |
|
616 iDoNotRemoves.AppendL( pair ); |
|
617 CleanupStack::Pop( pair ); |
|
618 } |
|
619 |
|
620 DLTRACEOUT(("")); |
|
621 } |
|
622 |
|
623 |
|
624 void CNcdNodeCacheCleaner::RemoveDoNotRemoveIdentifiersL( const RPointerArray<CNcdNodeIdentifier>& aIdentifiers ) |
|
625 { |
|
626 DLTRACEIN(("")); |
|
627 |
|
628 // Check if the identifiers should be moved from the waiting back to the |
|
629 // cleanup array and remove identifier from the do not remove array. |
|
630 for ( TInt i = 0; i < aIdentifiers.Count(); ++i ) |
|
631 { |
|
632 RemoveDoNotRemoveIdentifierL( *aIdentifiers[ i ] ); |
|
633 } |
|
634 |
|
635 DLTRACEOUT(("")); |
|
636 } |
|
637 |
|
638 void CNcdNodeCacheCleaner::RemoveDoNotRemoveIdentifierL( |
|
639 const CNcdNodeIdentifier& aIdentifier, |
|
640 TBool aForceRemove ) |
|
641 { |
|
642 DLTRACEIN(("")); |
|
643 DLNODEID(( aIdentifier )); |
|
644 |
|
645 TBool waitingRemoved( |
|
646 RemoveIdentifier( aIdentifier, iWaitingIdentifiers ) ); |
|
647 TBool waitingParentRemoved( |
|
648 RemoveIdentifier( aIdentifier, iWaitingParentIdentifiers ) ); |
|
649 |
|
650 if ( waitingRemoved || waitingParentRemoved ) |
|
651 { |
|
652 // Wait list contained the given identifier. |
|
653 // So, move the given identifier back to the cleanup list. |
|
654 AddIdentifierL( aIdentifier, iCleanupIdentifiers ); |
|
655 } |
|
656 |
|
657 RemoveIdentifier( aIdentifier, iDoNotRemoves, aForceRemove ); |
|
658 |
|
659 DLTRACEOUT(("")); |
|
660 } |
|
661 |
|
662 |
|
663 TInt CNcdNodeCacheCleaner::DbMaxSize() const |
|
664 { |
|
665 DLTRACEIN(("")); |
|
666 return iDbMaxSize; |
|
667 } |
|
668 |
|
669 |
|
670 void CNcdNodeCacheCleaner::SetDbMaxSize( const TInt aDbMaxSize ) |
|
671 { |
|
672 DLTRACEIN(("")); |
|
673 iDbMaxSize = aDbMaxSize; |
|
674 } |
|
675 |
|
676 |
|
677 void CNcdNodeCacheCleaner::ForceCleanupL() |
|
678 { |
|
679 DLTRACEIN(("")); |
|
680 |
|
681 // Print array debug infos into the log file |
|
682 #ifdef NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
683 DLINFO(("iDoNotRemoves array:")); |
|
684 ArrayDebugPrint( iDoNotRemoves ); |
|
685 |
|
686 DLINFO(("iWaitingIdentifiers array:")); |
|
687 ArrayDebugPrint( iWaitingIdentifiers ); |
|
688 |
|
689 DLINFO(("iWaitingParentIdentifiers array:")); |
|
690 ArrayDebugPrint( iWaitingParentIdentifiers ); |
|
691 #endif |
|
692 |
|
693 |
|
694 // iDoNotRemoves array is not reseted here. So, those nodes will not be deleted even here. |
|
695 // This way some nodes can be saved from deletion. But, the nodes that are waiting to |
|
696 // be deleted are forced to be deleted now. |
|
697 |
|
698 // Move waiting identifiers to the cleanup array. |
|
699 AddIdentifiersL( iWaitingIdentifiers, iCleanupIdentifiers ); |
|
700 iWaitingIdentifiers.ResetAndDestroy(); |
|
701 |
|
702 AddIdentifiersL( iWaitingParentIdentifiers, iCleanupIdentifiers ); |
|
703 iWaitingParentIdentifiers.ResetAndDestroy(); |
|
704 |
|
705 // Clean the items that are in the cleanup array from db. |
|
706 HandleCleaningL(); |
|
707 |
|
708 DLTRACEOUT(("")); |
|
709 } |
|
710 |
|
711 |
|
712 void CNcdNodeCacheCleaner::HandleCleaningL() |
|
713 { |
|
714 DLTRACEIN(("")); |
|
715 |
|
716 // Asynchronous operations have to be stopped before |
|
717 // starting synchronous cleaning. Otherwise the |
|
718 // asynchronous cleaning may work wrong later. |
|
719 Cancel(); |
|
720 |
|
721 // Update the arrays and handle cleaning. |
|
722 // Thde node array will be emptied when this is done. |
|
723 HandleCleaningL( ETrue, ETrue ); |
|
724 |
|
725 DLTRACEOUT(("")); |
|
726 } |
|
727 |
|
728 |
|
729 void CNcdNodeCacheCleaner::HandleCleaningL( TBool aReloadNodeList, TBool aResetNodeList ) |
|
730 { |
|
731 DLTRACEIN(("")); |
|
732 |
|
733 #ifdef NCD_NODE_CACHE_CLEANER_TURN_OFF |
|
734 // Nothing to do here. Because cleaning should not be done. |
|
735 DLWARNING(("*** CNcdNodeCacheCleaner turned off ***")); |
|
736 #warning *** CNcdNodeCacheCleaner turned off *** |
|
737 return; |
|
738 #endif |
|
739 |
|
740 if ( !AllowCleaning() ) |
|
741 { |
|
742 DLINFO(("Cleaning is not allowed.")); |
|
743 return; |
|
744 } |
|
745 |
|
746 // Clean all the nodes from the list. |
|
747 // Notice that we only delete the nodes here. |
|
748 // The metadata and metadata related |
|
749 // data will be removed later, when this cleaner checks |
|
750 // if they are left hanging and |
|
751 // do not belong to any node anymore. |
|
752 |
|
753 // Print array debug info into the log file |
|
754 #ifdef NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
755 DLINFO(("iCleanupIdentifiers array before parent and child check:")); |
|
756 ArrayDebugPrint( iCleanupIdentifiers ); |
|
757 #endif |
|
758 |
|
759 if ( aReloadNodeList ) |
|
760 { |
|
761 DLINFO(("Reload node list")); |
|
762 // The caller may require the list to be updated. |
|
763 // So, make sure that all the necessary ids are in the |
|
764 // list. It may also be so, that the db is empty. |
|
765 // This check is required for example if some other class wants to |
|
766 // clean some nodes. |
|
767 SetAllDbStorageNodeItemsL(); |
|
768 } |
|
769 |
|
770 if ( iAllDbStorageNodeItems.Count() == 0 ) |
|
771 { |
|
772 // Because there are not nodeitems in the db, |
|
773 // just return. |
|
774 DLTRACEOUT(("No nodes to remove")); |
|
775 return; |
|
776 } |
|
777 |
|
778 // Because the name of the children starts with the same id |
|
779 // as the name of the parent, check that also the children |
|
780 // of the parents will be deleted, unless they are in do not remove list |
|
781 // or in the waiting list. |
|
782 AddChildrenToCleanupArrayL(); |
|
783 ParentCleaningCheckL(); |
|
784 |
|
785 // In some cases there are unremovable items in the cleanup array |
|
786 // so let's remove them |
|
787 RemoveDoNotRemovesFromCleanupArray(); |
|
788 |
|
789 DLINFO(("Remove nodes from db")); |
|
790 // Print array debug info into the log file |
|
791 #ifdef NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
792 DLINFO(("iCleanupIdentifiers array:")); |
|
793 ArrayDebugPrint( iCleanupIdentifiers ); |
|
794 #endif |
|
795 |
|
796 // Now the parents and their children are in the array. |
|
797 NodeDbManager(). |
|
798 RemoveDataFromDatabaseL( iCleanupIdentifiers, |
|
799 iNodeCleanupTypes ); |
|
800 |
|
801 // Because all the items have been marked as removable in db |
|
802 // manager, we can clear the array. |
|
803 iCleanupIdentifiers.ResetAndDestroy(); |
|
804 |
|
805 if ( aResetNodeList ) |
|
806 { |
|
807 DLINFO(("Reset node list")); |
|
808 // The list should be reseted to save some memory. |
|
809 iAllDbStorageNodeItems.ResetAndDestroy(); |
|
810 } |
|
811 |
|
812 DLTRACEOUT(("")); |
|
813 } |
|
814 |
|
815 |
|
816 void CNcdNodeCacheCleaner::DoCancel() |
|
817 { |
|
818 DLTRACEIN(("")); |
|
819 |
|
820 // Do not continue the action any more |
|
821 // because cancel was called. |
|
822 ResetState(); |
|
823 |
|
824 // Also, make sure that the active object will know that the |
|
825 // cancel is ready. If active process is going on, the status is |
|
826 // set to KRequestPending. |
|
827 |
|
828 // There is no need for additional User::RequestComplete |
|
829 // call here because DoCancel is executed only if this object is active |
|
830 // and there has always been a call to User::RequestComplete when this |
|
831 // object has been put to active state in other function calls. |
|
832 |
|
833 DLTRACEOUT(("")); |
|
834 } |
|
835 |
|
836 |
|
837 void CNcdNodeCacheCleaner::RunL() |
|
838 { |
|
839 DLTRACEIN(("")); |
|
840 |
|
841 if ( iIncreasePriority != KDefaultCleaningPriority ) |
|
842 { |
|
843 // Increase priority flag has been set. |
|
844 // So, increase the priority from idle to suggested value. |
|
845 SetPriority( iIncreasePriority ); |
|
846 iIncreasePriority = KDefaultCleaningPriority; |
|
847 } |
|
848 |
|
849 User::LeaveIfError( iStatus.Int() ); |
|
850 |
|
851 // Continue working if there is something to be done. |
|
852 switch ( iCleanupState ) |
|
853 { |
|
854 case ECleaningSpecialCases: |
|
855 DLINFO(("KErrNone cleaning specials")); |
|
856 CleanSpecialsL(); |
|
857 break; |
|
858 |
|
859 case ECleaningTemporaryNodes: |
|
860 DLINFO(("KErrNone cleaning temporary nodes")); |
|
861 CleanTemporaryNodesL(); |
|
862 break; |
|
863 |
|
864 case ECleaningHangingCases: |
|
865 DLINFO(("KErrNone cleaning hangings")); |
|
866 CleanHangingsL(); |
|
867 break; |
|
868 |
|
869 case EStartCleaningHangingSpecialCases: |
|
870 DLINFO(("KErrNone start cleaning special hangings")); |
|
871 StartCleanSpecialHangingsL(); |
|
872 break; |
|
873 |
|
874 case ECleaningHangingSpecialCases: |
|
875 DLINFO(("KErrNone cleaning special hangings")); |
|
876 CleanSpecialHangingsL(); |
|
877 break; |
|
878 |
|
879 case EFinishCleaningHangingSpecialCases: |
|
880 DLINFO(("KErrNone finish cleaning special hangings")); |
|
881 FinishCleanSpecialHangingsL(); |
|
882 break; |
|
883 |
|
884 case EStartCleaningExcess: |
|
885 DLINFO(("KErrNone start cleaning excess")); |
|
886 StartCleanExcessL(); |
|
887 break; |
|
888 |
|
889 case EStartRootChildrenCheck: |
|
890 DLINFO(("KErrNone start root children check")); |
|
891 StartRootChildrenCheckL(); |
|
892 break; |
|
893 |
|
894 case ECheckRootChildren: |
|
895 DLINFO(("KErrNone check root children")); |
|
896 CheckRootChildrenL(); |
|
897 break; |
|
898 |
|
899 case EHandleBundleChildren: |
|
900 DLINFO(("KErrNone handle bundle children")); |
|
901 HandleBundleChildrenL(); |
|
902 break; |
|
903 |
|
904 case ECleaningExpireds: |
|
905 DLINFO(("KErrNone cleaning expireds")); |
|
906 CleanExpiredsL(); |
|
907 break; |
|
908 |
|
909 case ECleaningExcess: |
|
910 DLINFO(("KErrNone cleaning excess")); |
|
911 CleanExcessL(); |
|
912 break; |
|
913 |
|
914 case EStopping: |
|
915 DLINFO(("KErrNone EStopping")); |
|
916 StoppingL(); |
|
917 break; |
|
918 |
|
919 case ENotStarted: |
|
920 DLINFO(("KErrNone ENotStarted")); |
|
921 // Nothing to do here |
|
922 break; |
|
923 |
|
924 default: |
|
925 DLERROR(("KErrNone default")); |
|
926 DASSERT( EFalse ); |
|
927 break; |
|
928 } |
|
929 |
|
930 DLTRACEOUT(("")); |
|
931 } |
|
932 |
|
933 |
|
934 TInt CNcdNodeCacheCleaner::RunError( TInt aError ) |
|
935 { |
|
936 DLTRACEIN(( "aError: %d", aError )); |
|
937 (void) aError; |
|
938 ResetState(); |
|
939 return KErrNone; |
|
940 } |
|
941 |
|
942 CNcdNodeManager& CNcdNodeCacheCleaner::NodeManager() const |
|
943 { |
|
944 return iNodeManager; |
|
945 } |
|
946 |
|
947 |
|
948 CNcdNodeDbManager& CNcdNodeCacheCleaner::NodeDbManager() const |
|
949 { |
|
950 return iNodeDbManager; |
|
951 } |
|
952 |
|
953 |
|
954 CNcdNodeFactory& CNcdNodeCacheCleaner::NodeFactory() const |
|
955 { |
|
956 return iNodeFactory; |
|
957 } |
|
958 |
|
959 |
|
960 TBool CNcdNodeCacheCleaner::ContainsIdentifier( |
|
961 const CNcdNodeIdentifier& aIdentifier, |
|
962 const RPointerArray<CDoNotRemoveIdentifier>& aTargetIdentifiers ) const |
|
963 { |
|
964 const TInt count = aTargetIdentifiers.Count(); |
|
965 // Compare given identifier to the identifiers in the array. |
|
966 for ( TInt i = 0; i < count; ++i ) |
|
967 { |
|
968 if ( aTargetIdentifiers[ i ]->Key().Equals( aIdentifier ) ) |
|
969 { |
|
970 // The given identifier was found from the array |
|
971 return ETrue; |
|
972 } |
|
973 } |
|
974 // Identifier was not found. |
|
975 return EFalse; |
|
976 } |
|
977 |
|
978 |
|
979 TBool CNcdNodeCacheCleaner::AddIdentifiersL( const RPointerArray<CNcdNodeIdentifier>& aIdentifiers, |
|
980 RPointerArray<CNcdNodeIdentifier>& aTargetArray ) |
|
981 { |
|
982 DLTRACEIN(("")); |
|
983 |
|
984 TBool targetArrayChanged( EFalse ); |
|
985 TBool identifierAdded( EFalse ); |
|
986 const TInt count = aIdentifiers.Count(); |
|
987 |
|
988 for ( TInt i = 0; i < count; ++i ) |
|
989 { |
|
990 DASSERT( aIdentifiers[ i ] != NULL ); |
|
991 |
|
992 identifierAdded = |
|
993 AddIdentifierL( *aIdentifiers[ i ], |
|
994 aTargetArray ); |
|
995 |
|
996 if ( !targetArrayChanged && identifierAdded ) |
|
997 { |
|
998 DLINFO(("Identifier was added")); |
|
999 // Because the identifier was added into the array. |
|
1000 // This is set only once because if something was added |
|
1001 // then the array has been changed. |
|
1002 // But, let the loop add all the other identifiers also. |
|
1003 // So, do not break here. |
|
1004 targetArrayChanged = ETrue; |
|
1005 } |
|
1006 } |
|
1007 |
|
1008 DLTRACEOUT(("")); |
|
1009 |
|
1010 // Inform the called if something was added into the target array. |
|
1011 return targetArrayChanged; |
|
1012 } |
|
1013 |
|
1014 TBool CNcdNodeCacheCleaner::AddIdentifierL( const CNcdNodeIdentifier& aIdentifier, |
|
1015 RPointerArray<CNcdNodeIdentifier>& aTargetArray ) |
|
1016 { |
|
1017 DLTRACEIN(("")); |
|
1018 |
|
1019 // Compare the given identifier to the identifiers that have already inserted into the |
|
1020 // array. |
|
1021 const TInt count = aTargetArray.Count(); |
|
1022 for ( TInt i = 0; i < count; ++i ) |
|
1023 { |
|
1024 DASSERT( aTargetArray[ i ] != NULL ); |
|
1025 |
|
1026 // If the identifier was already in the array then, do not add it again. |
|
1027 if ( aIdentifier.Equals( *aTargetArray[ i ] ) ) |
|
1028 { |
|
1029 DLINFO(("Identifier was found. Return false.")); |
|
1030 // The identifier was found. |
|
1031 // So, return EFalse to inform that identifier was not added. |
|
1032 return EFalse; |
|
1033 } |
|
1034 } |
|
1035 |
|
1036 // The item was not in the array yet. So, append it into the array. |
|
1037 |
|
1038 CNcdNodeIdentifier* copyIdentifier = |
|
1039 CNcdNodeIdentifier::NewLC( aIdentifier ); |
|
1040 aTargetArray.AppendL( copyIdentifier ); |
|
1041 CleanupStack::Pop( copyIdentifier ); |
|
1042 |
|
1043 DLTRACEOUT(("")); |
|
1044 |
|
1045 // Return ETrue, because addition was done into the target array. |
|
1046 return ETrue; |
|
1047 } |
|
1048 |
|
1049 |
|
1050 TBool CNcdNodeCacheCleaner::RemoveIdentifiers( const RPointerArray<CNcdNodeIdentifier>& aIdentifiers, |
|
1051 RPointerArray<CNcdNodeIdentifier>& aTargetArray ) |
|
1052 { |
|
1053 DLTRACEIN(("")); |
|
1054 |
|
1055 TBool targetArrayChanged( EFalse ); |
|
1056 TBool identifierRemoved( EFalse ); |
|
1057 const TInt count = aIdentifiers.Count(); |
|
1058 for ( TInt i = 0; i < count; ++i ) |
|
1059 { |
|
1060 DASSERT( aIdentifiers[ i ] != NULL ); |
|
1061 |
|
1062 identifierRemoved = |
|
1063 RemoveIdentifier( *aIdentifiers[ i ], |
|
1064 aTargetArray ); |
|
1065 |
|
1066 if ( !targetArrayChanged && identifierRemoved ) |
|
1067 { |
|
1068 DLINFO(("Identifier was removed")); |
|
1069 // The identifier was removed from the array. |
|
1070 // This value is set only once because if something was added |
|
1071 // then the array has been changed. |
|
1072 targetArrayChanged = ETrue; |
|
1073 } |
|
1074 } |
|
1075 |
|
1076 DLTRACEOUT(("")); |
|
1077 |
|
1078 // Inform the caller if something was added into the target array. |
|
1079 return targetArrayChanged; |
|
1080 } |
|
1081 |
|
1082 TBool CNcdNodeCacheCleaner::RemoveIdentifier( const CNcdNodeIdentifier& aIdentifier, |
|
1083 RPointerArray<CNcdNodeIdentifier>& aTargetArray ) |
|
1084 { |
|
1085 DLTRACEIN(("")); |
|
1086 |
|
1087 TBool removed( EFalse ); |
|
1088 |
|
1089 // Remove all occurrences of the identifier from the target array. |
|
1090 // Start from the end of the array and move towards the beginning. |
|
1091 for ( TInt i = aTargetArray.Count() - 1; i >= 0; --i ) |
|
1092 { |
|
1093 DASSERT( aTargetArray[ i ] != NULL ); |
|
1094 |
|
1095 if ( aIdentifier.Equals( *aTargetArray[ i ] ) ) |
|
1096 { |
|
1097 DLINFO(("Remove identifier")); |
|
1098 // The identifier was found from the array. So, remove it. |
|
1099 delete aTargetArray[ i ]; |
|
1100 aTargetArray.Remove( i ); |
|
1101 removed = ETrue; |
|
1102 // Because the indexing comes from the counter value towards |
|
1103 // the zero, no need to update indexing here even if the removal |
|
1104 // was done above. |
|
1105 } |
|
1106 } |
|
1107 |
|
1108 DLTRACEOUT(("")); |
|
1109 |
|
1110 return removed; |
|
1111 } |
|
1112 |
|
1113 |
|
1114 TBool CNcdNodeCacheCleaner::RemoveIdentifier( |
|
1115 const CNcdNodeIdentifier& aIdentifier, |
|
1116 RPointerArray<CDoNotRemoveIdentifier>& aTargetArray, |
|
1117 TBool aForceRemove ) |
|
1118 { |
|
1119 DLTRACEIN(("")); |
|
1120 // Remove all occurrences of the identifier from the target array. |
|
1121 // Start from the end of the array and move towards the beginning. |
|
1122 TInt i = aTargetArray.Count(); |
|
1123 while ( i-- ) |
|
1124 { |
|
1125 DASSERT( aTargetArray[ i ] != NULL ); |
|
1126 |
|
1127 if ( aIdentifier.Equals( aTargetArray[ i ]->Key() ) ) |
|
1128 { |
|
1129 // Make sure that favorites are removed only if they are actually |
|
1130 // removed from favorites |
|
1131 if ( aForceRemove || |
|
1132 !aTargetArray[ i ]->Value() ) |
|
1133 { |
|
1134 DLINFO(("Remove identifier")); |
|
1135 // The identifier was found from the array. So, remove it. |
|
1136 delete aTargetArray[ i ]; |
|
1137 aTargetArray.Remove( i ); |
|
1138 } |
|
1139 return ETrue; |
|
1140 } |
|
1141 } |
|
1142 |
|
1143 DLTRACEOUT(("")); |
|
1144 return EFalse; |
|
1145 } |
|
1146 |
|
1147 |
|
1148 void CNcdNodeCacheCleaner::SetAllDbStorageNodeItemsL() |
|
1149 { |
|
1150 DLTRACEIN(("")); |
|
1151 |
|
1152 // Just in case, first clean the identifier list. |
|
1153 iAllDbStorageNodeItems.ResetAndDestroy(); |
|
1154 |
|
1155 // Yes, we intentionally push a member variable to the cleanupstack |
|
1156 CleanupResetAndDestroyPushL( iAllDbStorageNodeItems ); |
|
1157 // Get the new values for cleaning. |
|
1158 // Note that some of the items are not accepted |
|
1159 // for this list. |
|
1160 |
|
1161 NodeDbManager(). |
|
1162 GetAllClientItemIdentifiersL( |
|
1163 iAllDbStorageNodeItems, |
|
1164 ClientUid(), |
|
1165 *iDoNotCleanNameSpaces, |
|
1166 iNodeCleanupTypes ); |
|
1167 |
|
1168 CleanupStack::Pop( &iAllDbStorageNodeItems ); |
|
1169 // Sort the identifiers in the array. |
|
1170 // The first item is closest to the root. The last item is |
|
1171 // deepest in the hierarchy. |
|
1172 // Give the function pointer of the static function as a parameter. |
|
1173 |
|
1174 DLTRACE(("start sorting")); |
|
1175 TLinearOrder<CNcdNodeIdentifier> sorter( &NodeIdentifierArraySortById ); |
|
1176 iAllDbStorageNodeItems.Sort( sorter ); |
|
1177 DLTRACE(("sorting ended")); |
|
1178 |
|
1179 // Print array debug info into the log file |
|
1180 #ifdef NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
1181 DLINFO(("iAllDbStorageNodeItems array:")); |
|
1182 ArrayDebugPrint( iAllDbStorageNodeItems ); |
|
1183 #endif |
|
1184 |
|
1185 DLTRACEOUT(("")); |
|
1186 } |
|
1187 |
|
1188 |
|
1189 void CNcdNodeCacheCleaner::SetAllDbStorageIconItemsL() |
|
1190 { |
|
1191 DLTRACEIN(("")); |
|
1192 |
|
1193 // Just in case first clean the identifier list. |
|
1194 iAllDbIconItems.ResetAndDestroy(); |
|
1195 |
|
1196 // Yes, we intentionally push a member variable to the cleanupstack |
|
1197 CleanupResetAndDestroyPushL( iAllDbIconItems ); |
|
1198 |
|
1199 // Get the new values for cleaning. |
|
1200 // Note that some of the items are not accepted |
|
1201 // for this list. |
|
1202 |
|
1203 NodeDbManager(). |
|
1204 GetAllClientItemIdentifiersL( |
|
1205 iAllDbIconItems, |
|
1206 ClientUid(), |
|
1207 *iDoNotCleanNameSpaces, |
|
1208 iIconCleanupTypes ); |
|
1209 |
|
1210 CleanupStack::Pop( &iAllDbIconItems ); |
|
1211 // Icon ids do not need to be sorted, because they do not contain node ids but |
|
1212 // are something else. |
|
1213 |
|
1214 // Print array debug info into the log file |
|
1215 #ifdef NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
1216 DLINFO(("iAllDbIconItems array:")); |
|
1217 ArrayDebugPrint( iAllDbIconItems ); |
|
1218 #endif |
|
1219 |
|
1220 DLTRACEOUT(("")); |
|
1221 } |
|
1222 |
|
1223 |
|
1224 |
|
1225 void CNcdNodeCacheCleaner::SetAllDbStorageScreenshotItemsL() |
|
1226 { |
|
1227 DLTRACEIN(("")); |
|
1228 // Just in case first clean the identifier list. |
|
1229 iAllDbScreenshotItems.ResetAndDestroy(); |
|
1230 |
|
1231 // Yes, we intentionally push a member variable to the cleanupstack |
|
1232 CleanupResetAndDestroyPushL( iAllDbScreenshotItems ); |
|
1233 |
|
1234 // Get the new values for cleaning. |
|
1235 // Note that some of the items are not accepted |
|
1236 // for this list. |
|
1237 NodeDbManager(). |
|
1238 GetAllClientItemIdentifiersL( |
|
1239 iAllDbScreenshotItems, |
|
1240 ClientUid(), |
|
1241 *iDoNotCleanNameSpaces, |
|
1242 iScreenshotCleanupTypes ); |
|
1243 |
|
1244 CleanupStack::Pop( &iAllDbScreenshotItems ); |
|
1245 |
|
1246 // Print array debug info into the log file |
|
1247 #ifdef NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
1248 DLINFO(("iAllDbScreenshotItems array:")); |
|
1249 ArrayDebugPrint( iAllDbScreenshotItems ); |
|
1250 #endif |
|
1251 } |
|
1252 |
|
1253 |
|
1254 void CNcdNodeCacheCleaner::AddChildrenToCleanupArrayL() |
|
1255 { |
|
1256 DLTRACEIN(("")); |
|
1257 |
|
1258 // Get the counter value. So, we know how many items are |
|
1259 // in the list before children are added |
|
1260 TInt counter = iCleanupIdentifiers.Count(); |
|
1261 |
|
1262 // Check if any children are found from the db items. |
|
1263 // If they are found, then move them to the cleanup array. |
|
1264 CNcdNodeIdentifier* cleanupIdentifier( NULL ); |
|
1265 CNcdNodeIdentifier* storageItemIdentifier( NULL ); |
|
1266 for ( TInt i = 0; i < counter; ++i ) |
|
1267 { |
|
1268 cleanupIdentifier = iCleanupIdentifiers[ i ]; |
|
1269 // Start from the end of the list. So, the indexing is |
|
1270 // always correct even if an item is moved |
|
1271 for ( TInt j = iAllDbStorageNodeItems.Count(); j > 0; --j ) |
|
1272 { |
|
1273 storageItemIdentifier = iAllDbStorageNodeItems[ j - 1 ]; |
|
1274 if ( NcdNodeIdentifierEditor::NodeDepthL( *cleanupIdentifier ) |
|
1275 > NcdNodeIdentifierEditor::NodeDepthL( *storageItemIdentifier ) ) |
|
1276 { |
|
1277 // Because the db items array is sorted so that the deepest items are |
|
1278 // in the end of the array, the children can not be found anymore. |
|
1279 // (Notice that db items are gone through from the end of the array.) |
|
1280 DLINFO(("Child parent barrier passed: %d", j - 1 )); |
|
1281 break; |
|
1282 } |
|
1283 else if ( NcdNodeIdentifierEditor::ParentOf( *cleanupIdentifier, |
|
1284 *storageItemIdentifier ) |
|
1285 && !ContainsIdentifier( *storageItemIdentifier, |
|
1286 iDoNotRemoves ) |
|
1287 && !NcdNodeIdentifierUtils::ContainsIdentifier( |
|
1288 *storageItemIdentifier, iWaitingIdentifiers ) |
|
1289 && !NcdNodeIdentifierUtils::ContainsIdentifier( |
|
1290 *storageItemIdentifier, iWaitingParentIdentifiers ) ) |
|
1291 { |
|
1292 DLINFO(("Children items found and can be moved")); |
|
1293 // The child is not in do not remove list or in the waiting list. |
|
1294 // So, it can be inserted into the cleanup list. |
|
1295 // Notice that before cleaning it should |
|
1296 // be checked that the child is not a parent of some other child that |
|
1297 // can not be removed. |
|
1298 // Use this function to check that the item is not appended twice |
|
1299 AddCleanupIdentifierL( *storageItemIdentifier ); |
|
1300 // Remove the data from its original place. Notice that identifier |
|
1301 // is copied in the function above. |
|
1302 delete storageItemIdentifier; |
|
1303 iAllDbStorageNodeItems.Remove( j - 1 ); |
|
1304 } |
|
1305 } |
|
1306 } |
|
1307 |
|
1308 // Print array debug info into the log file |
|
1309 #ifdef NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
1310 DLINFO(("iCleanupIdentifiers array:")) |
|
1311 ArrayDebugPrint( iCleanupIdentifiers ); |
|
1312 #endif |
|
1313 |
|
1314 DLTRACEOUT(("")); |
|
1315 } |
|
1316 |
|
1317 |
|
1318 void CNcdNodeCacheCleaner::ParentCleaningCheckL() |
|
1319 { |
|
1320 DLTRACEIN(("")); |
|
1321 |
|
1322 // Print array debug info into the log file |
|
1323 #ifdef NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
1324 DLINFO(("iDoNotRemoves array:")); |
|
1325 ArrayDebugPrint( iDoNotRemoves ); |
|
1326 #endif |
|
1327 |
|
1328 // Print array debug info into the log file |
|
1329 #ifdef NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
1330 DLINFO(("iWaitingParentIdentifiers array:")); |
|
1331 ArrayDebugPrint( iWaitingParentIdentifiers ); |
|
1332 #endif |
|
1333 |
|
1334 // Print array debug info into the log file |
|
1335 #ifdef NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
1336 DLINFO(("iWaitingIdentifiers array:")); |
|
1337 ArrayDebugPrint( iWaitingIdentifiers ); |
|
1338 #endif |
|
1339 |
|
1340 // Check if there are some parents that are going to be cleaned but |
|
1341 // they should not be because their children are in the do not remove list |
|
1342 // or in the in the waiting list |
|
1343 for ( TInt i = iCleanupIdentifiers.Count(); i > 0 ; --i ) |
|
1344 { |
|
1345 for ( TInt j = 0; j < iDoNotRemoves.Count(); ++j ) |
|
1346 { |
|
1347 // first check if parent can not be removed (for favorites it can be removed) |
|
1348 if ( !iDoNotRemoves[ j ]->Value() && |
|
1349 NcdNodeIdentifierEditor::ParentOf( *iCleanupIdentifiers[ i - 1 ], |
|
1350 iDoNotRemoves[ j ]->Key() ) ) |
|
1351 { |
|
1352 DLINFO(("Do not remove parent because child is do not remove: %d", i)) |
|
1353 // Because the cleanup identifier was a parent of something that |
|
1354 // should not be removed, then do not remove the parent either, |
|
1355 // but insert it to wait. |
|
1356 AddIdentifierL( *iCleanupIdentifiers[ i - 1 ], iWaitingParentIdentifiers ); |
|
1357 delete iCleanupIdentifiers[ i - 1 ]; |
|
1358 iCleanupIdentifiers.Remove( i - 1 ); |
|
1359 |
|
1360 // Because the identifier was now removed from the array |
|
1361 // and moved to the waiting array, we skip to the next identifier check. |
|
1362 // This way the i-indexing will be correct. |
|
1363 break; |
|
1364 } |
|
1365 } |
|
1366 } |
|
1367 |
|
1368 // Check the waiting identifiers in their own loop, so the i indexing |
|
1369 // will be correct here if removing has been done above. |
|
1370 for ( TInt i = iCleanupIdentifiers.Count(); i > 0 ; --i ) |
|
1371 { |
|
1372 for ( TInt k = 0; k < iWaitingIdentifiers.Count(); ++k ) |
|
1373 { |
|
1374 if ( NcdNodeIdentifierEditor::ParentOf( *iCleanupIdentifiers[ i - 1 ], |
|
1375 *iWaitingIdentifiers[ k ] ) ) |
|
1376 { |
|
1377 DLINFO(("Do not remove parent because child is waiting: %d", i)) |
|
1378 // Because the cleanup identifier was a parent of something that |
|
1379 // should not be removed, then do not remove the parent either, |
|
1380 // but insert it to wait. |
|
1381 AddIdentifierL( *iCleanupIdentifiers[ i - 1 ], |
|
1382 iWaitingParentIdentifiers ); |
|
1383 delete iCleanupIdentifiers[ i - 1 ]; |
|
1384 iCleanupIdentifiers.Remove( i - 1 ); |
|
1385 |
|
1386 // Because the identifier was now removed from the array |
|
1387 // and moved to the waiting array, we skip to the next identifier check. |
|
1388 // This way the i-indexing will be correct. |
|
1389 break; |
|
1390 } |
|
1391 } |
|
1392 } |
|
1393 |
|
1394 // Now check if there are some parents waiting that should not any more |
|
1395 TBool wasNotFound( ETrue ); |
|
1396 for ( TInt i = iWaitingParentIdentifiers.Count(); i > 0 ; --i ) |
|
1397 { |
|
1398 wasNotFound = ETrue; |
|
1399 for ( TInt j = 0; j < iDoNotRemoves.Count(); ++j ) |
|
1400 { |
|
1401 if ( !iDoNotRemoves[ j ]->Value() && |
|
1402 NcdNodeIdentifierEditor::ParentOf( *iWaitingParentIdentifiers[ i - 1 ], |
|
1403 iDoNotRemoves[ j ]->Key() ) ) |
|
1404 { |
|
1405 // The waiting parent should still be waiting |
|
1406 wasNotFound = EFalse; |
|
1407 break; |
|
1408 } |
|
1409 } |
|
1410 for ( TInt k = 0; k < iWaitingIdentifiers.Count() && wasNotFound; ++k ) |
|
1411 { |
|
1412 if ( NcdNodeIdentifierEditor::ParentOf( *iWaitingParentIdentifiers[ i - 1 ], |
|
1413 *iWaitingIdentifiers[ k ] ) ) |
|
1414 { |
|
1415 // The waiting parent should still be waiting |
|
1416 wasNotFound = EFalse; |
|
1417 break; |
|
1418 } |
|
1419 } |
|
1420 |
|
1421 if ( wasNotFound ) |
|
1422 { |
|
1423 DLINFO(("Waiting parent can be moved to the cleanup list: %d", i)); |
|
1424 // Because the waiting identifier was not a parent of something that |
|
1425 // should not be removed anymore. Move it to the cleanup list. |
|
1426 AddIdentifierL( *iWaitingParentIdentifiers[ i - 1 ], iCleanupIdentifiers ); |
|
1427 delete iWaitingParentIdentifiers[ i - 1 ]; |
|
1428 iWaitingParentIdentifiers.Remove( i - 1 ); |
|
1429 } |
|
1430 } |
|
1431 |
|
1432 // Print array debug info into the log file |
|
1433 #ifdef NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
1434 DLINFO(("iCleanupIdentifiers array:")); |
|
1435 ArrayDebugPrint( iCleanupIdentifiers ); |
|
1436 #endif |
|
1437 |
|
1438 DLTRACEOUT(("")); |
|
1439 } |
|
1440 |
|
1441 |
|
1442 void CNcdNodeCacheCleaner::RemoveDoNotRemovesFromCleanupArray() |
|
1443 { |
|
1444 DLTRACEIN(("")); |
|
1445 TInt doNotRemoveCount = iDoNotRemoves.Count(); |
|
1446 while ( doNotRemoveCount-- ) |
|
1447 { |
|
1448 TInt cleanupCount = iCleanupIdentifiers.Count(); |
|
1449 while( cleanupCount-- ) |
|
1450 { |
|
1451 if ( iDoNotRemoves[ doNotRemoveCount ]->Key().Equals( |
|
1452 *iCleanupIdentifiers[ cleanupCount ] ) ) |
|
1453 { |
|
1454 DLTRACE(("Removing")); |
|
1455 DLNODEID(( *iCleanupIdentifiers[ cleanupCount ] )); |
|
1456 delete iCleanupIdentifiers[ cleanupCount ]; |
|
1457 iCleanupIdentifiers.Remove( cleanupCount ); |
|
1458 break; |
|
1459 } |
|
1460 } |
|
1461 } |
|
1462 } |
|
1463 |
|
1464 |
|
1465 void CNcdNodeCacheCleaner::CheckTemporaryNodesL() |
|
1466 { |
|
1467 DLTRACEIN(("")); |
|
1468 |
|
1469 TInt itemCount( iAllDbStorageNodeItems.Count() ); |
|
1470 |
|
1471 CNcdNodeIdentifier* identifier( NULL ); |
|
1472 |
|
1473 for ( TInt i = itemCount; i > 0; --i ) |
|
1474 { |
|
1475 identifier = iAllDbStorageNodeItems[ i - 1 ]; |
|
1476 |
|
1477 // All the nodes that do not start with the root id are thought to be |
|
1478 // temporary nodes. |
|
1479 if ( NcdNodeIdentifierEditor::IdentifiesTemporaryNodeL( *identifier ) ) |
|
1480 { |
|
1481 DLINFO((_L("Remove temporary node: %S, %S, %S, %d"), |
|
1482 &identifier->NodeNameSpace(), &identifier->NodeId(), |
|
1483 &identifier->ServerUri(), identifier->ClientUid().iUid)); |
|
1484 // This is a temporary node. |
|
1485 // Insert it into the cleanup array if removal is allowed. |
|
1486 AddCleanupIdentifierL( *identifier ); |
|
1487 |
|
1488 // Remove the data from its original place. Notice that identifier |
|
1489 // is copied in the function above. |
|
1490 delete iAllDbStorageNodeItems[ i - 1 ]; |
|
1491 iAllDbStorageNodeItems.Remove( i - 1 ); |
|
1492 } |
|
1493 } |
|
1494 |
|
1495 DLTRACEOUT(("")); |
|
1496 } |
|
1497 |
|
1498 |
|
1499 void CNcdNodeCacheCleaner::ResetState() |
|
1500 { |
|
1501 DLTRACEIN(("")); |
|
1502 |
|
1503 iExpiredCleaningIndex = 0; |
|
1504 iExcessCleanupStarted = EFalse; |
|
1505 |
|
1506 // Do not waste space with old info. |
|
1507 iAllDbStorageNodeItems.ResetAndDestroy(); |
|
1508 iAllDbIconItems.ResetAndDestroy(); |
|
1509 iDbMetaIdentifiers.ResetAndDestroy(); |
|
1510 iRootChildren.ResetAndDestroy(); |
|
1511 iBundleChildren.ResetAndDestroy(); |
|
1512 |
|
1513 iAllDbScreenshotItems.ResetAndDestroy(); |
|
1514 |
|
1515 // Set the priority to the correct value |
|
1516 // for the next cleaning round. The priority |
|
1517 // may have been changed if db was too full. |
|
1518 iIncreasePriority = KDefaultCleaningPriority; |
|
1519 if ( IsActive() ) |
|
1520 { |
|
1521 DLINFO(("Active. Priority should be reseted later.")); |
|
1522 // Set the priority flags for the member variables. |
|
1523 // This value will be used in later in StartCleanupL |
|
1524 // where the priority is set for this active object next time |
|
1525 // they are called. This check is required because DoCancel uses |
|
1526 // this function and then the active object may still be active until |
|
1527 // DoCancel finishes its job. |
|
1528 iResetPriority = ETrue; |
|
1529 } |
|
1530 else |
|
1531 { |
|
1532 DLINFO(("Not active")); |
|
1533 // Set the correct priority value. |
|
1534 // The priority can also be set for the active object because |
|
1535 // it is not active at the moment. |
|
1536 SetPriority( KDefaultCleaningPriority ); |
|
1537 } |
|
1538 |
|
1539 // Set state and other flags. To inital values. |
|
1540 iCleanupState = ENotStarted; |
|
1541 |
|
1542 DLTRACEOUT(("")); |
|
1543 } |
|
1544 |
|
1545 |
|
1546 #ifdef NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
1547 void CNcdNodeCacheCleaner::ArrayDebugPrint( const RPointerArray<CNcdNodeIdentifier>& aIdentifiers ) const |
|
1548 { |
|
1549 DLTRACEIN(("")); |
|
1550 |
|
1551 CNcdNodeIdentifier* identifier( NULL ); |
|
1552 (void) *identifier; // prevents compiler warning of unused variable |
|
1553 |
|
1554 for ( TInt i = 0; i < aIdentifiers.Count(); ++i ) |
|
1555 { |
|
1556 identifier = aIdentifiers[ i ]; |
|
1557 DLINFO((_L("Array identifier: %S, %S, %S, %d"), |
|
1558 &identifier->NodeNameSpace(), &identifier->NodeId(), |
|
1559 &identifier->ServerUri(), identifier->ClientUid().iUid)); |
|
1560 } |
|
1561 |
|
1562 DLTRACEOUT(("")); |
|
1563 } |
|
1564 |
|
1565 void CNcdNodeCacheCleaner::ArrayDebugPrint( const RPointerArray<CDoNotRemoveIdentifier>& aIdentifiers ) const |
|
1566 { |
|
1567 DLTRACEIN(("")); |
|
1568 |
|
1569 const CNcdNodeIdentifier* identifier( NULL ); |
|
1570 (void) *identifier; // prevents compiler warning of unused variable |
|
1571 |
|
1572 for ( TInt i = 0; i < aIdentifiers.Count(); ++i ) |
|
1573 { |
|
1574 identifier = &aIdentifiers[ i ]->Key(); |
|
1575 DLINFO((_L("Array identifier: %S, %S, %S, %d"), |
|
1576 &identifier->NodeNameSpace(), &identifier->NodeId(), |
|
1577 &identifier->ServerUri(), identifier->ClientUid().iUid)); |
|
1578 } |
|
1579 |
|
1580 DLTRACEOUT(("")); |
|
1581 } |
|
1582 |
|
1583 #endif // NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
1584 |
|
1585 |
|
1586 void CNcdNodeCacheCleaner::CleanSpecialsL() |
|
1587 { |
|
1588 DLTRACEIN(("")); |
|
1589 |
|
1590 // Try to clean some nodes if they are in the cleanuplist. |
|
1591 // Do not reset the node list or delete it here. |
|
1592 // This list is used throughout the cleaning process. |
|
1593 // The array might be updated only in the start excess cleaning function. |
|
1594 // Other functions should not update the list, because otherwise the |
|
1595 // excess cleaner may go into the infinite loop if deepest nodes cannot |
|
1596 // be removed. |
|
1597 HandleCleaningL( EFalse, EFalse ); |
|
1598 |
|
1599 // Next step will be cleaning temporary nodes that |
|
1600 // are not used any more. If too much space is used, |
|
1601 // some extra cleaning will also be done by looping these steps. |
|
1602 iCleanupState = ECleaningTemporaryNodes; |
|
1603 |
|
1604 iStatus = KRequestPending; |
|
1605 SetActive(); |
|
1606 TRequestStatus* ptrStatus = &iStatus; |
|
1607 User::RequestComplete( ptrStatus, KErrNone ); |
|
1608 |
|
1609 DLTRACEOUT(("")); |
|
1610 } |
|
1611 |
|
1612 |
|
1613 void CNcdNodeCacheCleaner::CleanTemporaryNodesL() |
|
1614 { |
|
1615 DLTRACEIN(("")); |
|
1616 |
|
1617 // Notice that the iAllDbStorageNodeItems may not be up to date here if |
|
1618 // some new nodes have been inserted into the database after the cleaning |
|
1619 // has been started. So, if those new items are temporary objects they will |
|
1620 // not be checked here. The update of the array is omitted here to save some |
|
1621 // time, because db-actions may take long time. Also, the array should not |
|
1622 // be updated here, because otherwise excess removing may go into the infinite loop. |
|
1623 // The omitting of some temporary nodes does not matter because they will be |
|
1624 // cleaned next time the cleaner starts it actions. |
|
1625 CheckTemporaryNodesL(); |
|
1626 |
|
1627 // HandleCleaningL and the functions it uses can handle the removing of the |
|
1628 // item from the db array. |
|
1629 // Just use the old node list. |
|
1630 // Do not delte the list because if excess cleaning is done, then the list should |
|
1631 // not be reloaded. Reloading might cause a infinite loop. |
|
1632 HandleCleaningL( EFalse, EFalse ); |
|
1633 |
|
1634 iCleanupState = ECleaningHangingCases; |
|
1635 iStatus = KRequestPending; |
|
1636 SetActive(); |
|
1637 TRequestStatus* ptrStatus = &iStatus; |
|
1638 User::RequestComplete( ptrStatus, KErrNone ); |
|
1639 |
|
1640 DLTRACEOUT(("")); |
|
1641 } |
|
1642 |
|
1643 |
|
1644 void CNcdNodeCacheCleaner::CleanHangingsL() |
|
1645 { |
|
1646 DLTRACEIN(("")); |
|
1647 |
|
1648 // The node items list has to be updated here. So, we can be sure that |
|
1649 // both the node array and metadata array are up to date when hangings |
|
1650 // are searched. If node list were not up to date, then some of the |
|
1651 // the metadata may be mistakenly thought to be hanging. |
|
1652 |
|
1653 // Get the node identifiers for the list. We do not use the member variable |
|
1654 // iAllDbStorageNodeItems here, because it should only be updated when the |
|
1655 // cleaning is started or in the excess clean function. |
|
1656 // Notice that here it does not matter that the nodes are not in specific |
|
1657 // order. Because all the nodes are compared to metadatas. |
|
1658 RPointerArray<CNcdNodeIdentifier> dbNodeIdentifiers; |
|
1659 CleanupResetAndDestroyPushL( dbNodeIdentifiers ); |
|
1660 NodeDbManager(). |
|
1661 GetAllClientItemIdentifiersL( |
|
1662 dbNodeIdentifiers, |
|
1663 ClientUid(), |
|
1664 *iDoNotCleanNameSpaces, |
|
1665 iNodeCleanupTypes ); |
|
1666 |
|
1667 // Get all the metadata identifiers from the db. |
|
1668 // (left the do not clean namespaces out because they |
|
1669 // are ignored in all cases here) |
|
1670 RPointerArray<CNcdNodeIdentifier> dbMetaIdentifiers; |
|
1671 CleanupResetAndDestroyPushL( dbMetaIdentifiers ); |
|
1672 NodeDbManager(). |
|
1673 GetAllClientItemIdentifiersL( |
|
1674 dbMetaIdentifiers, |
|
1675 ClientUid(), |
|
1676 *iDoNotCleanNameSpaces, |
|
1677 iMetaCleanupTypes ); |
|
1678 |
|
1679 DLINFO(("Db node count: %d", dbNodeIdentifiers.Count())); |
|
1680 // Print array debug info into the log file |
|
1681 #ifdef NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
1682 DLINFO(("dbNodeIdentifiers array:")); |
|
1683 ArrayDebugPrint( dbNodeIdentifiers ); |
|
1684 #endif |
|
1685 |
|
1686 DLINFO(("Db meta count: %d", dbMetaIdentifiers.Count())); |
|
1687 // Print array debug info into the log file |
|
1688 #ifdef NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
1689 DLINFO(("dbNodeIdentifiers array:")); |
|
1690 ArrayDebugPrint( dbMetaIdentifiers ); |
|
1691 #endif |
|
1692 |
|
1693 // Check if the node corresponding metadata identifier can be |
|
1694 // found from the db node list. |
|
1695 // If it can not be found, then the item has been left to hang in |
|
1696 // the db and can be removed. |
|
1697 CNcdNodeIdentifier* identifier( NULL ); |
|
1698 TBool nodeFound( EFalse ); |
|
1699 TInt j = dbMetaIdentifiers.Count(); |
|
1700 const TInt count = dbNodeIdentifiers.Count(); |
|
1701 |
|
1702 while ( j-- ) |
|
1703 { |
|
1704 nodeFound = EFalse; |
|
1705 |
|
1706 for ( TInt i = 0; i < count; ++i ) |
|
1707 { |
|
1708 // Get the metadata part of the node name |
|
1709 identifier = |
|
1710 NcdNodeIdentifierEditor:: |
|
1711 CreateMetaDataIdentifierL( *dbNodeIdentifiers[ i ] ); |
|
1712 |
|
1713 // Check if the metadata part of the node id |
|
1714 // equals the metadata part of the list. |
|
1715 if ( identifier->Equals( *dbMetaIdentifiers[ j ] ) ) |
|
1716 { |
|
1717 // The identifiers equal so corresponding node was found |
|
1718 nodeFound = ETrue; |
|
1719 |
|
1720 delete identifier; |
|
1721 identifier = NULL; |
|
1722 |
|
1723 // Because node was found the meta can be removed from the |
|
1724 // list |
|
1725 delete dbMetaIdentifiers[ j ]; |
|
1726 dbMetaIdentifiers.Remove( j ); |
|
1727 |
|
1728 break; |
|
1729 } |
|
1730 else |
|
1731 { |
|
1732 delete identifier; |
|
1733 identifier = NULL; |
|
1734 } |
|
1735 } |
|
1736 |
|
1737 if ( !nodeFound ) |
|
1738 { |
|
1739 // If node was not found from DB, it is possibly in DoNotRemove list. |
|
1740 // Don't delete the metadata of such a node. |
|
1741 const TInt doNotRemovesCount = iDoNotRemoves.Count(); |
|
1742 for ( TInt i = 0; i < doNotRemovesCount; i++ ) |
|
1743 { |
|
1744 identifier = |
|
1745 NcdNodeIdentifierEditor::CreateMetaDataIdentifierL( |
|
1746 iDoNotRemoves[i]->Key() ); |
|
1747 |
|
1748 // Check if the metadata part of the node id equals the metadata part |
|
1749 // of the list. |
|
1750 if ( identifier->Equals( *dbMetaIdentifiers[ j ] ) ) |
|
1751 { |
|
1752 |
|
1753 delete identifier; |
|
1754 identifier = NULL; |
|
1755 |
|
1756 delete dbMetaIdentifiers[ j ]; |
|
1757 dbMetaIdentifiers.Remove( j ); |
|
1758 |
|
1759 break; |
|
1760 } |
|
1761 else |
|
1762 { |
|
1763 delete identifier; |
|
1764 identifier = NULL; |
|
1765 } |
|
1766 } |
|
1767 } |
|
1768 } |
|
1769 |
|
1770 DLINFO(("Remove hangings from db: %d", dbMetaIdentifiers.Count())); |
|
1771 // Print array debug info into the log file |
|
1772 #ifdef NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
1773 DLINFO(("dbMetaIdentifiers array:")); |
|
1774 ArrayDebugPrint( dbMetaIdentifiers ); |
|
1775 #endif |
|
1776 |
|
1777 // No need to check do not remove items here, because all the items |
|
1778 // that are hanging are independent from the nodes. That is also why, |
|
1779 // we do not need to do any parent child relation checking either. |
|
1780 NodeDbManager(). |
|
1781 RemoveDataFromDatabaseL( dbMetaIdentifiers, |
|
1782 iMetaCleanupTypes ); |
|
1783 |
|
1784 CleanupStack::PopAndDestroy( &dbMetaIdentifiers ); |
|
1785 CleanupStack::PopAndDestroy( &dbNodeIdentifiers ); |
|
1786 |
|
1787 // Next handle excess cleaning |
|
1788 iCleanupState = EStartCleaningHangingSpecialCases; |
|
1789 iStatus = KRequestPending; |
|
1790 SetActive(); |
|
1791 TRequestStatus* ptrStatus = &iStatus; |
|
1792 User::RequestComplete( ptrStatus, KErrNone ); |
|
1793 |
|
1794 DLTRACEOUT(("")); |
|
1795 } |
|
1796 |
|
1797 |
|
1798 void CNcdNodeCacheCleaner::StartCleanSpecialHangingsL() |
|
1799 { |
|
1800 DLTRACEIN(("")); |
|
1801 |
|
1802 // Notice that the special hanging only need metadata objects. |
|
1803 |
|
1804 // Get all the metadata identifiers from the db. |
|
1805 // (left the do not clean namespaces out because they |
|
1806 // are ignored in all cases here) |
|
1807 // Notice that the icon array is also updated below. So, |
|
1808 // the metadata and the icon infromation will be in sync. |
|
1809 iDbMetaIdentifiers.ResetAndDestroy(); |
|
1810 NodeDbManager(). |
|
1811 GetAllClientItemIdentifiersL( |
|
1812 iDbMetaIdentifiers, |
|
1813 ClientUid(), |
|
1814 *iDoNotCleanNameSpaces, |
|
1815 iMetaCleanupTypes ); |
|
1816 |
|
1817 DLINFO(("Db meta count: %d", iDbMetaIdentifiers.Count())); |
|
1818 // Print array debug info into the log file |
|
1819 #ifdef NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
1820 DLINFO(("iDbMetaIdentifiers array:")); |
|
1821 ArrayDebugPrint( iDbMetaIdentifiers ); |
|
1822 #endif |
|
1823 |
|
1824 // Start to clean all the special cases. |
|
1825 SetAllDbStorageIconItemsL(); |
|
1826 |
|
1827 SetAllDbStorageScreenshotItemsL(); |
|
1828 |
|
1829 // Next clean the excess special cases |
|
1830 iCleanupState = ECleaningHangingSpecialCases; |
|
1831 iStatus = KRequestPending; |
|
1832 SetActive(); |
|
1833 TRequestStatus* ptrStatus = &iStatus; |
|
1834 User::RequestComplete( ptrStatus, KErrNone ); |
|
1835 |
|
1836 DLTRACEOUT(("")); |
|
1837 } |
|
1838 |
|
1839 |
|
1840 void CNcdNodeCacheCleaner::CleanSpecialHangingsL() |
|
1841 { |
|
1842 DLTRACEIN(("")); |
|
1843 |
|
1844 if ( iDbMetaIdentifiers.Count() > 0 ) |
|
1845 { |
|
1846 DLINFO(("More metas left")); |
|
1847 |
|
1848 // There are still some metadatas. |
|
1849 // So, check their special contents. |
|
1850 CNcdNodeMetaData* metaData( NULL ); |
|
1851 HBufC8* data( NULL ); |
|
1852 CNcdNodeIdentifier* metaDataIdentifier( iDbMetaIdentifiers[ 0 ] ); |
|
1853 |
|
1854 // The read operation may leave for example with KErrNotFound if the |
|
1855 // item was not found. Ignore the error and just continue normally. |
|
1856 TRAP_IGNORE( |
|
1857 data = |
|
1858 NodeDbManager(). |
|
1859 ReadDataFromDatabaseL( *metaDataIdentifier, |
|
1860 NcdNodeClassIds::ENcdMetaData ) ); |
|
1861 |
|
1862 if ( data != NULL ) |
|
1863 { |
|
1864 CleanupStack::PushL( data ); |
|
1865 if ( *data != KNullDesC8 ) |
|
1866 { |
|
1867 TRAP_IGNORE( |
|
1868 metaData = |
|
1869 NodeFactory().CreateMetaDataL( *metaDataIdentifier, |
|
1870 *data ) ); |
|
1871 if ( metaData != NULL ) |
|
1872 { |
|
1873 DLINFO(("Metadata was found")); |
|
1874 |
|
1875 // Notice that the metadata should be closed not deleted! |
|
1876 CleanupClosePushL( *metaData ); |
|
1877 |
|
1878 // Now that we have the metadata. |
|
1879 // Check the icons |
|
1880 CNcdNodeIcon* icon( NULL ); |
|
1881 TRAP_IGNORE( icon = &metaData->IconL() ); |
|
1882 if ( icon != NULL ) |
|
1883 { |
|
1884 DLINFO(("icon check")); |
|
1885 // Check if the icon can be found from the icon list |
|
1886 // If its found then remove it from the list. |
|
1887 CNcdNodeIdentifier* iconIdentifier( NULL ); |
|
1888 for ( TInt i = iAllDbIconItems.Count(); i > 0; --i ) |
|
1889 { |
|
1890 iconIdentifier = iAllDbIconItems[ i - 1 ]; |
|
1891 if ( icon->IconId() == iconIdentifier->NodeId() ) |
|
1892 { |
|
1893 // Icon was found. |
|
1894 DLINFO((_L("Icon found and no need to remove: %S"), |
|
1895 &iconIdentifier->NodeId())); |
|
1896 delete iAllDbIconItems[ i - 1 ]; |
|
1897 iAllDbIconItems.Remove( i - 1 ); |
|
1898 } |
|
1899 } |
|
1900 } |
|
1901 |
|
1902 |
|
1903 const CNcdNodeScreenshot* screenshot( NULL ); |
|
1904 TRAP_IGNORE( screenshot = &metaData->ScreenshotL() ); |
|
1905 if ( screenshot != NULL ) |
|
1906 { |
|
1907 DLINFO(("screenshot check")); |
|
1908 // Check if the screenshot can be found from the icon list |
|
1909 // If its found then remove it from the list. |
|
1910 CNcdNodeIdentifier* screenshotIdentifier( NULL ); |
|
1911 for ( TInt i = iAllDbScreenshotItems.Count(); i > 0; --i ) |
|
1912 { |
|
1913 screenshotIdentifier = iAllDbScreenshotItems[ i - 1 ]; |
|
1914 TInt shotCount = screenshot->ScreenshotDownloadCount(); |
|
1915 DLTRACE(("Going through %d screenshots", shotCount )); |
|
1916 while ( shotCount-- ) |
|
1917 { |
|
1918 if ( screenshot->ScreenshotDownloadUri( shotCount ) |
|
1919 == screenshotIdentifier->NodeId() ) |
|
1920 { |
|
1921 // Screenshot was found. |
|
1922 DLINFO(("screenshot found")); |
|
1923 delete iAllDbScreenshotItems[ i - 1 ]; |
|
1924 iAllDbScreenshotItems.Remove( i - 1 ); |
|
1925 } |
|
1926 } |
|
1927 } |
|
1928 } |
|
1929 |
|
1930 // When metadata is deleted, also icons, |
|
1931 // etc. are deleted. |
|
1932 CleanupStack::PopAndDestroy( metaData ); |
|
1933 } |
|
1934 } |
|
1935 CleanupStack::PopAndDestroy( data ); |
|
1936 } |
|
1937 |
|
1938 // Remove the used identifier. |
|
1939 // So, next round will have a new identifier in the beginning of the array |
|
1940 delete iDbMetaIdentifiers[ 0 ]; |
|
1941 iDbMetaIdentifiers.Remove( 0 ); |
|
1942 |
|
1943 // Continue cleaning special cases |
|
1944 iCleanupState = ECleaningHangingSpecialCases; |
|
1945 } |
|
1946 else |
|
1947 { |
|
1948 // All the metadatas have been gone through. |
|
1949 // So, the special arrays will contain |
|
1950 // identifiers of the items that should be removed |
|
1951 // from the db. |
|
1952 // So, go to the next level. |
|
1953 iCleanupState = EFinishCleaningHangingSpecialCases; |
|
1954 } |
|
1955 |
|
1956 iStatus = KRequestPending; |
|
1957 SetActive(); |
|
1958 TRequestStatus* ptrStatus = &iStatus; |
|
1959 User::RequestComplete( ptrStatus, KErrNone ); |
|
1960 |
|
1961 DLTRACEOUT(("")); |
|
1962 } |
|
1963 |
|
1964 |
|
1965 void CNcdNodeCacheCleaner::FinishCleanSpecialHangingsL() |
|
1966 { |
|
1967 DLTRACEIN(("")); |
|
1968 |
|
1969 // Special arrays contain only the identifiers that |
|
1970 // belong to no metadata. |
|
1971 // So, delete those icons. |
|
1972 |
|
1973 DLINFO(("Remove icons from db: %d", iAllDbIconItems.Count())); |
|
1974 // Print array debug info into the log file |
|
1975 #ifdef NCD_NODE_CACHE_CLEANER_DEBUG_ARRAY_PRINT |
|
1976 DLINFO(("iAllDbIconItems array:")); |
|
1977 ArrayDebugPrint( iAllDbIconItems ); |
|
1978 #endif |
|
1979 |
|
1980 NodeDbManager(). |
|
1981 RemoveDataFromDatabaseL( iAllDbIconItems, |
|
1982 iIconCleanupTypes ); |
|
1983 iAllDbIconItems.ResetAndDestroy(); |
|
1984 |
|
1985 |
|
1986 DLINFO(("Remove screenshot from db: %d", iAllDbScreenshotItems.Count() )); |
|
1987 NodeDbManager(). |
|
1988 RemoveDataFromDatabaseL( iAllDbScreenshotItems, |
|
1989 iScreenshotCleanupTypes ); |
|
1990 iAllDbScreenshotItems.ResetAndDestroy(); |
|
1991 |
|
1992 // Everything is done here. |
|
1993 // So, go to the next level. |
|
1994 if ( iExcessCleanupStarted ) |
|
1995 { |
|
1996 // Because excess cleanup has already been started we have looped here back. |
|
1997 // So, skip the start and go directly to the correct cleaning procedure. |
|
1998 // Notice, that this also skips the expireds check, which is what we want |
|
1999 // because expired should be checked only once to save some time. If for some |
|
2000 // reason some nodes will expire during this cleanup it does not matter. |
|
2001 // Also, transparency and bundle checks are skipped, because they will be |
|
2002 // handled already during the first loop. |
|
2003 // They will be cleaned another time. |
|
2004 iCleanupState = ECleaningExcess; |
|
2005 } |
|
2006 else |
|
2007 { |
|
2008 // Start cleaning. |
|
2009 iCleanupState = EStartCleaningExcess; |
|
2010 } |
|
2011 iStatus = KRequestPending; |
|
2012 SetActive(); |
|
2013 TRequestStatus* ptrStatus = &iStatus; |
|
2014 User::RequestComplete( ptrStatus, KErrNone ); |
|
2015 |
|
2016 DLTRACEOUT(("")); |
|
2017 } |
|
2018 |
|
2019 |
|
2020 void CNcdNodeCacheCleaner::StartCleanExcessL() |
|
2021 { |
|
2022 DLTRACEIN(("")); |
|
2023 |
|
2024 TInt currentDbSize( |
|
2025 NodeDbManager().StorageSizeL( ClientUid(), |
|
2026 *iDoNotCleanNameSpaces ) ); |
|
2027 TInt compareSize( DbMaxSize() ); |
|
2028 |
|
2029 DLINFO(("current db size: %d, compare size: %d", |
|
2030 currentDbSize, compareSize)); |
|
2031 |
|
2032 TBool stopCleaning( ETrue ); |
|
2033 if ( compareSize < currentDbSize ) |
|
2034 { |
|
2035 // Get the current node items from the db. These will be gone through |
|
2036 // to decide what should be removed if the current database size is too |
|
2037 // big. |
|
2038 // This is the last change to update the list before the excess cleaning |
|
2039 // starts to loop. Then the node list should not be updated because |
|
2040 // that might result to a infinite loop, if deepest nodes can not be removed. |
|
2041 // We will not come back here if excess cleaning is looping. |
|
2042 // Notice that actually it does not matter if not all the items can not be |
|
2043 // checked here. They will be checked next time the cleaning is started. |
|
2044 SetAllDbStorageNodeItemsL(); |
|
2045 if ( iAllDbStorageNodeItems.Count() > 0 ) |
|
2046 { |
|
2047 // We still have to cleanup some more. |
|
2048 // So, make new request for the next step. |
|
2049 stopCleaning = EFalse; |
|
2050 iExcessCleanupStarted = ETrue; |
|
2051 |
|
2052 // Next check the root children, transparent and bundle nodes |
|
2053 // and after that expired nodes before actually removing the |
|
2054 // deepest nodes. |
|
2055 iCleanupState = EStartRootChildrenCheck; |
|
2056 } |
|
2057 } |
|
2058 |
|
2059 // Nothing to clean or the database size is small enough. |
|
2060 if ( stopCleaning ) |
|
2061 { |
|
2062 DLINFO(("Excess cleaned")); |
|
2063 // Just in case somebody has added something for removal. |
|
2064 // This call will update the node list once more from db |
|
2065 // and reset it when cleaning is done. The array update is ok |
|
2066 // here, because no additional loop will be done. |
|
2067 HandleCleaningL( ETrue, ETrue ); |
|
2068 // Nothing to do next |
|
2069 iCleanupState = EStopping; |
|
2070 } |
|
2071 |
|
2072 iStatus = KRequestPending; |
|
2073 SetActive(); |
|
2074 TRequestStatus* ptrStatus = &iStatus; |
|
2075 User::RequestComplete( ptrStatus, KErrNone ); |
|
2076 |
|
2077 DLTRACEOUT(("")); |
|
2078 } |
|
2079 |
|
2080 |
|
2081 void CNcdNodeCacheCleaner::StartRootChildrenCheckL() |
|
2082 { |
|
2083 DLTRACEIN(("")); |
|
2084 |
|
2085 // Bundles are always direct children of the root. |
|
2086 // Transparent folders are always direct children of the root |
|
2087 // or the bundles. |
|
2088 // So, start the checking from the root node and its children. |
|
2089 |
|
2090 CNcdNodeIdentifier* rootIdentifier = |
|
2091 NcdNodeIdentifierEditor::CreateRootIdentifierForClientLC( ClientUid() ); |
|
2092 |
|
2093 // As a default, make the next step to be cleaning expireds. |
|
2094 // This will skip the transparent and bundle checks. |
|
2095 // If the root is found below, then the state will be changed to the |
|
2096 // required value. |
|
2097 iCleanupState = ECleaningExpireds; |
|
2098 |
|
2099 // Here, we remove the root from the db node list if it is included there. |
|
2100 // The root should not be removed from the db later anyway. |
|
2101 // So, we may as well remove it from the db node list now. |
|
2102 iRootChildren.ResetAndDestroy(); |
|
2103 if ( RemoveIdentifier( *rootIdentifier, iAllDbStorageNodeItems ) ) |
|
2104 { |
|
2105 // Root was in the list. So, it can be found from db. |
|
2106 // Thus, we can try to create the root node here. |
|
2107 // Also, check the root children. |
|
2108 CNcdRootNode* root( NULL ); |
|
2109 CNcdNode* node( NULL ); |
|
2110 HBufC8* nodeData( NULL ); |
|
2111 |
|
2112 // The read operation may leave for example with KErrNotFound if the |
|
2113 // item was not found. Ignore the error and just continue normally. |
|
2114 TRAP_IGNORE( |
|
2115 nodeData = |
|
2116 NodeDbManager(). |
|
2117 ReadDataFromDatabaseL( *rootIdentifier, |
|
2118 NcdNodeClassIds::ENcdNode ) ); |
|
2119 if ( nodeData != NULL ) |
|
2120 { |
|
2121 CleanupStack::PushL( nodeData ); |
|
2122 if ( *nodeData != KNullDesC8 ) |
|
2123 { |
|
2124 TRAP_IGNORE( |
|
2125 node = |
|
2126 NodeFactory().CreateNodeL( *rootIdentifier, |
|
2127 *nodeData ) ); |
|
2128 |
|
2129 if ( node != NULL ) |
|
2130 { |
|
2131 // Push the node into the cleanup stack because checking |
|
2132 // may leave. |
|
2133 CleanupClosePushL( *node ); |
|
2134 if ( CNcdNodeFactory::NodeTypeL( *node ) |
|
2135 == CNcdNodeFactory::ENcdNodeRoot ) |
|
2136 { |
|
2137 // Only handle the root. |
|
2138 root = static_cast<CNcdRootNode*>( node ); |
|
2139 // Release the node from the cleanupstack. |
|
2140 // It will be put back as a root next. |
|
2141 CleanupStack::Pop( node ); |
|
2142 } |
|
2143 else |
|
2144 { |
|
2145 DLERROR(("The node with root identifier was not root.")) |
|
2146 DASSERT( EFalse ); |
|
2147 // Delete the node because it was not of the right type. |
|
2148 // The root will be left to NULL. |
|
2149 CleanupStack::PopAndDestroy( node ); |
|
2150 node = NULL; |
|
2151 } |
|
2152 } |
|
2153 |
|
2154 if ( root != NULL ) |
|
2155 { |
|
2156 // Notice that the node should be closed not deleted! |
|
2157 CleanupClosePushL( *root ); |
|
2158 const RPointerArray<CNcdChildEntity>& children = root->ChildArray(); |
|
2159 for ( TInt i = 0; i < children.Count(); i++ ) |
|
2160 { |
|
2161 // Because the root child will be added into the root list |
|
2162 // and those children are handled separately, remove |
|
2163 // the children also from the original node list. |
|
2164 // When iAllDbStorageNodeItems was initialized it contained all the |
|
2165 // identifiers of all the nodes in db. |
|
2166 // Notice, that if the children are not in the db node list, then |
|
2167 // they will not be removed from the db here. |
|
2168 |
|
2169 // So, check if the identifier is found from the db list and remove it |
|
2170 // if found. |
|
2171 if ( RemoveIdentifier( children[i]->Identifier(), iAllDbStorageNodeItems ) ) |
|
2172 { |
|
2173 // The root child was in the db list and it was removed. |
|
2174 // Now, insert the identifier into the temporary root list. |
|
2175 // So, these children will be checked later for transparency and |
|
2176 // bundle features. |
|
2177 AddIdentifierL( children[i]->Identifier(), iRootChildren ); |
|
2178 } |
|
2179 } |
|
2180 CleanupStack::PopAndDestroy( root ); |
|
2181 |
|
2182 // Because we got the root, then next step is to handle its |
|
2183 // children. |
|
2184 iCleanupState = ECheckRootChildren; |
|
2185 } |
|
2186 } |
|
2187 |
|
2188 // Delete node data. |
|
2189 CleanupStack::PopAndDestroy( nodeData ); |
|
2190 } |
|
2191 } |
|
2192 |
|
2193 CleanupStack::PopAndDestroy( rootIdentifier ); |
|
2194 |
|
2195 iStatus = KRequestPending; |
|
2196 SetActive(); |
|
2197 TRequestStatus* ptrStatus = &iStatus; |
|
2198 User::RequestComplete( ptrStatus, KErrNone ); |
|
2199 |
|
2200 DLTRACEOUT(("")); |
|
2201 } |
|
2202 |
|
2203 |
|
2204 void CNcdNodeCacheCleaner::CheckRootChildrenL() |
|
2205 { |
|
2206 DLTRACEIN(("")); |
|
2207 |
|
2208 if ( iRootChildren.Count() > 0 ) |
|
2209 { |
|
2210 DLINFO(("Root children in the array.")); |
|
2211 |
|
2212 // As a default loop here after this stuff is done. |
|
2213 // This way next loop will check if there are still more children |
|
2214 // to be checked. |
|
2215 iCleanupState = ECheckRootChildren; |
|
2216 |
|
2217 // All the children of the root should always be folders. |
|
2218 CNcdNode* node( NULL ); |
|
2219 CNcdNodeFolder* folder( NULL ); |
|
2220 HBufC8* nodeData( NULL ); |
|
2221 CNcdNodeIdentifier* rootChildIdentifier( iRootChildren[ 0 ] ); |
|
2222 |
|
2223 // The read operation may leave for example with KErrNotFound if the |
|
2224 // item was not found. Ignore the error and just continue normally. |
|
2225 TRAP_IGNORE( |
|
2226 nodeData = |
|
2227 NodeDbManager(). |
|
2228 ReadDataFromDatabaseL( *rootChildIdentifier, |
|
2229 NcdNodeClassIds::ENcdNode ) ); |
|
2230 if ( nodeData != NULL ) |
|
2231 { |
|
2232 CleanupStack::PushL( nodeData ); |
|
2233 if ( *nodeData != KNullDesC8 ) |
|
2234 { |
|
2235 TRAP_IGNORE( |
|
2236 node = |
|
2237 NodeFactory().CreateNodeL( *rootChildIdentifier, |
|
2238 *nodeData ) ); |
|
2239 if ( node != NULL ) |
|
2240 { |
|
2241 // Push the node into the cleanup stack because checking |
|
2242 // may leave. |
|
2243 CleanupClosePushL( *node ); |
|
2244 if ( CNcdNodeFactory::NodeTypeL( *node ) |
|
2245 == CNcdNodeFactory::ENcdNodeFolder ) |
|
2246 { |
|
2247 // Only handle the folders here. |
|
2248 // Else, the child can not be bundle or transparent. |
|
2249 folder = static_cast<CNcdNodeFolder*>( node ); |
|
2250 // Remove the node from the cleanup stack but do not delete |
|
2251 // it here. It will be used as a folder next. |
|
2252 CleanupStack::Pop( node ); |
|
2253 } |
|
2254 else |
|
2255 { |
|
2256 // Delete the node because it was not of the right type. |
|
2257 DLERROR(("The root child was not a folder. Has the specification been changed?")); |
|
2258 DASSERT( EFalse ); |
|
2259 CleanupStack::PopAndDestroy( node ); |
|
2260 } |
|
2261 } |
|
2262 |
|
2263 if ( folder != NULL ) |
|
2264 { |
|
2265 // Notice that the node should be closed not deleted! |
|
2266 CleanupClosePushL( *folder ); |
|
2267 CNcdNodeFactory::TNcdNodePurpose nodePurpose( |
|
2268 CNcdNodeFactory::NodePurposeL( *folder ) ); |
|
2269 |
|
2270 if ( nodePurpose == CNcdNodeFactory::ENcdTransparentNode ) |
|
2271 { |
|
2272 DLINFO(("Transparent folder.")); |
|
2273 const RPointerArray<CNcdChildEntity>& children = folder->ChildArray(); |
|
2274 for ( TInt i = 0; i < children.Count(); i++ ) |
|
2275 { |
|
2276 // Because the folder is transparent folder, |
|
2277 // remove the child identifiers from the node list. |
|
2278 // So, those transparent children will not be |
|
2279 // removed from the database later. |
|
2280 |
|
2281 // Notice, that if the children of the transparent folder |
|
2282 // are not in the db list, then they will not be removed |
|
2283 // from the db. |
|
2284 RemoveIdentifier( children[i]->Identifier(), |
|
2285 iAllDbStorageNodeItems ); |
|
2286 } |
|
2287 } |
|
2288 else if ( nodePurpose == CNcdNodeFactory::ENcdBundleNode ) |
|
2289 { |
|
2290 DLINFO(("Bundle folder")) |
|
2291 // Next, we have to handle the bundle children and check |
|
2292 // if they are transparent |
|
2293 iBundleChildren.ResetAndDestroy(); |
|
2294 const RPointerArray<CNcdChildEntity>& children = folder->ChildArray(); |
|
2295 for ( TInt i = 0; i < children.Count(); i++ ) |
|
2296 { |
|
2297 if ( RemoveIdentifier( children[i]->Identifier(), |
|
2298 iAllDbStorageNodeItems ) ) |
|
2299 { |
|
2300 // The identifier was found from the db list and removed. |
|
2301 // So, because the node can be found from the db, it can be |
|
2302 // created. So, add it into the bundle children temporary list. |
|
2303 AddIdentifierL( children[i]->Identifier(), iBundleChildren ); |
|
2304 } |
|
2305 } |
|
2306 |
|
2307 // Now that we got the children of the bundle folder, |
|
2308 // we should handle them separately during next active rounds. |
|
2309 iCleanupState = EHandleBundleChildren; |
|
2310 } |
|
2311 CleanupStack::PopAndDestroy( folder ); |
|
2312 } |
|
2313 } |
|
2314 |
|
2315 // Delete node data. |
|
2316 CleanupStack::PopAndDestroy( nodeData ); |
|
2317 } |
|
2318 |
|
2319 // Now, the root child has been checked. So, remove its identifier |
|
2320 // from the root array. |
|
2321 delete iRootChildren[ 0 ]; |
|
2322 iRootChildren.Remove( 0 ); |
|
2323 } |
|
2324 else |
|
2325 { |
|
2326 // No more children to be checked. |
|
2327 // So, skip to expireds. |
|
2328 iCleanupState = ECleaningExpireds; |
|
2329 } |
|
2330 |
|
2331 iStatus = KRequestPending; |
|
2332 SetActive(); |
|
2333 TRequestStatus* ptrStatus = &iStatus; |
|
2334 User::RequestComplete( ptrStatus, KErrNone ); |
|
2335 |
|
2336 DLTRACEOUT(("")); |
|
2337 } |
|
2338 |
|
2339 |
|
2340 void CNcdNodeCacheCleaner::HandleBundleChildrenL() |
|
2341 { |
|
2342 DLTRACEIN(("")); |
|
2343 |
|
2344 // Check all the bundle children for transparent folders. |
|
2345 |
|
2346 if ( iBundleChildren.Count() > 0 ) |
|
2347 { |
|
2348 DLINFO(("Bundle children in the array.")); |
|
2349 |
|
2350 // As a default loop here after this stuff is done. |
|
2351 // This way next loop will check if there are still more children |
|
2352 // to be checked. |
|
2353 iCleanupState = EHandleBundleChildren; |
|
2354 |
|
2355 // All the children of the root should always be folders. |
|
2356 CNcdNode* node( NULL ); |
|
2357 CNcdNodeFolder* folder( NULL ); |
|
2358 HBufC8* nodeData( NULL ); |
|
2359 CNcdNodeIdentifier* bundleChildIdentifier( iBundleChildren[ 0 ] ); |
|
2360 |
|
2361 // The read operation may leave for example with KErrNotFound if the |
|
2362 // item was not found. Ignore the error and just continue normally. |
|
2363 TRAP_IGNORE( |
|
2364 nodeData = |
|
2365 NodeDbManager(). |
|
2366 ReadDataFromDatabaseL( *bundleChildIdentifier, |
|
2367 NcdNodeClassIds::ENcdNode ) ); |
|
2368 if ( nodeData != NULL ) |
|
2369 { |
|
2370 CleanupStack::PushL( nodeData ); |
|
2371 if ( *nodeData != KNullDesC8 ) |
|
2372 { |
|
2373 TRAP_IGNORE( |
|
2374 node = |
|
2375 NodeFactory().CreateNodeL( *bundleChildIdentifier, |
|
2376 *nodeData ) ); |
|
2377 if ( node != NULL ) |
|
2378 { |
|
2379 // Push the node into the cleanup stack because checking |
|
2380 // may leave. |
|
2381 CleanupClosePushL( *node ); |
|
2382 if ( CNcdNodeFactory::NodeTypeL( *node ) |
|
2383 == CNcdNodeFactory::ENcdNodeFolder ) |
|
2384 { |
|
2385 // Only handle the folders here. |
|
2386 // Else, the child can not be transparent. |
|
2387 folder = static_cast<CNcdNodeFolder*>( node ); |
|
2388 } |
|
2389 // Remove the node from the cleanup stack but do not delete |
|
2390 // it here. It will be used as a folder next. |
|
2391 CleanupStack::Pop( node ); |
|
2392 } |
|
2393 |
|
2394 if ( folder != NULL ) |
|
2395 { |
|
2396 // Notice that the node should be closed not deleted! |
|
2397 CleanupClosePushL( *folder ); |
|
2398 CNcdNodeFactory::TNcdNodePurpose nodePurpose( |
|
2399 CNcdNodeFactory::NodePurposeL( *folder ) ); |
|
2400 |
|
2401 if ( nodePurpose == CNcdNodeFactory::ENcdTransparentNode ) |
|
2402 { |
|
2403 DLINFO(("Transparent folder.")); |
|
2404 const RPointerArray<CNcdChildEntity>& children = folder->ChildArray(); |
|
2405 for ( TInt i = 0; i < children.Count(); ++i ) |
|
2406 { |
|
2407 // Because the folder is transparent folder, |
|
2408 // remove the child identifiers from the node list. |
|
2409 // So, those transparent children will not be |
|
2410 // removed from the database. |
|
2411 |
|
2412 // Because the root child will be added into the root list |
|
2413 // and those children are handled separately, remove |
|
2414 // the children also from the original node list. |
|
2415 // Notice, that if the children are not in the db list, then |
|
2416 // there will not be any need to remove them from the db either. |
|
2417 // So, check it here. |
|
2418 RemoveIdentifier( children[i]->Identifier(), |
|
2419 iAllDbStorageNodeItems ); |
|
2420 } |
|
2421 } |
|
2422 CleanupStack::PopAndDestroy( folder ); |
|
2423 } |
|
2424 } |
|
2425 |
|
2426 // Delete node data. |
|
2427 CleanupStack::PopAndDestroy( nodeData ); |
|
2428 } |
|
2429 |
|
2430 // Now the root child has been checked. So, remove its identifier |
|
2431 // from the root array. |
|
2432 delete iBundleChildren[ 0 ]; |
|
2433 iBundleChildren.Remove( 0 ); |
|
2434 } |
|
2435 else |
|
2436 { |
|
2437 // No more bundle children to be checked. |
|
2438 // So, skip back to root child checking. |
|
2439 iCleanupState = ECheckRootChildren; |
|
2440 } |
|
2441 |
|
2442 iStatus = KRequestPending; |
|
2443 SetActive(); |
|
2444 TRequestStatus* ptrStatus = &iStatus; |
|
2445 User::RequestComplete( ptrStatus, KErrNone ); |
|
2446 |
|
2447 DLTRACEOUT(("")); |
|
2448 } |
|
2449 |
|
2450 |
|
2451 void CNcdNodeCacheCleaner::CleanExpiredsL() |
|
2452 { |
|
2453 DLTRACEIN(("")); |
|
2454 |
|
2455 // Notice that this function is looped if there are multiple nodes in the |
|
2456 // iAllDbStorageNodeItems. The array may not be uptodate if some nodes are |
|
2457 // inserted into the database during this active object looping. This does |
|
2458 // not matter because then only those new items will not be checked here. |
|
2459 // They will be checked when the cleaner is started next time. The array |
|
2460 // could be updated here every time but because db-actions may take time |
|
2461 // this is omitted here. |
|
2462 |
|
2463 // Notice that because the db items are sorted when the array is created, |
|
2464 // the removing of the children from the end list does not affect this index. |
|
2465 // So, if the current item is removed then also its children are removed, but |
|
2466 // the children exist after the parent in the array. |
|
2467 if ( iExpiredCleaningIndex < iAllDbStorageNodeItems.Count() ) |
|
2468 { |
|
2469 CNcdNodeIdentifier* itemIdentifier( |
|
2470 iAllDbStorageNodeItems[ iExpiredCleaningIndex ] ); |
|
2471 |
|
2472 DLINFO((_L("Cleaning index: %d, id: %S"), |
|
2473 iExpiredCleaningIndex, &itemIdentifier->NodeId())); |
|
2474 |
|
2475 // Set the expire to be true by default. So, if node can not be initialized |
|
2476 // correctly it will be removed also in that case. |
|
2477 TBool expired( ETrue ); |
|
2478 TInt depth( NcdNodeIdentifierEditor::NodeDepthL( *itemIdentifier ) ); |
|
2479 |
|
2480 if ( depth < 2 ) |
|
2481 { |
|
2482 DLINFO(("No need to check expiration. Depth: %d", depth)); |
|
2483 // Root nodes are not removed here. They will be updated by the |
|
2484 // other methods when they expire. |
|
2485 // Only items that are not root or direct children of root should |
|
2486 // be removed here. Notice that temporary items have depth zero, but |
|
2487 // their are cleaned during temporary cleaning. So, omitting them here |
|
2488 // is ok. |
|
2489 // Notice also, that items directly under the root should not be |
|
2490 // removed by the cleaner. For example, bundle folders should be |
|
2491 // updated only same time as root, because their info is only gotten |
|
2492 // during the root refresh. |
|
2493 expired = EFalse; |
|
2494 } |
|
2495 else |
|
2496 { |
|
2497 // Node will not be some root so, check the expiration here. |
|
2498 HBufC8* nodeData( NULL ); |
|
2499 |
|
2500 // The read operation may leave for example with KErrNotFound if the |
|
2501 // item was not found. Ignore the error and just continue normally. |
|
2502 TRAP_IGNORE( |
|
2503 nodeData = |
|
2504 NodeDbManager(). |
|
2505 ReadDataFromDatabaseL( *itemIdentifier, |
|
2506 NcdNodeClassIds::ENcdNode ) ); |
|
2507 if ( nodeData != NULL ) |
|
2508 { |
|
2509 if ( *nodeData != KNullDesC8 ) |
|
2510 { |
|
2511 CNcdNode* node( NULL ); |
|
2512 TRAP_IGNORE( |
|
2513 node = |
|
2514 NodeFactory().CreateNodeL( *itemIdentifier, |
|
2515 *nodeData ) ); |
|
2516 if ( node != NULL ) |
|
2517 { |
|
2518 // Notice that the node should be closed not deleted! |
|
2519 CNcdNodeLink* link = node->NodeLink(); |
|
2520 if ( link ) |
|
2521 { |
|
2522 // Check if the node should be marked not expired. |
|
2523 expired = link->IsExpired(); |
|
2524 } |
|
2525 node->Close(); |
|
2526 } |
|
2527 } |
|
2528 |
|
2529 // Delete node data. |
|
2530 delete nodeData; |
|
2531 } |
|
2532 } |
|
2533 |
|
2534 if ( expired ) |
|
2535 { |
|
2536 DLINFO((_L("Expired: %S"), &itemIdentifier->NodeId())); |
|
2537 // Because the node was expired, or it could not be created for some reason |
|
2538 // correctly. Add the identifier to the cleanup list if it is allowed action. |
|
2539 // This function knows how to move the item into the waiting list. |
|
2540 AddCleanupIdentifierL( *itemIdentifier ); |
|
2541 |
|
2542 // Remove the data from its original place. Notice that identifier |
|
2543 // is copied in the function above. |
|
2544 delete itemIdentifier; |
|
2545 iAllDbStorageNodeItems.Remove( iExpiredCleaningIndex ); |
|
2546 |
|
2547 // HandleCleaningL and the functions it uses can handle the removing of the |
|
2548 // item from the db array. |
|
2549 HandleCleaningL( EFalse, EFalse ); |
|
2550 } |
|
2551 else |
|
2552 { |
|
2553 // Increase the cleaning index by one for the next round |
|
2554 // because the current item was not removed. |
|
2555 ++iExpiredCleaningIndex; |
|
2556 } |
|
2557 |
|
2558 // There may still be something to be done. |
|
2559 // So, make new request for the next step. |
|
2560 iCleanupState = ECleaningExpireds; |
|
2561 } |
|
2562 else |
|
2563 { |
|
2564 DLINFO(("Expireds cleaned")); |
|
2565 // Reset the cleaning index. |
|
2566 iExpiredCleaningIndex = 0; |
|
2567 |
|
2568 // Because expireds are cleaned now. Check if the excess nodes should |
|
2569 // still be removed from the database to free enough space. |
|
2570 iCleanupState = ECleaningExcess; |
|
2571 } |
|
2572 |
|
2573 iStatus = KRequestPending; |
|
2574 SetActive(); |
|
2575 TRequestStatus* ptrStatus = &iStatus; |
|
2576 User::RequestComplete( ptrStatus, KErrNone ); |
|
2577 |
|
2578 DLTRACEOUT(("")); |
|
2579 } |
|
2580 |
|
2581 |
|
2582 void CNcdNodeCacheCleaner::CleanExcessL() |
|
2583 { |
|
2584 DLTRACEIN(("")); |
|
2585 |
|
2586 TInt currentDbSize( |
|
2587 NodeDbManager().StorageSizeL( ClientUid(), |
|
2588 *iDoNotCleanNameSpaces ) ); |
|
2589 |
|
2590 // Because cleaning has been started the compare size should be somewhat |
|
2591 // less than the max accepted size after the cleaning operation. |
|
2592 TInt compareSize( DbMaxSize() / KMaxSizeDivider ); |
|
2593 |
|
2594 DLINFO(("current db size: %d, compare size: %d", |
|
2595 currentDbSize, compareSize)); |
|
2596 |
|
2597 // Here the node list may not be uptodate if database has changed during the |
|
2598 // active loops. But do not update it, because otherwise we might try to remove |
|
2599 // same node over and over again. If the deepest nodes are not allowed to be |
|
2600 // removed. |
|
2601 TInt itemCount( iAllDbStorageNodeItems.Count() ); |
|
2602 TInt deepestDepth( 0 ); |
|
2603 |
|
2604 if ( itemCount > 0 ) |
|
2605 { |
|
2606 // Get the depth of the final node in db list. This is the deepest node because |
|
2607 // the array has been sorted. |
|
2608 deepestDepth = |
|
2609 NcdNodeIdentifierEditor::NodeDepthL( *iAllDbStorageNodeItems[ itemCount - 1 ] ); |
|
2610 if ( deepestDepth < 2 ) |
|
2611 { |
|
2612 DLINFO(("Do not clean excess any more. Depth: %d", deepestDepth)); |
|
2613 // Because we should not delete root or its direct children here. |
|
2614 // Reset the node items array and reset the item count. |
|
2615 // Because the item count will be zero now, |
|
2616 // the cleaning will continue to the stopping state next. |
|
2617 iAllDbStorageNodeItems.ResetAndDestroy(); |
|
2618 itemCount = iAllDbStorageNodeItems.Count(); |
|
2619 } |
|
2620 } |
|
2621 |
|
2622 // Start actual cleaning if it is still required. |
|
2623 if ( itemCount > 0 |
|
2624 && compareSize < currentDbSize ) |
|
2625 { |
|
2626 DLINFO(("Excess cleaning is required")); |
|
2627 |
|
2628 DLINFO(("Deepest depth: %d", deepestDepth)); |
|
2629 |
|
2630 CNcdNodeIdentifier* identifier( NULL ); |
|
2631 for ( TInt i = itemCount; i > 0; --i ) |
|
2632 { |
|
2633 identifier = iAllDbStorageNodeItems[ i - 1 ]; |
|
2634 if ( deepestDepth != NcdNodeIdentifierEditor::NodeDepthL( *identifier ) ) |
|
2635 { |
|
2636 // Only remove items that have the same depth at once. |
|
2637 DLINFO(("All the same depth nodes added.")); |
|
2638 break; |
|
2639 } |
|
2640 |
|
2641 // This identifier has also the same depth. |
|
2642 // Insert it into the cleanup array if removal is allowed. |
|
2643 AddCleanupIdentifierL( *iAllDbStorageNodeItems[ i - 1 ] ); |
|
2644 |
|
2645 // Remove the data from its original place. Notice that identifier |
|
2646 // is copied in the function above. |
|
2647 delete iAllDbStorageNodeItems[ i - 1 ]; |
|
2648 iAllDbStorageNodeItems.Remove( i - 1 ); |
|
2649 |
|
2650 DLINFO(("Same depth id added to array")); |
|
2651 } |
|
2652 |
|
2653 // Clean the nodes from the database. |
|
2654 HandleCleaningL( EFalse, EFalse ); |
|
2655 |
|
2656 // We may still have to cleanup some more. |
|
2657 // So, make new request for the next step. |
|
2658 // This will clean the metadata related data such as icons. |
|
2659 // The cleaning will loop until enough space is released. |
|
2660 iCleanupState = ECleaningTemporaryNodes; |
|
2661 } |
|
2662 else |
|
2663 { |
|
2664 DLINFO(("Excess cleaned")); |
|
2665 // Just in case somebody has added something for removal |
|
2666 // while waiting this new round. |
|
2667 // Because we are about to end the cleaning we can update the |
|
2668 // node list one more time before final removing. |
|
2669 HandleCleaningL( ETrue, ETrue ); |
|
2670 |
|
2671 // Nothing to do next |
|
2672 iCleanupState = EStopping; |
|
2673 } |
|
2674 |
|
2675 iStatus = KRequestPending; |
|
2676 SetActive(); |
|
2677 TRequestStatus* ptrStatus = &iStatus; |
|
2678 User::RequestComplete( ptrStatus, KErrNone ); |
|
2679 |
|
2680 DLTRACEOUT(("")); |
|
2681 } |
|
2682 |
|
2683 |
|
2684 void CNcdNodeCacheCleaner::StoppingL() |
|
2685 { |
|
2686 DLTRACEIN(("")); |
|
2687 |
|
2688 // This function resets the member variables to default values. |
|
2689 // Also, the priority of this active object is set to the default. |
|
2690 ResetState(); |
|
2691 |
|
2692 DLTRACEOUT(("")); |
|
2693 } |
|
2694 |