|
1 // Copyright (c) 1999-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 // Implements the classes TSAREntry and CSmsSARStore |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 */ |
|
21 |
|
22 #include <e32svr.h> |
|
23 |
|
24 #include "gsmustor.h" |
|
25 #include "Gsmumain.h" |
|
26 |
|
27 const TDriveNumber KStoreDrive = EDriveC; |
|
28 _LIT(KStoreSubDir, "sms\\"); |
|
29 |
|
30 |
|
31 /** |
|
32 * Utility func for cleanup stack - close the filestore and set pointer to NULL |
|
33 */ |
|
34 void CSARStoreCloseObject(TAny* aObj) |
|
35 { |
|
36 LOGGSMU2("WARNING! Hey, CSARStoreCloseObject called by Untrapper! [0x%08x]", aObj); |
|
37 ((CSARStore*)aObj)->Revert(); |
|
38 } |
|
39 |
|
40 // |
|
41 // implementation of TSAREntry |
|
42 // |
|
43 |
|
44 |
|
45 /** |
|
46 * Constructor |
|
47 * |
|
48 * @capability None |
|
49 */ |
|
50 EXPORT_C TSAREntry::TSAREntry(): |
|
51 iReference(0), |
|
52 iTotal(0), |
|
53 iCount(0), |
|
54 iData1(0), |
|
55 iData2(0), |
|
56 iData3(0), |
|
57 iData4(0), |
|
58 iDataStreamId(KNullStreamId), |
|
59 iFlags(0) |
|
60 { |
|
61 } // TSAREntry::TSAREntry |
|
62 |
|
63 |
|
64 /** |
|
65 * Internalises the object. |
|
66 * |
|
67 * @param aStream Stream to read from |
|
68 * @capability None |
|
69 */ |
|
70 EXPORT_C void TSAREntry::InternalizeL(RReadStream& aStream) |
|
71 { |
|
72 iReference=aStream.ReadInt32L(); |
|
73 iTotal=aStream.ReadInt32L(); |
|
74 iCount=aStream.ReadInt32L(); |
|
75 iData1=aStream.ReadInt32L(); |
|
76 iData2=aStream.ReadInt32L(); |
|
77 iData3=aStream.ReadInt32L(); |
|
78 iData4=aStream.ReadInt32L(); |
|
79 aStream >> iDescription1; |
|
80 aStream >> iDescription2; |
|
81 TInt64 time; |
|
82 aStream >> time; |
|
83 iTime=time; |
|
84 aStream >> iDataStreamId; |
|
85 } // TSAREntry::InternalizeL |
|
86 |
|
87 |
|
88 /** |
|
89 * Externalises the object. |
|
90 * |
|
91 * @param aStream Stream to write to |
|
92 * @capability None |
|
93 */ |
|
94 EXPORT_C void TSAREntry::ExternalizeL(RWriteStream& aStream) const |
|
95 { |
|
96 aStream.WriteInt32L(iReference); |
|
97 aStream.WriteInt32L(iTotal); |
|
98 aStream.WriteInt32L(iCount); |
|
99 aStream.WriteInt32L(iData1); |
|
100 aStream.WriteInt32L(iData2); |
|
101 aStream.WriteInt32L(iData3); |
|
102 aStream.WriteInt32L(iData4); |
|
103 aStream << iDescription1; |
|
104 aStream << iDescription2; |
|
105 aStream << Time().Int64(); |
|
106 aStream << iDataStreamId; |
|
107 } // TSAREntry::ExternalizeL |
|
108 |
|
109 |
|
110 // |
|
111 // implementation of CSARStore |
|
112 // |
|
113 |
|
114 |
|
115 /** |
|
116 * Opens a specified SAR store. |
|
117 * |
|
118 * A SAR filestore has has three uids, KPermanentFileStoreLayoutUid, KSARStoreUid |
|
119 * (which designates that the file store is a SAR store) and a third UID, that |
|
120 * identifies the particular implementation of CSARStore. |
|
121 * |
|
122 * @param aFullName Name for the segmentation and reassembly filestore |
|
123 * @param aThirdUid Third UID for the filestore. |
|
124 * @capability None |
|
125 */ |
|
126 EXPORT_C void CSARStore::OpenL(const TDesC& aFullName, const TUid& aThirdUid) |
|
127 { |
|
128 #ifdef _SMS_LOGGING_ENABLED |
|
129 TBuf8<80> buf8; |
|
130 buf8.Copy(aFullName); |
|
131 LOGGSMU2("CSARStore::OpenL(): '%S'", &buf8); |
|
132 #endif |
|
133 |
|
134 // sanity check |
|
135 __ASSERT_DEBUG(iFileStore==NULL,Panic(KGsmuPanicSARStoreAlreadyOpen)); |
|
136 __ASSERT_DEBUG(!iInTransaction, Panic(KGsmuPanicSARStoreTransaction)); |
|
137 __ASSERT_DEBUG(iEntryArray.Count()==0,Panic(KGsmuPanicSARStoreEntryArrayNotReset)); |
|
138 iFullName.Set(aFullName); |
|
139 iThirdUid = aThirdUid; |
|
140 |
|
141 // first opening we have to Internalize |
|
142 DoOpenL(); |
|
143 // defect fix for EDNJJUN-4WYJGP |
|
144 // Unable to send sms cause sms*.dat is corrupted |
|
145 // TODO - has to be back ported to higher versions |
|
146 TRAPD(ret, InternalizeEntryArrayL()); |
|
147 if (ret != KErrNone) |
|
148 { |
|
149 LOGGSMU2("WARNING: InteralizeEntryArrayL left with %d", ret); |
|
150 } |
|
151 |
|
152 if(ret == KErrCorrupt || ret == KErrEof || ret == KErrNotFound) |
|
153 { |
|
154 Close(); //because the file is in use |
|
155 User::LeaveIfError(iFs.Delete(iFullName)); |
|
156 DoOpenL(); |
|
157 } |
|
158 else |
|
159 User::LeaveIfError(ret); |
|
160 } // CSARStore::OpenL |
|
161 |
|
162 |
|
163 /** |
|
164 * Commits a transaction to the filestore. |
|
165 * @capability None |
|
166 */ |
|
167 EXPORT_C void CSARStore::CommitTransactionL() |
|
168 // This function does the real work of updating the filestore |
|
169 { |
|
170 LOGGSMU4("CSARStore::CommitTransactionL(): this=0x%08X iInTransaction=%d iFileStore=0x%08X", |
|
171 this, iInTransaction, iFileStore); |
|
172 |
|
173 __ASSERT_DEBUG(iFileStore!=NULL, Panic(KGsmuPanicSARStoreNotOpen)); |
|
174 __ASSERT_DEBUG(iInTransaction, Panic(KGsmuPanicSARStoreTransaction)); |
|
175 |
|
176 #ifdef _SMS_LOGGING_ENABLED |
|
177 TRAPD(err, DoCommitAndCompactL()); |
|
178 if (err != KErrNone) |
|
179 { |
|
180 LOGGSMU2("WARNING! could not CommitL/CompactL due to %d", err); |
|
181 User::Leave(err); |
|
182 } |
|
183 #else |
|
184 DoCommitAndCompactL(); |
|
185 #endif |
|
186 |
|
187 //TODO AA: What should we do if err == KErrCorrupt? |
|
188 |
|
189 CleanupStack::Pop(this); |
|
190 iInTransaction = EFalse; |
|
191 |
|
192 RemoveDeletedEntries(); |
|
193 } // CSARStore::CommitTransactionL |
|
194 |
|
195 |
|
196 /** |
|
197 * Closes the file store. |
|
198 * |
|
199 * The function deletes the file store object and resets the entry array. It |
|
200 * should be called once when the protocol module is closing down. |
|
201 * @capability None |
|
202 */ |
|
203 EXPORT_C void CSARStore::Close() |
|
204 { |
|
205 #ifdef _SMS_LOGGING_ENABLED |
|
206 TBuf8<80> buf8; |
|
207 buf8.Copy(iFullName); |
|
208 LOGGSMU2("CSARStore::Close(): '%S'", &buf8); |
|
209 #endif |
|
210 |
|
211 __ASSERT_DEBUG(!iInTransaction, Panic(KGsmuPanicSARStoreTransaction)); |
|
212 |
|
213 delete iFileStore; |
|
214 iFileStore=NULL; |
|
215 iEntryArray.Reset(); |
|
216 } // CSARStore::Close |
|
217 |
|
218 |
|
219 /** |
|
220 * Gets a const reference to the entry array. |
|
221 * |
|
222 * @return Entry array |
|
223 * @capability None |
|
224 */ |
|
225 EXPORT_C const CArrayFix<TSAREntry>& CSARStore::Entries() const |
|
226 { |
|
227 return iEntryArray; |
|
228 } // CSARStore::Entries |
|
229 |
|
230 |
|
231 /** |
|
232 * Purges the reassembly file store. |
|
233 * |
|
234 * After a multipart message, it delete all the old entries. |
|
235 * |
|
236 * Entries will be purged when: 1) The complete message is received; 2) After |
|
237 * aTimerintervalMinutes, if aPurgeIncompletely is false. |
|
238 * |
|
239 * PurgeL() will be called after the booting of the device or when a message |
|
240 * has been received. |
|
241 * |
|
242 * This function opens and closes the file automatically. |
|
243 * |
|
244 * Note: overload function for segmentation store. |
|
245 * |
|
246 * @param aTimeIntervalMinutes Purge time |
|
247 * @param aPurgeIncompleteOnly Purge complete messages flag |
|
248 * @capability None |
|
249 */ |
|
250 EXPORT_C void CSARStore::PurgeL(const TTimeIntervalMinutes& aTimeIntervalMinutes, |
|
251 TBool aPurgeIncompleteOnly) |
|
252 // |
|
253 // TODO ahe - performance filestore / sms |
|
254 // In many cases the files will be opened and closed but no entry will be deleted. |
|
255 // Conclusion: |
|
256 // 1) only open, close, externalize and compact the file when an entry |
|
257 // really shall be deleted |
|
258 // 2) Compact the file after purging, only compact it here |
|
259 // 3) Only purge the segmentation store if the send queue is empty |
|
260 // and only purge the reassembly store when the receiv queue is full |
|
261 // |
|
262 // TODO ahe - for last release - |
|
263 // message can be lost during crash: this issue has to be redesigned but |
|
264 // after the reboot of the device the information in the stores could be lost |
|
265 // due to purging or compacting - a single pdu always gets lost due to not |
|
266 // storing it in the reassembly store. |
|
267 // |
|
268 { |
|
269 LOGGSMU3("CSARStore::PurgeL(): aTimeIntervalMinutes=%d, aPurgeIncompleteOnly=%d", |
|
270 aTimeIntervalMinutes.Int(), aPurgeIncompleteOnly); |
|
271 |
|
272 // TODO - flag |
|
273 // we could also save the call of the method from the consruction of the smsprot |
|
274 if( aPurgeIncompleteOnly ) |
|
275 return; |
|
276 |
|
277 TInt count=iEntryArray.Count(); |
|
278 LOGGSMU2("CSARStore::PurgeL(): count=%d", count); |
|
279 |
|
280 TTime time; |
|
281 time.UniversalTime(); |
|
282 |
|
283 // we open the file outside the loop |
|
284 // to save some CPU |
|
285 BeginTransactionLC(); |
|
286 for (TInt i=count-1; i>=0; i--) |
|
287 { |
|
288 TSAREntry entry=iEntryArray[i]; |
|
289 if (((time>(entry.Time()+aTimeIntervalMinutes)) && !aPurgeIncompleteOnly )) |
|
290 // TODO - flag |
|
291 // check the logic o the aPurgeIncompleteOnly flg |
|
292 // don't purge the store if the entry is complete |
|
293 // entry.IsComplete() ) |
|
294 { |
|
295 DoDeleteEntryL(i); |
|
296 } |
|
297 } |
|
298 ExternalizeEntryArrayL(); |
|
299 CommitTransactionL(); |
|
300 } // CSARStore::PurgeL |
|
301 |
|
302 |
|
303 /** |
|
304 * Purges the segmentation store. |
|
305 * |
|
306 * This purges the filestore after a multipart message, deleting all the old |
|
307 * entries. |
|
308 * |
|
309 * This function opens and closes the file automatically. |
|
310 * |
|
311 * @param aKSegmentationLifetimeMultiplier The coefficient for calculating whether |
|
312 * a message should be purged |
|
313 * @param aPurgeIncompleteOnly Set to false to purge all entries. Set to true |
|
314 * to purge incomplete messages only. |
|
315 * @capability None |
|
316 */ |
|
317 EXPORT_C void CSARStore::PurgeL(TInt aKSegmentationLifetimeMultiplier,TBool aPurgeIncompleteOnly) |
|
318 { |
|
319 LOGGSMU3("CSARStore::PurgeL(): aKSegmentationLifetimeMultiplier=%d, aPurgeIncompleteOnly=%d", |
|
320 aKSegmentationLifetimeMultiplier, aPurgeIncompleteOnly); |
|
321 |
|
322 TInt count=Entries().Count(); |
|
323 LOGGSMU2("CSARStore::PurgeL(): count=%d", count); |
|
324 TTime time; |
|
325 time.UniversalTime(); |
|
326 |
|
327 // we open the file outside the loop |
|
328 // to save some CPU |
|
329 BeginTransactionLC(); |
|
330 TInt numDeletedEntry = 0; |
|
331 |
|
332 for (TInt i=count-1; i>=0; i--) |
|
333 { |
|
334 const TSmsSegmentationEntry& entry = (const TSmsSegmentationEntry&)Entries()[i]; |
|
335 const TTimeIntervalMinutes lifetime((entry.ValidityPeriod()*aKSegmentationLifetimeMultiplier)/1000); |
|
336 // |
|
337 // AEH: Defect fix for EDNPAHN-4WADW3 'Unreliable logging' |
|
338 // |
|
339 // This should solve the problem with agressive PurgeL algorithm |
|
340 // deleting PDUs which are waiting for Status Reports. |
|
341 // Extra bit in TSAREntry indicating Status Reports. |
|
342 // if we don't expect a status report, fake the |
|
343 // number of delivered and failed to be equal |
|
344 // to Total. |
|
345 // |
|
346 |
|
347 const TBool have_sr = entry.ExpectStatusReport(); |
|
348 |
|
349 const TInt deliv_n_failed = have_sr |
|
350 ? entry.Delivered() + entry.Failed() // total acked PDUs |
|
351 : entry.Total(); // fake |
|
352 |
|
353 if ( |
|
354 (entry.IsComplete() && (deliv_n_failed >= entry.Total())) |
|
355 || |
|
356 ((time>(entry.Time()+lifetime)) && !aPurgeIncompleteOnly ) |
|
357 ) |
|
358 { |
|
359 DoDeleteEntryL(i); |
|
360 ++numDeletedEntry; |
|
361 } |
|
362 } |
|
363 |
|
364 TInt numOldestEntry = 0; |
|
365 if(iMaxmumNumberOfMessagesInSegmentationStore > 0) |
|
366 { |
|
367 while((count - numDeletedEntry) > iMaxmumNumberOfMessagesInSegmentationStore) |
|
368 { // The number of messages in the store is greater than the allowed number. Find&Delete the oldest one. |
|
369 // If the maximum number of messages is set to o, we don't delete any messages. |
|
370 while (Entries()[numOldestEntry].IsDeleted()) |
|
371 { // Find oldest entry that has not been deleted already |
|
372 ++numOldestEntry; |
|
373 } |
|
374 DoDeleteEntryL(numOldestEntry++); |
|
375 ++numDeletedEntry; |
|
376 } |
|
377 } |
|
378 |
|
379 ExternalizeEntryArrayL(); |
|
380 CommitTransactionL(); |
|
381 LOGGSMU1("CSmsSegmentationStore::PurgeL End"); |
|
382 } // CSARStore::PurgeL |
|
383 |
|
384 |
|
385 /** |
|
386 * Deletes an entry from the entry array, and externalizes it. |
|
387 * |
|
388 * The file store must be open before calling this function. |
|
389 * |
|
390 * @param aIndex Entry in the SAR store to delete |
|
391 * @capability None |
|
392 */ |
|
393 EXPORT_C void CSARStore::DeleteEntryL(TInt aIndex) |
|
394 { |
|
395 LOGGSMU2("CSARStore::DeleteEntryL(): aIndex=%d", aIndex); |
|
396 |
|
397 DoDeleteEntryL(aIndex); |
|
398 ExternalizeEntryArrayL(); |
|
399 } // CSARStore::DeleteEntryL |
|
400 |
|
401 |
|
402 /** |
|
403 * Constructor, initialises class members only. |
|
404 * |
|
405 * @param aFs File system handle |
|
406 * @capability None |
|
407 */ |
|
408 EXPORT_C CSARStore::CSARStore(RFs& aFs) |
|
409 :iFs(aFs) |
|
410 ,iEntryArray(8) |
|
411 { |
|
412 } // CSARStore::CSARStore |
|
413 |
|
414 |
|
415 /** |
|
416 * Destructor. Frees resource. |
|
417 * @capability None |
|
418 */ |
|
419 EXPORT_C CSARStore::~CSARStore() |
|
420 { |
|
421 delete iFileStore; |
|
422 } // CSARStore::CSARStore |
|
423 |
|
424 |
|
425 /** |
|
426 * Gets a reference to the filestore. |
|
427 * |
|
428 * @return The filestore |
|
429 * @capability None |
|
430 */ |
|
431 EXPORT_C CFileStore& CSARStore::FileStore() |
|
432 { |
|
433 LOGGSMU1("CSARStore::FileStore()"); |
|
434 |
|
435 __ASSERT_DEBUG(iFileStore!=NULL,Panic(KGsmuPanicSARStoreNotOpen)); |
|
436 return *iFileStore; |
|
437 } // CSARStore::FileStore |
|
438 |
|
439 |
|
440 /** |
|
441 * Gets a (const) reference to the filestore. |
|
442 * |
|
443 * @return The filestore |
|
444 * @capability None |
|
445 */ |
|
446 EXPORT_C const CFileStore& CSARStore::FileStore() const |
|
447 { |
|
448 // Ignore in code coverage - not used in SMS stack. |
|
449 BULLSEYE_OFF |
|
450 LOGGSMU1("CSARStore::FileStore()"); |
|
451 __ASSERT_DEBUG(iFileStore!=NULL,Panic(KGsmuPanicSARStoreNotOpen)); |
|
452 return *iFileStore; |
|
453 BULLSEYE_RESTORE |
|
454 } |
|
455 |
|
456 /** |
|
457 * Adds a new entry to the file store. |
|
458 * |
|
459 * The function appends the new entry to the internal entry array, and then externalises |
|
460 * it. |
|
461 * |
|
462 * The file store must be open before calling this function. |
|
463 * |
|
464 * @param aEntry SAR entry to add |
|
465 * @capability None |
|
466 */ |
|
467 EXPORT_C void CSARStore::AddEntryL(const TSAREntry& aEntry) |
|
468 { |
|
469 LOGGSMU1("CSARStore::AddEntryL()"); |
|
470 |
|
471 __ASSERT_DEBUG(iFileStore!=NULL,Panic(KGsmuPanicSARStoreNotOpen)); |
|
472 __ASSERT_DEBUG(aEntry.DataStreamId()!=KNullStreamId,Panic(KGsmuPanicSAREntryDataStreamIdNotSet)); |
|
473 iEntryArray.AppendL(aEntry); |
|
474 iEntryArray[iEntryArray.Count()-1].SetIsAdded(ETrue); |
|
475 ExternalizeEntryArrayL(); |
|
476 } // CSARStore::AddEntryL |
|
477 |
|
478 |
|
479 /** |
|
480 * Changes an entry in the file store - changes it first in the internal |
|
481 * entry array, and then externalizes it. |
|
482 * |
|
483 * The file store must be open before calling this function. |
|
484 * |
|
485 * @param aIndex The index into the SAR store to be changed |
|
486 * @param aNewEntry The new SAR store entry |
|
487 * @capability None |
|
488 */ |
|
489 EXPORT_C void CSARStore::ChangeEntryL(TInt aIndex,const TSAREntry& aNewEntry) |
|
490 { |
|
491 LOGGSMU2("CSARStore::ChangeEntryL(): aIndex=%d", aIndex); |
|
492 |
|
493 __ASSERT_DEBUG(iFileStore!=NULL,Panic(KGsmuPanicSARStoreNotOpen)); |
|
494 __ASSERT_DEBUG(iEntryArray[aIndex].DataStreamId()==aNewEntry.DataStreamId(),Panic(KGsmuPanicSAREntryDataStreamIdChanged)); |
|
495 |
|
496 iEntryArray[aIndex].SetIsDeleted(ETrue); |
|
497 iEntryArray.InsertL(aIndex,aNewEntry); |
|
498 iEntryArray[aIndex].SetIsAdded(ETrue); |
|
499 |
|
500 ExternalizeEntryArrayL(); |
|
501 } // CSARStore::ChangeEntryL |
|
502 |
|
503 |
|
504 /** |
|
505 * Gets the extra stream ID. |
|
506 * |
|
507 * @return Extra stream ID |
|
508 * @capability None |
|
509 */ |
|
510 EXPORT_C TStreamId CSARStore::ExtraStreamId() const |
|
511 { |
|
512 LOGGSMU1("CSARStore::ExtraStreamId"); |
|
513 return iExtraStreamId; |
|
514 } // CSARStore::ExtraStreamId |
|
515 |
|
516 |
|
517 /** |
|
518 * Sets the extra stream ID - changes it first in the internal |
|
519 * entry array, and then externalizes it. |
|
520 * |
|
521 * You must call Close() when the function returns. |
|
522 * |
|
523 * @param aExtraStreamId Extra stream ID |
|
524 * @capability None |
|
525 */ |
|
526 EXPORT_C void CSARStore::SetExtraStreamIdL(const TStreamId& aExtraStreamId) |
|
527 { |
|
528 LOGGSMU2("CSARStore::SetExtraStreamIdL(): id=%d", aExtraStreamId.Value()); |
|
529 |
|
530 __ASSERT_DEBUG(iFileStore!=NULL,Panic(KGsmuPanicSARStoreNotOpen)); |
|
531 TStreamId streamid=iExtraStreamId; |
|
532 iExtraStreamId=aExtraStreamId; |
|
533 TRAPD(ret, ExternalizeEntryArrayL()); |
|
534 if (ret!=KErrNone) |
|
535 { |
|
536 LOGGSMU2("WARNING! CSARStore::DoExternalizeEntryArrayL left with %d", ret); |
|
537 iExtraStreamId=streamid; // Roll back |
|
538 User::Leave(ret); // re-leave to allow caller to also roll back |
|
539 } |
|
540 } // CSARStore::SetExtraStreamIdL |
|
541 |
|
542 |
|
543 /** |
|
544 * Compacts the file store. |
|
545 * |
|
546 * This is done on every reboot and for every eighth SMS message sent, to keep |
|
547 * the size of the file as low as possible. |
|
548 * |
|
549 * This function opens and closes the file automatically. |
|
550 * @capability None |
|
551 */ |
|
552 EXPORT_C void CSARStore::CompactL() |
|
553 { |
|
554 LOGGSMU1("CSARStore::CompactL Start"); |
|
555 __ASSERT_DEBUG(iFileStore!=NULL, Panic(KGsmuPanicSARStoreNotOpen)); |
|
556 __ASSERT_DEBUG(iInTransaction, Panic(KGsmuPanicSARStoreTransaction)); |
|
557 |
|
558 TInt space = iFileStore->CompactL(); |
|
559 iFileStore->CommitL(); |
|
560 |
|
561 LOGGSMU2("CSARStore::CompactL End [space=%d]", space); |
|
562 (void)space; |
|
563 } // CSARStore::CompactL |
|
564 |
|
565 |
|
566 /** |
|
567 * Sets the SAR store as in-transaction. |
|
568 * |
|
569 * The function checks the validity of the call and leaves KErrAccessDenied if |
|
570 * invalid. |
|
571 * @capability None |
|
572 */ |
|
573 EXPORT_C void CSARStore::BeginTransactionLC() |
|
574 { |
|
575 LOGGSMU4("CSARStore::BeginTransactionLC [this=0x%08X iInTransaction=%d iFileStore=0x%08X]", this, iInTransaction, iFileStore); |
|
576 |
|
577 if (iFileStore == NULL || iInTransaction) |
|
578 { |
|
579 LOGGSMU1("WARNING CSARStore::BeginTransactionLC leaving with KErrAccessDenied"); |
|
580 User::Leave(KErrAccessDenied); |
|
581 } |
|
582 |
|
583 TCleanupItem sarClose(CSARStoreCloseObject, this); |
|
584 CleanupStack::PushL(sarClose); |
|
585 iInTransaction = ETrue; |
|
586 } // CSARStore::BeginTransactionLC |
|
587 |
|
588 void CSARStore::Revert() |
|
589 { |
|
590 LOGGSMU3("CSARStore::Revert(): this=0x%08X, iInTransaction=%d", |
|
591 this, iInTransaction); |
|
592 |
|
593 __ASSERT_DEBUG(iInTransaction, Panic(KGsmuPanicSARStoreTransaction)); |
|
594 |
|
595 iFileStore->Revert(); |
|
596 iInTransaction = EFalse; |
|
597 ReinstateDeletedEntries(); |
|
598 } // CSARStore::Revert |
|
599 |
|
600 |
|
601 /** |
|
602 * Opens a filestore. |
|
603 * |
|
604 * This is called by OpenL(), and does the work of really opening the file. If |
|
605 * the file is not there, it creates a new one. |
|
606 * @capability None |
|
607 */ |
|
608 EXPORT_C void CSARStore::DoOpenL() |
|
609 { |
|
610 #ifdef _SMS_LOGGING_ENABLED |
|
611 TBuf8<80> buf8; |
|
612 buf8.Copy(iFullName); |
|
613 LOGGSMU3("CSARStore::DoOpenL(): '%S' this=0x%08X", &buf8, this); |
|
614 #endif |
|
615 |
|
616 TUidType uidtype(KPermanentFileStoreLayoutUid,KSARStoreUid,iThirdUid); |
|
617 TEntry entry; |
|
618 TInt ret=iFs.Entry(iFullName,entry); // Check file exists |
|
619 if (ret==KErrNone) // File found |
|
620 { |
|
621 if (uidtype!=entry.iType) |
|
622 ret=KErrNotFound; |
|
623 } |
|
624 if (ret==KErrNone) // Filestore found |
|
625 { |
|
626 // using OpenLC puts it on the cleanup stack, |
|
627 // so that the trap handler will close the file |
|
628 // automatically |
|
629 TRAP(ret,(iFileStore=CPermanentFileStore::OpenL(iFs,iFullName,EFileShareExclusive|EFileStream|EFileRead|EFileWrite))); |
|
630 if(ret != KErrNone) |
|
631 { |
|
632 LOGGSMU2("WARNING! CPermanentFileStore::OpenLC left with %d", ret); |
|
633 } |
|
634 } |
|
635 |
|
636 if (ret==KErrNoMemory) // Filestore not corrupted |
|
637 { |
|
638 User::Leave(ret); |
|
639 } |
|
640 else if (ret != KErrNone) // The filestore was corrupted or not found, so create a new one |
|
641 { |
|
642 // create a new file and push the close function on the cleanup stack, |
|
643 // so that the trap handler will close the file automatically |
|
644 #ifdef _SMS_LOGGING_ENABLED |
|
645 TBuf8<80> buf8; |
|
646 buf8.Copy(iFullName); |
|
647 LOGGSMU2("CSARStore::DoOpenL(): New file created '%S'", &buf8); |
|
648 #endif |
|
649 TInt kerr(iFs.MkDirAll(iFullName)); //the directory may not exist, So create one. |
|
650 if(kerr != KErrAlreadyExists) |
|
651 { |
|
652 User::LeaveIfError(kerr); |
|
653 } |
|
654 iFileStore=CPermanentFileStore::ReplaceL(iFs, iFullName,EFileShareExclusive|EFileStream|EFileRead|EFileWrite); |
|
655 iFileStore->SetTypeL(uidtype); |
|
656 // the file got lost so we externalize the internal |
|
657 // representation of the data before we continue |
|
658 BeginTransactionLC(); |
|
659 ExternalizeEntryArrayL(); |
|
660 CommitTransactionL(); |
|
661 } |
|
662 |
|
663 __ASSERT_DEBUG(iFileStore!=NULL, Panic(KGsmuPanicSARStoreNotOpen)); |
|
664 } // CSARStore::DoOpenL |
|
665 |
|
666 |
|
667 /** |
|
668 * Actually delete an entry in the entry array |
|
669 */ |
|
670 void CSARStore::DoDeleteEntryL(TInt aIndex) |
|
671 { |
|
672 #ifdef _SMS_LOGGING_ENABLED |
|
673 const TSmsSegmentationEntry& entry = (const TSmsSegmentationEntry&)iEntryArray[aIndex]; |
|
674 |
|
675 LOGGSMU3("CSARStore::DoDeleteEntryL [aIndex=%d Count=%d]", |
|
676 aIndex, iEntryArray.Count()); |
|
677 LOGGSMU4("CSARStore::DoDeleteEntryL [aIndex=%d Delivered=%d Failed=%d]", |
|
678 aIndex, entry.Delivered(), entry.Failed()); |
|
679 LOGGSMU4("CSARStore::DoDeleteEntryL [aIndex=%d Count=%d Total=%d]", |
|
680 aIndex, entry.Count(), entry.Total()); |
|
681 LOGGSMU4("CSARStore::DoDeleteEntryL [aIndex=%d logId=%d StreamId=%d]", |
|
682 aIndex, entry.LogServerId(), entry.DataStreamId().Value()); |
|
683 #endif // _SMS_LOGGING_ENABLED |
|
684 |
|
685 __ASSERT_DEBUG(iFileStore!=NULL,Panic(KGsmuPanicSARStoreNotOpen)); |
|
686 TRAP_IGNORE(iFileStore->DeleteL(iEntryArray[aIndex].DataStreamId())); |
|
687 iEntryArray[aIndex].SetIsDeleted(ETrue); // TODO - truth value should be set depending on ret |
|
688 } // CSARStore::DoDeleteEntryL |
|
689 |
|
690 |
|
691 /** |
|
692 * internalize - read from the file store into RAM |
|
693 */ |
|
694 void CSARStore::InternalizeEntryArrayL() |
|
695 { |
|
696 LOGGSMU1("CSARStore::InternalizeEntryArrayL()"); |
|
697 |
|
698 __ASSERT_DEBUG(iFileStore!=NULL, Panic(KGsmuPanicSARStoreNotOpen)); |
|
699 |
|
700 TStreamId headerid=iFileStore->Root(); |
|
701 RStoreReadStream stream; |
|
702 stream.OpenLC(*iFileStore,headerid); |
|
703 TInt count=stream.ReadInt32L(); |
|
704 for (TInt i=0; i<count; i++) |
|
705 { |
|
706 TSAREntry sarentry; |
|
707 stream >> sarentry; |
|
708 iEntryArray.AppendL(sarentry); |
|
709 } |
|
710 stream >> iExtraStreamId; |
|
711 CleanupStack::PopAndDestroy(); // stream |
|
712 } // CSARStore::InternalizeEntryArrayL |
|
713 |
|
714 |
|
715 void CSARStore::RemoveDeletedEntries() |
|
716 { |
|
717 LOGGSMU1("CSARStore::RemoveDeletedEntries()"); |
|
718 |
|
719 TInt count=iEntryArray.Count(); |
|
720 while (count--) |
|
721 { |
|
722 TSAREntry& entry = iEntryArray[count]; |
|
723 |
|
724 if (entry.IsDeleted()) |
|
725 iEntryArray.Delete(count); |
|
726 else |
|
727 entry.SetIsAdded(EFalse); |
|
728 } |
|
729 } // CSARStore::RemoveDeletedEntries |
|
730 |
|
731 |
|
732 void CSARStore::ReinstateDeletedEntries() |
|
733 { |
|
734 LOGGSMU1("CSARStore::ReinstateDeletedEntries()"); |
|
735 |
|
736 TInt count=iEntryArray.Count(); |
|
737 while (count--) |
|
738 { |
|
739 TSAREntry& entry = iEntryArray[count]; |
|
740 |
|
741 if (entry.IsAdded()) |
|
742 iEntryArray.Delete(count); |
|
743 else |
|
744 entry.SetIsDeleted(EFalse); |
|
745 } |
|
746 } // CSARStore::ReinstateDeletedEntries |
|
747 |
|
748 |
|
749 /** |
|
750 * externalize - read from RAM to the file store |
|
751 */ |
|
752 void CSARStore::ExternalizeEntryArrayL() |
|
753 { |
|
754 __ASSERT_DEBUG(iFileStore!=NULL, Panic(KGsmuPanicSARStoreNotOpen)); |
|
755 __ASSERT_DEBUG(iInTransaction, Panic(KGsmuPanicSARStoreTransaction)); |
|
756 |
|
757 LOGGSMU4("CSARStore::ExternalizeEntryArrayL(): this=0x%08X count=%d headerid=%d]", |
|
758 this, iEntryArray.Count(), iFileStore->Root().Value()); |
|
759 |
|
760 TStreamId headerid=iFileStore->Root(); |
|
761 RStoreWriteStream stream; |
|
762 if (headerid==KNullStreamId) |
|
763 { |
|
764 headerid=stream.CreateLC(*iFileStore); |
|
765 iFileStore->SetRootL(headerid); |
|
766 } |
|
767 else |
|
768 { |
|
769 stream.ReplaceLC(*iFileStore,headerid); |
|
770 } |
|
771 |
|
772 TInt count1=iEntryArray.Count(); |
|
773 TInt count2=0; |
|
774 TInt i=0; |
|
775 |
|
776 for (; i<count1; i++) |
|
777 { |
|
778 if (!iEntryArray[i].IsDeleted()) |
|
779 { |
|
780 count2++; |
|
781 } |
|
782 } |
|
783 stream.WriteInt32L(count2); |
|
784 for (i=0; i<count1; i++) |
|
785 { |
|
786 if (!iEntryArray[i].IsDeleted()) |
|
787 { |
|
788 stream << iEntryArray[i]; |
|
789 } |
|
790 } |
|
791 |
|
792 stream << iExtraStreamId; |
|
793 stream.CommitL(); // TODO - keep this in your head |
|
794 CleanupStack::PopAndDestroy(&stream); |
|
795 } // CSARStore::ExternalizeEntryArrayL |
|
796 |
|
797 |
|
798 /** |
|
799 * called by CloseFile - always do a CommitL |
|
800 * and if the store is of a certains size then |
|
801 * call CompactL also |
|
802 */ |
|
803 void CSARStore::DoCommitAndCompactL() |
|
804 { |
|
805 LOGGSMU1("CSARStore::DoCommitAndCompactL()"); |
|
806 |
|
807 LOGGSMUTIMESTAMP(); |
|
808 iFileStore->CommitL(); |
|
809 LOGGSMUTIMESTAMP(); |
|
810 |
|
811 iCommitCount--; |
|
812 if (iCommitCount < 0) |
|
813 { |
|
814 iCommitCount = KNumStoreCommitsBeforeCompaction; |
|
815 iFileStore->CompactL(); |
|
816 iFileStore->CommitL(); |
|
817 } |
|
818 } // CSARStore::DoCommitAndCompactL |
|
819 |
|
820 |
|
821 /** |
|
822 * Returns the private path used to open a store. |
|
823 * |
|
824 * @param aPath The private path of a store. |
|
825 * @capability None |
|
826 */ |
|
827 EXPORT_C void CSARStore::PrivatePath(TDes& aPath) |
|
828 { |
|
829 LOGGSMU1("CSARStore::PrivatePath()"); |
|
830 |
|
831 TDriveUnit driveUnit(KStoreDrive); |
|
832 TDriveName drive=driveUnit.Name(); |
|
833 aPath.Insert(0, drive); |
|
834 //append private path |
|
835 TPath privatePath; |
|
836 iFs.PrivatePath(privatePath); |
|
837 aPath.Append(privatePath); |
|
838 aPath.Append(KStoreSubDir); |
|
839 } // CSARStore::PrivatePath |