|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // CMSVCACHEVISIBLEFOLDER.CPP |
|
15 // |
|
16 // |
|
17 |
|
18 #include "msvcachevisiblefolder.h" |
|
19 #include "msventryfreepool.h" |
|
20 #include "msvcacheindextableentry.h" |
|
21 #include "msvdbadapter.h" |
|
22 #include "msvcacheentry.h" |
|
23 |
|
24 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT) |
|
25 #include "msvindexadapter.h" |
|
26 #endif |
|
27 |
|
28 #define BLOCK_SIZE 64 |
|
29 #define BLOCK_THRESHOLD 16 |
|
30 |
|
31 /** |
|
32 Literal Definition |
|
33 */ |
|
34 |
|
35 _LIT8(KId, "id "); |
|
36 _LIT8(KBetween, "between "); |
|
37 _LIT8(KAnd, " and "); |
|
38 _LIT8(KOr, " or "); |
|
39 _LIT8(KIn, " in "); |
|
40 _LIT8(KRtBrace, ") "); |
|
41 _LIT8(KLtBrace, "( "); |
|
42 _LIT8(KComma, ", "); |
|
43 _LIT8(KSemiColon, ";"); |
|
44 _LIT8(KOrder, " order by id ASC"); |
|
45 |
|
46 |
|
47 |
|
48 /** |
|
49 CMsvCacheVisibleFolder |
|
50 */ |
|
51 const TInt CMsvCacheVisibleFolder::iOffset = _FOFF(CMsvCacheVisibleFolder, iDlink); |
|
52 |
|
53 |
|
54 /** |
|
55 NewL() |
|
56 @param TMsvId: Visible Folder TMsvId. |
|
57 @return The newly created Visible Folder. |
|
58 |
|
59 It returns an instance of CMsvCacheVisibleFolder class. |
|
60 */ |
|
61 CMsvCacheVisibleFolder* CMsvCacheVisibleFolder::NewL(TMsvId aId) |
|
62 { |
|
63 CMsvCacheVisibleFolder *self = new(ELeave) CMsvCacheVisibleFolder(aId); |
|
64 return self; |
|
65 } |
|
66 |
|
67 |
|
68 /** |
|
69 NewL() |
|
70 @param TMsvId: Visible Folder TMsvId. |
|
71 @param RPointerArray<CMsvCacheEntry>: Rpointer Reference to children Entries |
|
72 @return The newly created Visible Folder. |
|
73 It returns an instance of CMsvCacheVisibleFolder class. |
|
74 */ |
|
75 CMsvCacheVisibleFolder* CMsvCacheVisibleFolder::NewL(TMsvId aId, RPointerArray<CMsvCacheEntry>& aEntries) |
|
76 { |
|
77 CMsvCacheVisibleFolder *self = new(ELeave) CMsvCacheVisibleFolder(aId); |
|
78 CleanupStack::PushL(self); |
|
79 self->ConstructL(aEntries); |
|
80 CleanupStack::Pop(); |
|
81 return self; |
|
82 } |
|
83 |
|
84 |
|
85 /** |
|
86 ~CMsvCacheVisibleFolder() |
|
87 @param None. |
|
88 @return None. |
|
89 Destructor for the CMsvCacheVisibleFolder class. |
|
90 */ |
|
91 CMsvCacheVisibleFolder::~CMsvCacheVisibleFolder() |
|
92 { |
|
93 iIndexTable.ResetAndDestroy(); |
|
94 iIndexTable.Close(); |
|
95 } |
|
96 |
|
97 |
|
98 /** |
|
99 CMsvCacheVisibleFolder() |
|
100 @param None. |
|
101 @return None. |
|
102 Constructor for the CMsvCacheVisibleFolder class. |
|
103 */ |
|
104 CMsvCacheVisibleFolder::CMsvCacheVisibleFolder(TMsvId aId) |
|
105 :iFlags(EMsvCacheVisibleFolderClearFlag) |
|
106 { |
|
107 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT) |
|
108 // Keep standard id unmasked. |
|
109 if(IsStandardId(aId)) |
|
110 { |
|
111 iVisibleFolderId = UnmaskTMsvId(aId); |
|
112 } |
|
113 else |
|
114 { |
|
115 iVisibleFolderId = aId; |
|
116 } |
|
117 // Store drive id information. |
|
118 iDriveId = GetDriveId(aId); |
|
119 #else |
|
120 iVisibleFolderId = aId; |
|
121 #endif |
|
122 } |
|
123 |
|
124 |
|
125 /** |
|
126 ConstructL() |
|
127 @param RPointerArray<CMsvCacheEntry>& aEntries. |
|
128 @return None. |
|
129 Two Phase constructor for adding the entries passed during the creation |
|
130 of the CMsvCacheVisibleFolder object. |
|
131 */ |
|
132 void CMsvCacheVisibleFolder::ConstructL(RPointerArray<CMsvCacheEntry>& aEntries) |
|
133 { |
|
134 AddEntryListL(aEntries, ETrue); |
|
135 } |
|
136 |
|
137 |
|
138 /** |
|
139 AddEntryL() |
|
140 @param CMsvCacheEntry&: CMsvCacheEntry Reference. |
|
141 @return none. |
|
142 |
|
143 The function Adds an Entry into the cache block |
|
144 01. check if the parent id of the entry exists; Incase if it is a child of a non-visible folder |
|
145 we cannot add it unless the parent is present |
|
146 02. Check if The Parent Id of the Entry is same as the visible folder id. |
|
147 02.1. If yes, Set the Flag to Update the ChildMsvId array of the parent. |
|
148 03. If there is no Index Table created, Create a new index table entry |
|
149 and add the entry into the table |
|
150 04. Iterate the Indextable entries and add the entry in the appropriate |
|
151 IndexTable entry Block and update the child msvid array of the parent |
|
152 If the entry is not an immediate child. |
|
153 05. In case index table is not yet created, then there is a possibility that entry Id does not fall in |
|
154 the first block range but it can be added before the first block. In such case, add the entry in the first |
|
155 block itself and update the first block range. |
|
156 06. If the Entry doesnt fall in the range of any of the blocks add the Entry |
|
157 in the last block and update the child MsvId array if the entry is not an immediate child. |
|
158 */ |
|
159 void CMsvCacheVisibleFolder::AddEntryL(CMsvCacheEntry*& aEntry, TBool aReplace /* DEFAULT = EFalse */) |
|
160 { |
|
161 TBool updateChild=EFalse; |
|
162 TInt noOfIndexTableEntries = iIndexTable.Count(); |
|
163 TMsvId entryId = aEntry->Entry().Id(); |
|
164 TMsvId parentId = aEntry->Entry().Parent(); |
|
165 |
|
166 |
|
167 // 02. Check if The Parent Id of the Entry is same as the visible folder id. |
|
168 if(parentId != iVisibleFolderId) |
|
169 { |
|
170 // 02.1. If yes, Set the Flag to Update the ChildMsvId array of the parent. |
|
171 updateChild = ETrue; |
|
172 } |
|
173 |
|
174 // 03. If there is no Index Table created, Create a new index table entry |
|
175 // and add the entry into the table |
|
176 if(NULL == noOfIndexTableEntries ) |
|
177 { |
|
178 CMsvCacheIndexTableEntry* tableEntry = CMsvCacheIndexTableEntry::NewLC(aEntry); |
|
179 tableEntry->SetMinMsvIdRange(aEntry->GetId()); |
|
180 tableEntry->SetMaxMsvIdRange(aEntry->GetId()); |
|
181 if(aEntry->Entry().Parent() != iVisibleFolderId) |
|
182 { |
|
183 tableEntry->SetGrandChildPresent(); |
|
184 } |
|
185 iIndexTable.AppendL(tableEntry); |
|
186 CleanupStack::Pop(); |
|
187 return; |
|
188 } |
|
189 |
|
190 // 04. Iterate the Indextable entries and add the entry in the appropriate |
|
191 // IndexTable entry Block and update the child msvid array of the parent |
|
192 // If the entry is not an immediate child. |
|
193 for(TInt index=0; index < noOfIndexTableEntries; ++index) |
|
194 { |
|
195 if(iIndexTable[index]->IsInRange(entryId)) |
|
196 { |
|
197 iIndexTable[index]->AddEntryL(aEntry, aReplace); |
|
198 if(aEntry->Entry().Parent() != iVisibleFolderId) |
|
199 { |
|
200 iIndexTable[index]->SetGrandChildPresent(); |
|
201 } |
|
202 if(updateChild) |
|
203 { |
|
204 UpdateChildMsvIdsL(parentId, entryId); |
|
205 } |
|
206 return; |
|
207 } |
|
208 //05. In case index table is not yet created, then there is a possibility that entry Id does not fall in |
|
209 // the first block range but it can be added before the first block. In such case, add the entry in the first |
|
210 // block itself and update the first block range. |
|
211 if((NULL == index) && (entryId < iIndexTable[index]->GetMinMsvIdRange())) |
|
212 { |
|
213 iIndexTable[index]->AddEntryL(aEntry, aReplace); |
|
214 if(aEntry->Entry().Parent() != iVisibleFolderId) |
|
215 { |
|
216 iIndexTable[index]->SetGrandChildPresent(); |
|
217 } |
|
218 if(updateChild) |
|
219 { |
|
220 UpdateChildMsvIdsL(parentId, entryId); |
|
221 } |
|
222 return; |
|
223 } |
|
224 } |
|
225 |
|
226 // 06. If the Entry doesnt fall in the range of any of the blocks add the Entry |
|
227 // in the last block and update the child MsvId array if the entry is not an immediate child. |
|
228 iIndexTable[noOfIndexTableEntries-1]->AddEntryL(aEntry, aReplace); |
|
229 if(aEntry->Entry().Parent() != iVisibleFolderId) |
|
230 { |
|
231 iIndexTable[noOfIndexTableEntries-1]->SetGrandChildPresent(); |
|
232 } |
|
233 if(entryId > iIndexTable[noOfIndexTableEntries-1]->GetMaxMsvIdRange()) |
|
234 { |
|
235 iIndexTable[noOfIndexTableEntries-1]->SetMaxMsvIdRange(entryId); |
|
236 } |
|
237 if(updateChild) |
|
238 { |
|
239 UpdateChildMsvIdsL(parentId, entryId); |
|
240 } |
|
241 } |
|
242 |
|
243 |
|
244 /** |
|
245 AddEntryListL() |
|
246 @param RPointerArray<CMsvCacheEntry>&: Entries to be added under this visible folder which are in sorted order. |
|
247 @param TBool: Set to true if the passed array of CMsvCacheEntry contains the complete childrens of VisibleFolder |
|
248 @return none. |
|
249 |
|
250 The function Adds a set of Entries into the cache |
|
251 1. If entry list is NULL, return to the caller. |
|
252 2.check if the IndexTable is not created then, |
|
253 2.1 Yes, create the required number of index tables and append the entries in the appropriate blocks |
|
254 2.2 No, Check if getchildren has already been performed on this VisibleFolder |
|
255 2.2.1 Yes Assuming the input list is already sorted, Add the entries in the appropriate |
|
256 blocks depending on the range of each blocks |
|
257 2.2.1.1 The remaining entries should be put in the last block |
|
258 2.3 No, check if getchildren has'nt been performed on this VisibleFolder |
|
259 2.3.1 Check If index table exists |
|
260 2.3.1.1 Yes,Create a Copy of the existing index table entries |
|
261 2.3.1.2 create the required number of index tables and append the entries in the appropriate blocks |
|
262 2.3.1.3 check the copy of the previous list if any entry exists |
|
263 2.3.1.3 copy back only the locked entries or entires |
|
264 which are not immediate childrens of the visible folder or |
|
265 entries which are locked and release the remaining entries |
|
266 2.3.2 If indextable is not present add the entries in the appropriate blocks |
|
267 */ |
|
268 void CMsvCacheVisibleFolder::AddEntryListL(RPointerArray<CMsvCacheEntry>& aEntries, TBool aIsCompleteChildOfFolder /*DEFAULT = EFalse */) |
|
269 { |
|
270 //1. If entry list is NULL, return to the caller. |
|
271 TInt size = aEntries.Count(); |
|
272 if(size <= 0) |
|
273 { |
|
274 if(!size && aIsCompleteChildOfFolder) |
|
275 { |
|
276 SetComplete(ETrue); |
|
277 } |
|
278 return; |
|
279 } |
|
280 |
|
281 TBool isGrandChildrenAdded = EFalse; |
|
282 if(aEntries[0]->Entry().Parent() != iVisibleFolderId) |
|
283 { |
|
284 isGrandChildrenAdded = ETrue; |
|
285 } |
|
286 |
|
287 |
|
288 //2.check if the IndexTable is not created then, |
|
289 if(0 == iIndexTable.Count()) |
|
290 { |
|
291 //2.1 Yes, create the required number of index tables and append the entries in the appropriate blocks |
|
292 SplitAndAppendL(aEntries); |
|
293 } |
|
294 else |
|
295 { |
|
296 //2.2 No, Check if getchildren has already been performed on this VisibleFolder |
|
297 if(IsComplete()) |
|
298 { |
|
299 TInt tmpIndex = 0, index = 0; |
|
300 //2.2.1 Yes Assuming the input list is already sorted, Add the entries in the appropriate |
|
301 // blocks depending on the range of each blocks |
|
302 for(TInt tableIndex = 0; tableIndex < iIndexTable.Count(); ++tableIndex) |
|
303 { |
|
304 while((tmpIndex < size) && (iIndexTable[tableIndex]->GetMaxMsvIdRange() >= aEntries[tmpIndex]->GetId())) |
|
305 { |
|
306 ++tmpIndex; |
|
307 } |
|
308 if(index != tmpIndex) |
|
309 { |
|
310 // No need to set Max/Min range, as IsComplete() is true. |
|
311 iIndexTable[tableIndex]->AddEntrySetL(aEntries, index, tmpIndex-index); |
|
312 if(isGrandChildrenAdded) |
|
313 { |
|
314 iIndexTable[tableIndex]->SetGrandChildPresent(); |
|
315 } |
|
316 } |
|
317 |
|
318 if(aIsCompleteChildOfFolder) |
|
319 { |
|
320 iIndexTable[tableIndex]->ClearDirty(); |
|
321 } |
|
322 |
|
323 if( tmpIndex >= size ) |
|
324 { |
|
325 break; |
|
326 } |
|
327 index = tmpIndex; |
|
328 |
|
329 } |
|
330 |
|
331 //2.2.1.1 The remaining entries should be put in the last block |
|
332 tmpIndex = size - tmpIndex; // Amount of entries remaining. |
|
333 if(tmpIndex > BLOCK_THRESHOLD) |
|
334 { |
|
335 SplitAndAppendL(aEntries, index); |
|
336 } |
|
337 else if(0 != tmpIndex) |
|
338 { |
|
339 TMsvId maxId = aEntries[size-1]->GetId(); |
|
340 iIndexTable[iIndexTable.Count()-1]->AddEntrySetL(aEntries, index, tmpIndex); |
|
341 if(isGrandChildrenAdded) |
|
342 { |
|
343 iIndexTable[iIndexTable.Count()-1]->SetGrandChildPresent(); |
|
344 } |
|
345 iIndexTable[iIndexTable.Count()-1]->SetMaxMsvIdRange(maxId); |
|
346 } |
|
347 } |
|
348 //2.3 No, check if getchildren has'nt been performed on this VisibleFolder |
|
349 else |
|
350 { |
|
351 //2.3.1 Check If index table exists |
|
352 if(aIsCompleteChildOfFolder) |
|
353 { |
|
354 // 2.3.1.1 Yes,Create a Copy of the existing index table entries |
|
355 RPointerArray<CMsvCacheIndexTableEntry> tmpTable; |
|
356 CleanupClosePushL(tmpTable); |
|
357 for(TInt index=0; index<iIndexTable.Count(); index++) |
|
358 { |
|
359 tmpTable.AppendL(iIndexTable[index]); |
|
360 } |
|
361 iIndexTable.Reset(); |
|
362 // 2.3.1.2 create the required number of index tables and append the entries in the appropriate blocks |
|
363 SplitAndAppendL(aEntries); |
|
364 // 2.3.1.3 check the copy of the previous list if any entry exists |
|
365 while(tmpTable.Count()) |
|
366 { |
|
367 if(tmpTable[0]->BlockPtr() != NULL) |
|
368 { |
|
369 RPointerArray<CMsvCacheEntry>* blockPtr = tmpTable[0]->BlockPtr(); |
|
370 TInt count = blockPtr->Count(); |
|
371 while(count--) |
|
372 { |
|
373 // 2.3.1.3 copy back only the locked entries or entires |
|
374 //which are not immediate childrens of the visible folder or |
|
375 //entries which are locked and release the remaining entries |
|
376 if( ((*blockPtr)[count]->Entry().Parent() != iVisibleFolderId) || !((*blockPtr)[count]->IsEntrySwappable()) ) |
|
377 { |
|
378 AddEntryL((*blockPtr)[count], ETrue); |
|
379 } |
|
380 else |
|
381 { |
|
382 CMsvEntryFreePool::Instance()->ReleaseEntry((*blockPtr)[count]); |
|
383 } |
|
384 } |
|
385 blockPtr->Reset(); |
|
386 blockPtr->Close(); |
|
387 } |
|
388 delete tmpTable[0]; |
|
389 tmpTable.Remove(0); |
|
390 } |
|
391 tmpTable.Reset(); |
|
392 CleanupStack::PopAndDestroy(); |
|
393 } |
|
394 //2.3.2 If indextable is not present add the entries in the appropriate blocks |
|
395 else |
|
396 { |
|
397 TInt size = aEntries.Count(); |
|
398 while(size--) |
|
399 { |
|
400 AddEntryL(aEntries[size]); |
|
401 } |
|
402 } |
|
403 } |
|
404 } |
|
405 |
|
406 if(aIsCompleteChildOfFolder) |
|
407 { |
|
408 SetComplete(ETrue); |
|
409 } |
|
410 } |
|
411 |
|
412 |
|
413 /** |
|
414 SplitAndAppendL() |
|
415 @param RPointerArray<CMsvCacheEntry>&: Entries to be added under this visible folder which are in sorted order. |
|
416 @param TInt: Maximum range of the last block under this visible folder |
|
417 @return none. |
|
418 |
|
419 The function Adds a set Entries into the cache |
|
420 1. Calculate the number of blocks to be created. |
|
421 2. If remaining entries are less then BLOCK_THRESHOLD they will be appended to last block. |
|
422 3. Create new indextable entries and then add the child entries into the appropriate blocks |
|
423 4. If few entries are still left, append them to the last block. |
|
424 */ |
|
425 void CMsvCacheVisibleFolder::SplitAndAppendL(RPointerArray<CMsvCacheEntry>& aEntryList, TInt aInitIndex /*(DEFAULT=0)*/) |
|
426 { |
|
427 //1. Calculate the number of blocks to be created. |
|
428 TInt entriesToBeAdded = aEntryList.Count() - aInitIndex; |
|
429 TInt blocksToCreate = entriesToBeAdded /(TInt) BLOCK_SIZE; |
|
430 TInt aLastMaxRange = -1; |
|
431 TBool isGrandChildrenAdded = EFalse; |
|
432 |
|
433 TInt blocksCreated = iIndexTable.Count(); |
|
434 if(blocksCreated != 0) |
|
435 { |
|
436 aLastMaxRange = iIndexTable[blocksCreated-1]->GetMaxMsvIdRange(); |
|
437 } |
|
438 if( aEntryList[aInitIndex]->Entry().Parent() != iVisibleFolderId) |
|
439 { |
|
440 isGrandChildrenAdded = ETrue; |
|
441 } |
|
442 |
|
443 //2. If remaining entries are less then BLOCK_THRESHOLD they will be appended to last block. |
|
444 if( (BLOCK_THRESHOLD < (entriesToBeAdded % BLOCK_SIZE)) || |
|
445 ( (NULL == (blocksCreated+blocksToCreate)) && (entriesToBeAdded <= BLOCK_THRESHOLD) ) |
|
446 ) |
|
447 { |
|
448 ++ blocksToCreate; |
|
449 } |
|
450 |
|
451 TInt blockSize = entriesToBeAdded/blocksToCreate; |
|
452 |
|
453 //3. Create new indextable entries and then add the child entries into the appropriate blocks |
|
454 for(TInt index = 0; index < blocksToCreate; ++index) |
|
455 { |
|
456 CMsvCacheIndexTableEntry* newTableEntry = CMsvCacheIndexTableEntry::NewLC(aEntryList, aInitIndex, blockSize); |
|
457 if(isGrandChildrenAdded) |
|
458 { |
|
459 newTableEntry->SetGrandChildPresent(); |
|
460 } |
|
461 TMsvId maxRange = aEntryList[aInitIndex+blockSize-1]->GetId(); |
|
462 newTableEntry->SetMinMsvIdRange(++aLastMaxRange); |
|
463 newTableEntry->SetMaxMsvIdRange(maxRange); |
|
464 iIndexTable.AppendL(newTableEntry); |
|
465 aLastMaxRange = maxRange; |
|
466 aInitIndex += blockSize; |
|
467 |
|
468 CleanupStack::Pop(); |
|
469 } |
|
470 |
|
471 //4. If few entries are still left, append them to the last block. |
|
472 entriesToBeAdded = aEntryList.Count() - aInitIndex; |
|
473 if(entriesToBeAdded > 0) |
|
474 { |
|
475 CMsvCacheIndexTableEntry* newTableEntry = iIndexTable[iIndexTable.Count()-1]; |
|
476 newTableEntry->AddEntrySetL(aEntryList, aInitIndex, entriesToBeAdded); |
|
477 if(isGrandChildrenAdded) |
|
478 { |
|
479 newTableEntry->SetGrandChildPresent(); |
|
480 } |
|
481 if(newTableEntry->GetMaxMsvIdRange() < aEntryList[aEntryList.Count()-1]->GetId()) |
|
482 { |
|
483 newTableEntry->SetMaxMsvIdRange(aEntryList[aEntryList.Count()-1]->GetId()); |
|
484 } |
|
485 } |
|
486 } |
|
487 |
|
488 |
|
489 |
|
490 /** |
|
491 GetEntry() |
|
492 @param TMsvId: TMsvId for the Entry to be fetched |
|
493 @param CMsvCacheEntry&: CMsvCacheEntry Reference. |
|
494 @return TBool: Cache Hit or Cache Miss. |
|
495 |
|
496 The function Gets an Entry from the cache block |
|
497 1. Find the IndexTable entry where the Range of the TMsvId falls. |
|
498 2. Get the Entry in the Block to which it belongs |
|
499 */ |
|
500 TBool CMsvCacheVisibleFolder::GetEntry(TMsvId aId, CMsvCacheEntry*& aEntry) |
|
501 { |
|
502 // 1. Find the IndexTable entry where the Range of the TMsvId falls. |
|
503 for(TInt index=0; index < iIndexTable.Count(); ++index) |
|
504 { |
|
505 if(iIndexTable[index]->IsInRange(aId)) |
|
506 { |
|
507 //2. Get the Entry in the Block to which it belongs |
|
508 return(iIndexTable[index]->GetEntry(aId, aEntry)); |
|
509 } |
|
510 } |
|
511 return EFalse; |
|
512 } |
|
513 |
|
514 |
|
515 /** |
|
516 GetChildren() |
|
517 @param TMsvId: TMsvId of the Parent Entry whose children are to be fetched. |
|
518 @param RPointerArray<const CMsvCacheEntry>&: Array to fill childrens |
|
519 @return TBool: Cache Hit or Cache Miss. |
|
520 |
|
521 The function Gets the childrens of the parent from the cache |
|
522 1. Check if the Parent Id is same as the Visible Folder |
|
523 1.1 yes, check if getchildren has'nt already been performed on this visible folder entry |
|
524 or all the blocks present are dirty. |
|
525 1.1.1 Then Fetch and fill all the childrens then return the same to the caller |
|
526 1.2 yes, check if getchildren has beeb performed on this visible folder |
|
527 1.2.1 yes, only few blocks are dirty, so fetch and fill the dirty blocks |
|
528 2. If the if the Parent Id is not same as the Visible Folder |
|
529 2.1 check if the parent of the children is present |
|
530 2.2 If parent is a visible folder |
|
531 2.2.1 Yes, then return Efalse to the caller stating that |
|
532 the parent is a visible folder |
|
533 2.3 Check if Getchildren has'nt been performed on the parent |
|
534 2.3.1 Yes, Fetch and fill the childrens of the Parent from DB |
|
535 2.4 Check If GetChildren has been already performed |
|
536 2.4.1 If childrens are available in the cache get them |
|
537 2.4.2 else fetch the children from DB add them to cache |
|
538 */ |
|
539 TBool CMsvCacheVisibleFolder::GetChildrenL(TMsvId aId, CMsvDBAdapter* aDbAdapter, RPointerArray<CMsvCacheEntry>& aEntries) |
|
540 { |
|
541 SetGetChildrenFromVisibleFolder(ETrue); |
|
542 //1. Check if the Parent Id is same as the Visible Folder |
|
543 TMsvId id = aId; |
|
544 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT) |
|
545 if(IsStandardId(aId)) |
|
546 { |
|
547 id = UnmaskTMsvId(aId); |
|
548 } |
|
549 #endif |
|
550 if(id == iVisibleFolderId) |
|
551 { |
|
552 //1.1 yes, check if getchildren has'nt already been performed on this visible folder entry |
|
553 // or all the blocks present are dirty. |
|
554 if( (!IsComplete()) || (IsComplete() && IsAllBlocksDirty()) ) |
|
555 { |
|
556 //1.1.1 Then Fetch and fill all the childrens then return the same to the caller |
|
557 aDbAdapter->GetChildrenL(id, aEntries); |
|
558 TInt excessEntries = CMsvEntryFreePool::Instance()->ExcessMemoryAllocated(); |
|
559 if(excessEntries) |
|
560 { |
|
561 TInt index = 0; |
|
562 RPointerArray<CMsvCacheEntry> entryList; |
|
563 CleanupClosePushL(entryList); |
|
564 for(; index<excessEntries; index++) |
|
565 { |
|
566 CMsvEntryFreePool::Instance()->RecordExcessMemoryL(aEntries[index]); |
|
567 } |
|
568 for(; index<aEntries.Count(); index++) |
|
569 { |
|
570 entryList.AppendL(aEntries[index]); |
|
571 } |
|
572 AddEntryListL(entryList, EFalse); |
|
573 CleanupStack::PopAndDestroy(); |
|
574 } |
|
575 else |
|
576 { |
|
577 AddEntryListL(aEntries, ETrue); |
|
578 } |
|
579 SetGetChildrenFromVisibleFolder(EFalse); |
|
580 return ETrue; |
|
581 } |
|
582 //1.2 yes, check if getchildren has beeb performed on this visible folder |
|
583 if(IsComplete()) |
|
584 { |
|
585 //1.2.1 yes, only few blocks are dirty, so fetch and fill the dirty blocks |
|
586 RBuf8 buf; |
|
587 buf.Create(2000); |
|
588 CleanupClosePushL(buf); |
|
589 TBool isDBOperationReqd = EFalse; |
|
590 for(TInt index=0; index < iIndexTable.Count(); ++index) |
|
591 { |
|
592 if(iIndexTable[index]->IsDirty()) |
|
593 { |
|
594 if(!isDBOperationReqd) |
|
595 { |
|
596 buf.Append(KAnd); |
|
597 buf.Append(KLtBrace); |
|
598 isDBOperationReqd = ETrue; |
|
599 } |
|
600 else |
|
601 { |
|
602 buf.Append(KOr); |
|
603 } |
|
604 buf.Append(KId); |
|
605 buf.Append(KBetween); |
|
606 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT) |
|
607 buf.AppendNum(UnmaskTMsvId(iIndexTable[index]->GetMinMsvIdRange())); |
|
608 buf.Append(KAnd); |
|
609 buf.AppendNum(UnmaskTMsvId(iIndexTable[index]->GetMaxMsvIdRange())); |
|
610 #else |
|
611 buf.AppendNum(iIndexTable[index]->GetMinMsvIdRange()); |
|
612 buf.Append(KAnd); |
|
613 buf.AppendNum(iIndexTable[index]->GetMaxMsvIdRange()); |
|
614 #endif // #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT) |
|
615 } |
|
616 } |
|
617 if(isDBOperationReqd) |
|
618 { |
|
619 buf.Append(KRtBrace); |
|
620 buf.Append(KOrder); |
|
621 buf.Append(KSemiColon); |
|
622 RPointerArray<CMsvCacheEntry> childEntries; |
|
623 CleanupClosePushL(childEntries); |
|
624 aDbAdapter->GetChildrenL(buf, id, childEntries); |
|
625 AddEntryListL(childEntries); |
|
626 CleanupStack::PopAndDestroy(); |
|
627 } |
|
628 for(TInt index=0; index < iIndexTable.Count(); ++index) |
|
629 { |
|
630 iIndexTable[index]->GetChildrenL(id, aEntries); |
|
631 iIndexTable[index]->ClearDirty(); |
|
632 } |
|
633 CleanupStack::PopAndDestroy(); |
|
634 SetGetChildrenFromVisibleFolder(EFalse); |
|
635 return ETrue; |
|
636 } |
|
637 } |
|
638 //2. If the if the Parent Id is not same as the Visible Folder |
|
639 else |
|
640 { |
|
641 CMsvCacheEntry* parentEntry; |
|
642 //2.1 check if the parent of the children is present |
|
643 if(!GetEntry(id, parentEntry)) |
|
644 { |
|
645 User::Leave(KErrNotFound); |
|
646 } |
|
647 |
|
648 //2.2 If parent is a visible folder |
|
649 if(parentEntry->Entry().VisibleFolderFlag()) |
|
650 { |
|
651 //2.2.1 Yes, then return Efalse to the caller stating that |
|
652 // the parent is a visible folder |
|
653 SetGetChildrenFromVisibleFolder(EFalse); |
|
654 return EFalse; |
|
655 } |
|
656 |
|
657 //2.3 Check if Getchildren hasn't been performed on the parent |
|
658 if(NULL == parentEntry->ChildIdArray()) |
|
659 { |
|
660 //2.3.1 Yes, Fetch and fill the childrens of the Parent from DB |
|
661 aDbAdapter->GetChildrenL(id, aEntries); |
|
662 TInt excessEntries = CMsvEntryFreePool::Instance()->ExcessMemoryAllocated(); |
|
663 if(excessEntries) |
|
664 { |
|
665 TInt index = 0; |
|
666 RPointerArray<CMsvCacheEntry> entryList; |
|
667 CleanupClosePushL(entryList); |
|
668 for(; index<excessEntries; index++) |
|
669 { |
|
670 CMsvEntryFreePool::Instance()->RecordExcessMemoryL(aEntries[index]); |
|
671 } |
|
672 for(; index<aEntries.Count(); index++) |
|
673 { |
|
674 entryList.AppendL(aEntries[index]); |
|
675 } |
|
676 AddEntryListL(entryList); |
|
677 CleanupStack::PopAndDestroy(); |
|
678 } |
|
679 else |
|
680 { |
|
681 AddEntryListL(aEntries); |
|
682 } |
|
683 RArray<TMsvId>* childIds = new(ELeave) RArray<TMsvId>; |
|
684 CleanupStack::PushL(childIds); |
|
685 CleanupClosePushL(*childIds); |
|
686 for(TInt index=0; index < aEntries.Count(); ++index) |
|
687 { |
|
688 childIds->AppendL(aEntries[index]->GetId()); |
|
689 } |
|
690 parentEntry->SetChildIdArray(childIds); |
|
691 CleanupStack::Pop(2); |
|
692 } |
|
693 // 2.4 Check If GetChildren has been already performed |
|
694 else |
|
695 { |
|
696 RBuf8 buf; |
|
697 buf.Create(2000); |
|
698 CleanupClosePushL(buf); |
|
699 CMsvCacheEntry* childEntry; |
|
700 TBool isDBOperationReqd = EFalse; |
|
701 for(TInt index=0; index< parentEntry->ChildIdArray()->Count(); ++index) |
|
702 { |
|
703 //2.4.1 If childrens are available in the cache get them |
|
704 if(GetEntry((*parentEntry->ChildIdArray())[index], childEntry)) |
|
705 { |
|
706 aEntries.AppendL(childEntry); |
|
707 } |
|
708 //2.4.2 else fetch the children from DB add them to cache |
|
709 else |
|
710 { |
|
711 if(isDBOperationReqd) |
|
712 { |
|
713 buf.Append(KComma); |
|
714 } |
|
715 if(!isDBOperationReqd) |
|
716 { |
|
717 buf.Append(KAnd); |
|
718 buf.Append(KId); |
|
719 buf.Append(KIn); |
|
720 buf.Append(KLtBrace); |
|
721 isDBOperationReqd = ETrue; |
|
722 } |
|
723 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT) |
|
724 buf.AppendNum(UnmaskTMsvId((*parentEntry->ChildIdArray())[index])); |
|
725 #else |
|
726 buf.AppendNum((*parentEntry->ChildIdArray())[index]); |
|
727 #endif |
|
728 } |
|
729 } |
|
730 if(isDBOperationReqd) |
|
731 { |
|
732 buf.Append(KRtBrace); |
|
733 buf.Append(KSemiColon); |
|
734 |
|
735 RPointerArray<CMsvCacheEntry> childEntries; |
|
736 CleanupClosePushL(childEntries); |
|
737 aDbAdapter->GetChildrenL(buf, parentEntry->GetId(), childEntries); |
|
738 for(TInt index=0; index<childEntries.Count(); ++index) |
|
739 { |
|
740 aEntries.AppendL(childEntries[index]); |
|
741 } |
|
742 AddEntryListL(childEntries); |
|
743 CleanupStack::PopAndDestroy(); |
|
744 } |
|
745 CleanupStack::PopAndDestroy(); |
|
746 } |
|
747 } |
|
748 SetGetChildrenFromVisibleFolder(EFalse); |
|
749 return ETrue; |
|
750 } |
|
751 |
|
752 |
|
753 /** |
|
754 * GetChildrenIdL() |
|
755 * @param CMsvEntrySelection& (OUT): List of child TMsvIds of the current visible |
|
756 * folder. |
|
757 * @return TBool: Returns ETrue, if children list can be returned, otherwise EFalse. |
|
758 * |
|
759 * The function returns list of child TMsvId of the current visible folder. |
|
760 * It will return ETrue if it is possible to return all child IDs, otherwise |
|
761 * it returns EFalse (In case when not all children of the folder is present |
|
762 * in cache i.e. IsComplete() is false. OR in case when some of the blocks |
|
763 * are dirty.). |
|
764 */ |
|
765 TBool CMsvCacheVisibleFolder::GetChildrenIdL(CMsvEntrySelection& aSelection) |
|
766 { |
|
767 if(IsComplete()) |
|
768 { |
|
769 for(TInt index=0; index < iIndexTable.Count(); ++index) |
|
770 { |
|
771 if(iIndexTable[index]->IsDirty()) |
|
772 { |
|
773 return EFalse; |
|
774 } |
|
775 } |
|
776 for(TInt index=0; index < iIndexTable.Count(); ++index) |
|
777 { |
|
778 CMsvCacheIndexTableEntry* entry = iIndexTable[index]; |
|
779 TInt blockSize = entry->Size(); |
|
780 RPointerArray<CMsvCacheEntry>* blkPtr = entry->BlockPtr(); |
|
781 // 1. Check if there are grandchildren present in the block. |
|
782 if(entry->IsGrandChildPresent()) |
|
783 { |
|
784 // 1.1 If yes, then fetch only those entries with parent Id as aParentId. |
|
785 // If the array of entries is NULL, then allocate space for it. |
|
786 for(TInt index1 = 0 ; index1 < blockSize ; ++index1) |
|
787 { |
|
788 if((*blkPtr)[index1]->Entry().Parent() == iVisibleFolderId) |
|
789 { |
|
790 aSelection.AppendL((*blkPtr)[index1]->GetId()); |
|
791 } |
|
792 } |
|
793 } //if(IsGrandChildPresent()) |
|
794 else |
|
795 { |
|
796 // 1.2 If not, then return a copy of the whole block. |
|
797 for(TInt index1 = 0 ; index1 < blockSize ; ++index1) |
|
798 { |
|
799 aSelection.AppendL((*blkPtr)[index1]->GetId()); |
|
800 } |
|
801 } //else |
|
802 } |
|
803 return ETrue; |
|
804 } |
|
805 else |
|
806 { |
|
807 return EFalse; |
|
808 } |
|
809 } |
|
810 |
|
811 |
|
812 |
|
813 /** |
|
814 DeleteEntry() |
|
815 @param TMsvId: TMsvId of the Entry to be deleted. |
|
816 @param aForceDelete TBool, it indicates whether the entry needs to be locked while deleting. |
|
817 @return TInt: Error Status. |
|
818 |
|
819 The function deletes an Entry from the Cache. |
|
820 1. Iterate through the IndexTable Entries. |
|
821 2. Find the IndexTable where the entry is present |
|
822 3. Delete the Entry and update the ChildMsvId array of the parent if delete successful |
|
823 4. If the its the last Entry in the IndexTable and the complete flag is False |
|
824 delete the IndexTable entry |
|
825 */ |
|
826 void CMsvCacheVisibleFolder::DeleteEntryL(TMsvId aId, TBool aForceDelete) |
|
827 { |
|
828 TMsvId parentIdOfEntry; |
|
829 |
|
830 // 1. Iterate through the IndexTable Entries. |
|
831 for(TInt index=0; index < iIndexTable.Count(); ++index) |
|
832 { |
|
833 // 2. Find the IndexTable where the entry is present |
|
834 if(iIndexTable[index]->IsInRange(aId)) |
|
835 { |
|
836 // 3. Delete the Entry and update the ChildMsvId array of the parent if delete successful |
|
837 iIndexTable[index]->DeleteEntryL(aId, parentIdOfEntry, aForceDelete); |
|
838 if(parentIdOfEntry != iVisibleFolderId) |
|
839 { |
|
840 UpdateChildMsvIdsL(parentIdOfEntry, aId, EFalse); |
|
841 } |
|
842 |
|
843 // 4. If the its the last Entry in the IndexTable and the complete flag is False |
|
844 // delete the IndexTable entry |
|
845 if(NULL == iIndexTable[index]->Size() ) |
|
846 { |
|
847 if((index+1) < iIndexTable.Count()) |
|
848 { |
|
849 iIndexTable[index+1]->SetMinMsvIdRange(iIndexTable[index]->GetMinMsvIdRange()); |
|
850 } |
|
851 delete iIndexTable[index]; |
|
852 iIndexTable.Remove(index); |
|
853 } |
|
854 return; |
|
855 } |
|
856 } |
|
857 User::Leave(KErrNotFound); |
|
858 } |
|
859 |
|
860 |
|
861 /** |
|
862 DeleteEntryList() |
|
863 @param CMsvEntrySelection& aEntrySelection. |
|
864 @return TInt: Error Status. |
|
865 |
|
866 The function deletes a set of Entries from the Cache. |
|
867 */ |
|
868 void CMsvCacheVisibleFolder::DeleteEntryListL(CMsvEntrySelection& aEntrySelection) |
|
869 { |
|
870 TInt count = aEntrySelection.Count(); |
|
871 for(TInt index=0; index < count; ++index) |
|
872 { |
|
873 DeleteEntryL(aEntrySelection.At(index)); |
|
874 } |
|
875 } |
|
876 |
|
877 |
|
878 /** |
|
879 IsAllBlocksDirty() |
|
880 @param None. |
|
881 @return TBool: Is All the IndexTableEntries dirty or not. |
|
882 |
|
883 The function checks whether all the IndexTable Entry are dirty. |
|
884 1. Iterate through all the IndexTable Entries. |
|
885 2. Check if the IndexTable Entry is Not Dirty. |
|
886 2.1 Yes, Then Return EFalse; stating that all IndexTable Entries are not dirty. |
|
887 2.2 No, Then Return ETrue; stating that all IndexTable Entries are dirty. |
|
888 */ |
|
889 TBool CMsvCacheVisibleFolder::IsAllBlocksDirty() const |
|
890 { |
|
891 // 1. If index table size is zero, return EFalse. |
|
892 if(0 == iIndexTable.Count()) |
|
893 { |
|
894 return (EFalse); |
|
895 } |
|
896 |
|
897 // 2. Iterate through all the IndexTable Entries. |
|
898 for(TInt index=0; index < iIndexTable.Count(); ++index) |
|
899 { |
|
900 // 3. Check if the IndexTable Entry is Not Dirty. |
|
901 if(!(iIndexTable[index]->IsDirty())) |
|
902 { |
|
903 // 3.1 Yes, Then Return EFalse; stating that all IndexTable Entries are not dirty. |
|
904 return(EFalse); |
|
905 } |
|
906 } |
|
907 // 3.2 No, Then Return ETrue; stating that all IndexTable Entries are dirty. |
|
908 return(ETrue); |
|
909 } |
|
910 |
|
911 |
|
912 /** |
|
913 EntryExists() |
|
914 @param TMsvId: TMsvId of the Entry. |
|
915 @return TBool: Entry Exists or not. |
|
916 |
|
917 The function checks whether an Entry with the Specified TMsvId Exists in the cache. |
|
918 1. Check if the TMsvId is same as the visible folder id. |
|
919 1.1. If they are same then return ETrue stating that id is present |
|
920 2. Else Check through all the IndexTableEntries and check if the Entry Exists. |
|
921 3. Else Return Entry is not Present. |
|
922 */ |
|
923 TBool CMsvCacheVisibleFolder::EntryExists(TMsvId aId) const |
|
924 { |
|
925 // 1. Check if the TMsvId is same as the visible folder id. |
|
926 if(aId == iVisibleFolderId) |
|
927 { |
|
928 // 1.1. If they are same then return ETrue stating that id is present |
|
929 return(ETrue); |
|
930 } |
|
931 |
|
932 // 2. Else Check through all the IndexTableEntries and check if the Entry |
|
933 // Exists. |
|
934 for(TInt index=0; index < iIndexTable.Count(); ++index) |
|
935 { |
|
936 if(iIndexTable[index]->EntryExists(aId)) |
|
937 { |
|
938 return(ETrue); |
|
939 } |
|
940 } |
|
941 |
|
942 // 3. Else Return Entry is not Present. |
|
943 return(EFalse); |
|
944 } |
|
945 |
|
946 |
|
947 /** |
|
948 UpdateChildMsvIdsL() |
|
949 @param TMsvId aParentId : parent Id whose MsvId Array has to be updated. |
|
950 @param TMsvId AChildId : Child Id which as to be updated in the MsvId Array. |
|
951 @param TBool aAppend : Whether the Entry has to be appended or removed from the Parent MsvId Array. |
|
952 @return none. |
|
953 |
|
954 The function Updates the Owner with its child TMsvIds. |
|
955 1. Iterate through the index Table entri |
|
956 2.Find the indexTable where the entry is present |
|
957 3. Update the Parent with the child TMsvIds |
|
958 */ |
|
959 void CMsvCacheVisibleFolder::UpdateChildMsvIdsL(TMsvId aParentId, TMsvId aChildId, TBool aAppend /* DEFAULT = ETrue */) |
|
960 { |
|
961 // 1. Iterate through the index Table entries |
|
962 for(TInt index = 0; index < iIndexTable.Count(); ++index) |
|
963 { |
|
964 // 2.Find the indexTable where the entry is present |
|
965 if(iIndexTable[index]->IsInRange(aParentId)) |
|
966 { |
|
967 // 3. Update the Parent with the child TMsvIds |
|
968 iIndexTable[index]->UpdateChildMsvIdsL(aParentId, aChildId, aAppend); |
|
969 return; |
|
970 } |
|
971 } |
|
972 } |
|
973 |
|
974 |
|
975 /** |
|
976 UpdateChildMsvIdsL() |
|
977 @param RPointerArray<CMsvCacheEntry>&: CMsvCacheEntry Pointer Array. |
|
978 @return none. |
|
979 |
|
980 The function Updates the Owner with its child TMsvIds. |
|
981 1. Find the IndexTableEntry where the parent is present. |
|
982 2. Update the Parent with the child TMsvIds |
|
983 */ |
|
984 void CMsvCacheVisibleFolder::UpdateChildMsvIdsL(RPointerArray<CMsvCacheEntry>& aEntries) |
|
985 { |
|
986 // 1. Find the IndexTableEntry where the parent is present. |
|
987 for(TInt index=0; index < iIndexTable.Count(); ++index) |
|
988 { |
|
989 if(iIndexTable[index]->IsInRange(aEntries[0]->Entry().Parent())) |
|
990 { |
|
991 // 2. Update the Parent with the child TMsvIds |
|
992 iIndexTable[index]->UpdateChildMsvIdsL(aEntries); |
|
993 return; |
|
994 } |
|
995 } |
|
996 } |
|
997 |
|
998 |
|
999 /** |
|
1000 ReleaseAllBlocks() |
|
1001 @param TInt : Number Entries Successfully released. |
|
1002 @return TBool : Returns true if all the entries are released successfully. |
|
1003 |
|
1004 The function Releases the blocks owned by the all indextable entries to freepool. |
|
1005 1. Iterate through the indextable entries. |
|
1006 2. Release the IndexTable Entry Block to the free pool |
|
1007 */ |
|
1008 TBool CMsvCacheVisibleFolder::ReleaseAllBlocks(TInt& aCount) |
|
1009 { |
|
1010 TBool isAllBlocksReleased = ETrue; |
|
1011 aCount = 0; |
|
1012 |
|
1013 // 1. Iterate through the indextable entries. |
|
1014 for(TInt index=0; index < iIndexTable.Count(); ++index) |
|
1015 { |
|
1016 TInt size = iIndexTable[index]->Size(); |
|
1017 //2.Release the IndexTable Entry Block to the free pool |
|
1018 if(!iIndexTable[index]->ReleaseBlock()) |
|
1019 { |
|
1020 isAllBlocksReleased = EFalse; |
|
1021 } |
|
1022 else |
|
1023 { |
|
1024 aCount += size; |
|
1025 } |
|
1026 } |
|
1027 if(!IsComplete() && isAllBlocksReleased) |
|
1028 { |
|
1029 iIndexTable.ResetAndDestroy(); |
|
1030 } |
|
1031 |
|
1032 return (isAllBlocksReleased); |
|
1033 } |
|
1034 |
|
1035 |
|
1036 /** |
|
1037 CompareOrder() |
|
1038 @param CMsvCacheIndexTableEntry : First indexTable entry (Comparison arg) |
|
1039 @param CMsvCacheIndexTableEntry : Second indexTable entry (Comparison arg) |
|
1040 @return TInt : Returns TTime difference. |
|
1041 |
|
1042 Used to sort indexTableEntry. |
|
1043 */ |
|
1044 static TInt CompareOrder(const CMsvCacheIndexTableEntry& aFirst, const CMsvCacheIndexTableEntry& aSecond) |
|
1045 { |
|
1046 return (TInt) (aFirst.AccessTime().Int64()-aSecond.AccessTime().Int64()); |
|
1047 } |
|
1048 |
|
1049 |
|
1050 |
|
1051 /** |
|
1052 ReleaseBlocks() |
|
1053 @param TInt : number of blocks to be released to free pool. |
|
1054 @param TBool : Returns true if the indextable was deleted. |
|
1055 @return TInt : Returns Number of entries successfully released. |
|
1056 |
|
1057 The function Releases the required number blocks owned by the all indextable entries to freepool. |
|
1058 1. Create a Copy of the IndexTable Entries & sort them w.r.t time |
|
1059 2. Iterate through all the blocks or until the expected number of entries are released |
|
1060 3. Release the entries to free pool |
|
1061 */ |
|
1062 TInt CMsvCacheVisibleFolder::ReleaseBlocks(TInt aNumberOfEntriesToRelease, TBool& aIsFolderEmpty) |
|
1063 { |
|
1064 aIsFolderEmpty = EFalse; |
|
1065 TInt index = 0; |
|
1066 TInt sizeOfBlock = 0; |
|
1067 TInt numEntries = aNumberOfEntriesToRelease; |
|
1068 TInt addrIndex = 0; |
|
1069 |
|
1070 //1. Create a Copy of the IndexTable Entries & sort them w.r.t time |
|
1071 RPointerArray<CMsvCacheIndexTableEntry> indexTableCopytoSort; |
|
1072 for(index=0; index<iIndexTable.Count(); ++index) |
|
1073 { |
|
1074 TInt err = indexTableCopytoSort.Append(iIndexTable[index]); |
|
1075 if(KErrNone != err) |
|
1076 { |
|
1077 indexTableCopytoSort.Close(); |
|
1078 return err; |
|
1079 } |
|
1080 } |
|
1081 |
|
1082 TLinearOrder<CMsvCacheIndexTableEntry> order(CompareOrder); |
|
1083 indexTableCopytoSort.Sort(order); |
|
1084 |
|
1085 index = 0; |
|
1086 // 2. Iterate through all the blocks or until the expected number of entries are released |
|
1087 while( (aNumberOfEntriesToRelease > 0) && (index < iIndexTable.Count())) |
|
1088 { |
|
1089 // 3. Release the entries to free pool |
|
1090 sizeOfBlock = indexTableCopytoSort[index]->Size(); |
|
1091 if(indexTableCopytoSort[index]->ReleaseBlock()) |
|
1092 { |
|
1093 aNumberOfEntriesToRelease -= sizeOfBlock; |
|
1094 if(!IsComplete()) |
|
1095 { |
|
1096 addrIndex = iIndexTable.Find(indexTableCopytoSort[index]); |
|
1097 if((addrIndex+1) < iIndexTable.Count()) |
|
1098 { |
|
1099 iIndexTable[addrIndex+1]->SetMinMsvIdRange(iIndexTable[addrIndex]->GetMinMsvIdRange()); |
|
1100 } |
|
1101 delete iIndexTable[addrIndex]; |
|
1102 iIndexTable.Remove(addrIndex); |
|
1103 indexTableCopytoSort.Remove(index); |
|
1104 --index; |
|
1105 } |
|
1106 } |
|
1107 ++index; |
|
1108 } |
|
1109 |
|
1110 if(!IsComplete() && 0 == iIndexTable.Count()) |
|
1111 { |
|
1112 aIsFolderEmpty = ETrue; |
|
1113 } |
|
1114 indexTableCopytoSort.Close(); |
|
1115 return (numEntries - aNumberOfEntriesToRelease); |
|
1116 } |
|
1117 |
|
1118 |
|
1119 |
|
1120 /** |
|
1121 *SplitBlock |
|
1122 *Will check if the block size will be more than 120, then call the IndexTable SplitBlock() |
|
1123 * |
|
1124 *@param None. |
|
1125 *@return void |
|
1126 */ |
|
1127 void CMsvCacheVisibleFolder::SplitBlockL() |
|
1128 { |
|
1129 TInt tableCount = iIndexTable.Count(); |
|
1130 while(tableCount--) |
|
1131 { |
|
1132 TInt size = iIndexTable[tableCount]->Size(); |
|
1133 if(size > 120) |
|
1134 { |
|
1135 iIndexTable[tableCount]->SortBlock(); |
|
1136 RPointerArray<CMsvCacheEntry> splitEntryBlock; |
|
1137 CleanupClosePushL(splitEntryBlock); |
|
1138 // Split the block and get the enteries of the 2nd block |
|
1139 iIndexTable[tableCount]->SplitBlockL(splitEntryBlock); |
|
1140 TInt count = splitEntryBlock.Count(); |
|
1141 |
|
1142 CMsvCacheIndexTableEntry* newTableEntry = CMsvCacheIndexTableEntry::NewLC(splitEntryBlock, 0, count); |
|
1143 |
|
1144 TMsvId minId = splitEntryBlock[0]->GetId(); |
|
1145 // Copy the flags(dirty and grandchildren) of the parent block. |
|
1146 if(iIndexTable[tableCount]->IsDirty()) |
|
1147 { |
|
1148 newTableEntry->SetDirty(); |
|
1149 } |
|
1150 if(iIndexTable[tableCount]->IsGrandChildPresent()) |
|
1151 { |
|
1152 newTableEntry->SetGrandChildPresent(); |
|
1153 } |
|
1154 newTableEntry->SetAccessTime(iIndexTable[tableCount]->AccessTime()); |
|
1155 |
|
1156 iIndexTable.InsertL(newTableEntry, tableCount+1); |
|
1157 iIndexTable[tableCount+1]->SetMinMsvIdRange(minId); |
|
1158 iIndexTable[tableCount+1]->SetMaxMsvIdRange(splitEntryBlock[count-1]->GetId()); |
|
1159 |
|
1160 iIndexTable[tableCount]->SetMaxMsvIdRange(minId - 1); |
|
1161 CleanupStack::Pop();//newTableEntry |
|
1162 splitEntryBlock.Reset(); |
|
1163 CleanupStack::PopAndDestroy();// splitEntryBlock |
|
1164 } |
|
1165 } |
|
1166 } |
|
1167 |
|
1168 |
|
1169 |
|
1170 /** |
|
1171 * GetIndexTableEntry() |
|
1172 * @param TInt : Index at which the desired indextable entry exists. |
|
1173 * @return CMsvCacheIndexTableEntry* : Returns pointer at the index specified. |
|
1174 * |
|
1175 * The function returns the pointer to the IndexTable from the list. |
|
1176 */ |
|
1177 RPointerArray<CMsvCacheIndexTableEntry>* CMsvCacheVisibleFolder::GetIndexTableEntry() |
|
1178 { |
|
1179 return &iIndexTable; |
|
1180 } |
|
1181 |
|
1182 |
|
1183 |
|
1184 |
|
1185 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE) |
|
1186 #ifdef _DEBUG |
|
1187 // To print message index cache. |
|
1188 void CMsvCacheVisibleFolder::Print(RFileLogger& aLogger) |
|
1189 { |
|
1190 _LIT8(KBlock, " BLOCK-ID: "); |
|
1191 TInt blockCount = iIndexTable.Count(); |
|
1192 |
|
1193 for(TInt index=0; index < blockCount; index++) |
|
1194 { |
|
1195 RBuf8 text; |
|
1196 text.Create(100); |
|
1197 text.Append(KBlock); |
|
1198 text.AppendNum(index+1); |
|
1199 aLogger.Write(text); |
|
1200 text.Close(); |
|
1201 iIndexTable[index]->Print(aLogger); |
|
1202 aLogger.Write(_L("")); |
|
1203 } |
|
1204 } |
|
1205 #endif // #ifdef _DEBUG |
|
1206 #endif // #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE) |
|
1207 |