|
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 // Implements CPreallocatedFile. |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 */ |
|
21 #include "smspclass0stor.h" |
|
22 #include "gsmubuf.h" |
|
23 #include "gsmunonieoperations.h" |
|
24 |
|
25 const TInt KSizeOfPreallocatedFileVersion = sizeof(CPreallocatedFile::TPreAllocatedFileVersion); |
|
26 const TInt KSizeOfNumberOfEntrySection = sizeof(TInt); |
|
27 //size of 32-bit checksum |
|
28 const TInt KSizeOfChecksum = sizeof(TUint32); |
|
29 const TInt KSizeOfPreAllocatedStoreEntry = sizeof(TSmsPreAllocatedFileStoreReassemblyEntry); |
|
30 const TInt KSizeOfGsmSmsSlotEntry = sizeof(TGsmSmsSlotEntry); |
|
31 const TInt KSizeOfIndexEntry = sizeof(TInt); |
|
32 const TInt KSizeOfSmsGsmPDU = sizeof(RMobileSmsMessaging::TMobileSmsGsmTpdu); |
|
33 const TInt KSizeOfAContainer = KSizeOfGsmSmsSlotEntry + KSizeOfIndexEntry + KSizeOfSmsGsmPDU; |
|
34 const TInt KBeginOfMasterHeaderSection = KSizeOfPreallocatedFileVersion; |
|
35 |
|
36 /** |
|
37 Static factory constructor. Uses two phase |
|
38 construction and leaves nothing on the CleanupStack. |
|
39 |
|
40 @param aFs File Server handle. |
|
41 @param aFileName Permanent file store name. |
|
42 @param aThirdUid Uid of file. |
|
43 @leave KErrNoMemory |
|
44 |
|
45 @return A pointer to the newly created CSmsPermanentFileStore object. |
|
46 |
|
47 @pre A connected file server session must be passed as parameter. |
|
48 @post CSmsPermanentFileStore object is now fully initialised |
|
49 |
|
50 @internalComponent |
|
51 */ |
|
52 CSmsPermanentFileStore* CSmsPermanentFileStore::NewL(RFs& aFs, const TDesC& aFileName, const TUid& aThirdUid) |
|
53 { |
|
54 LOGSMSPROT1("CSmsPermanentFileStore::NewL()"); |
|
55 CSmsPermanentFileStore* self = new (ELeave) CSmsPermanentFileStore(aFs, aThirdUid); |
|
56 CleanupStack::PushL(self); |
|
57 self->ConstructL(aFileName); |
|
58 CleanupStack::Pop(self); |
|
59 |
|
60 return self; |
|
61 } |
|
62 |
|
63 void CSmsPermanentFileStore::ConstructL(const TDesC& aFileName) |
|
64 { |
|
65 LOGSMSPROT1("CSmsPermanentFileStore::ConstructL()"); |
|
66 iFileName = aFileName.AllocL(); |
|
67 } |
|
68 |
|
69 /** |
|
70 * Constructor. |
|
71 */ |
|
72 CSmsPermanentFileStore::CSmsPermanentFileStore(RFs& aFs, const TUid& aThirdUid) |
|
73 : iFs(aFs), iFileName(NULL), iThirdUid(aThirdUid), iFileStore(NULL), iEntryArray(KFlatArrayGranularity) |
|
74 { |
|
75 } |
|
76 |
|
77 /** |
|
78 * Destructor. It destroys all the member variables. |
|
79 */ |
|
80 CSmsPermanentFileStore::~CSmsPermanentFileStore() |
|
81 { |
|
82 delete iFileName; |
|
83 } |
|
84 |
|
85 /** |
|
86 It checks & returns whether the file exist or not. If file is there whether |
|
87 it is corrupted or not. |
|
88 |
|
89 @internalComponent |
|
90 */ |
|
91 TBool CSmsPermanentFileStore::IsFileOK() |
|
92 { |
|
93 TBool retBool(EFalse); |
|
94 TUidType uidtype(KPermanentFileStoreLayoutUid,KSARStoreUid,iThirdUid); |
|
95 TEntry entry; |
|
96 TInt ret=iFs.Entry(iFileName->Des(), entry); |
|
97 // Check file existence & corruption |
|
98 if ((ret == KErrNone) && (entry.iType == uidtype)) |
|
99 { |
|
100 retBool = ETrue; |
|
101 } |
|
102 return retBool; |
|
103 } |
|
104 |
|
105 /** |
|
106 It creates a permanent store file. |
|
107 |
|
108 @internalComponent |
|
109 */ |
|
110 void CSmsPermanentFileStore::CreateL() |
|
111 { |
|
112 LOGSMSPROT1("CSmsPermanentFileStore::CreateL()"); |
|
113 TUidType uidtype(KPermanentFileStoreLayoutUid,KSARStoreUid,iThirdUid); |
|
114 iFileStore=CPermanentFileStore::ReplaceL(iFs, iFileName->Des(), EFileShareExclusive|EFileStream|EFileRead|EFileWrite); |
|
115 iFileStore->SetTypeL(uidtype); |
|
116 iEntryArray.Reset(); |
|
117 ExternalizeEntryArrayL(); |
|
118 iFileStore->CommitL(); |
|
119 // Close it to make sure that file is created correctly (defensive approach). |
|
120 Close(); |
|
121 //Again Open the file |
|
122 OpenL(); |
|
123 } |
|
124 |
|
125 /** |
|
126 It opens the permanent store file and internalizes the entries. |
|
127 |
|
128 @internalComponent |
|
129 */ |
|
130 void CSmsPermanentFileStore::OpenL() |
|
131 { |
|
132 LOGSMSPROT1("CSmsPermanentFileStore::OpenL()"); |
|
133 iFileStore=CPermanentFileStore::OpenL(iFs,iFileName->Des(),EFileShareExclusive|EFileStream|EFileRead|EFileWrite); |
|
134 InternalizeEntryArrayL(); |
|
135 } |
|
136 |
|
137 /** |
|
138 It closes the permanent store file. |
|
139 |
|
140 @internalComponent |
|
141 */ |
|
142 void CSmsPermanentFileStore::Close() |
|
143 { |
|
144 LOGSMSPROT1("CSmsPermanentFileStore::Close()"); |
|
145 delete iFileStore; |
|
146 iFileStore = NULL; |
|
147 iEntryArray.Reset(); |
|
148 } |
|
149 |
|
150 /* |
|
151 This function cleans its entries against the passed entries. |
|
152 This is needed because there might be a scenario where user has deleted a message |
|
153 but the corresponding message is not deleted from permanent store file |
|
154 due to out-of-disk condition. But the entry is invalid because |
|
155 it is no more in the pre-allocated file which contains master header info. |
|
156 And also at the time of forwarding an incomplete message a forwarded |
|
157 message has not been deleted due to above reason. |
|
158 This function also compacts the store after deletion. |
|
159 |
|
160 @param aEntryArray entray array against whose clean up is carried out. |
|
161 |
|
162 @internalComponent |
|
163 */ |
|
164 void CSmsPermanentFileStore::CleanupEntriesWithCompactL(const CArrayFix<TSmsPreAllocatedFileStoreReassemblyEntry>& aEntryArray) |
|
165 { |
|
166 // Ignore in code coverage - a previous CleanupEntries would need to have failed with KErrDiskFull |
|
167 BULLSEYE_OFF |
|
168 LOGSMSPROT1("CSmsPermanentFileStore::CleanupEntriesWithCompactL()"); |
|
169 |
|
170 iCompact = ETrue; |
|
171 CleanupEntriesL(aEntryArray); |
|
172 BULLSEYE_RESTORE |
|
173 } |
|
174 |
|
175 /* |
|
176 This function cleans its entries against the passed entries. |
|
177 This is needed because there migth be a scenario where user has deleted a message |
|
178 but the corresponding message is not deleted from permanent store file |
|
179 due to out-of-disk condition. But the entry is invalid because |
|
180 it is no more in the pre-allocated file which contains master header info. |
|
181 And also at the time of forwarding an incomplete message a forwarded |
|
182 message has not been deleted due to above reason. |
|
183 |
|
184 @param aEntryArray entray array against whose clean up is carried out. |
|
185 |
|
186 @internalComponent |
|
187 */ |
|
188 void CSmsPermanentFileStore::CleanupEntriesL(const CArrayFix<TSmsPreAllocatedFileStoreReassemblyEntry>& aEntryArray) |
|
189 { |
|
190 LOGSMSPROT1("CSmsPermanentFileStore::CleanupEntriesL()"); |
|
191 |
|
192 TInt reassemblyCount = iEntryArray.Count(); |
|
193 TInt index, index2; |
|
194 |
|
195 for (index = 0; index < reassemblyCount; index++) |
|
196 { |
|
197 for (index2 = 0; index2 < aEntryArray.Count(); index2++) |
|
198 { |
|
199 if (iEntryArray[index].Reference() == aEntryArray[index2].Reference() && |
|
200 iEntryArray[index].Total() == aEntryArray[index2].Total() && |
|
201 iEntryArray[index].PduType() == aEntryArray[index2].PduType() && |
|
202 iEntryArray[index].Storage() == aEntryArray[index2].Storage() && |
|
203 iEntryArray[index].Description2() == aEntryArray[index2].Description2()) |
|
204 { |
|
205 if (aEntryArray[index2].NumberOfPDUsForwardToClient() > 0) |
|
206 { |
|
207 //Internalize the entries. |
|
208 CSmsBuffer* buffer = CSmsBuffer::NewL(); |
|
209 CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer); |
|
210 CleanupStack::PushL(smsMessage); |
|
211 |
|
212 CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity); |
|
213 CleanupStack::PushL(indexArray); |
|
214 CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity); |
|
215 CleanupStack::PushL(smsArray); |
|
216 |
|
217 InternalizeEntryL(index, *smsMessage, *indexArray, *smsArray); |
|
218 TInt noOfForwardedEntries = 0; |
|
219 for (TInt j=indexArray->Count(); j>0 ;j--) |
|
220 { |
|
221 TUint8 bitMapIndex = (indexArray->At(j-1)-1)/8; |
|
222 TUint8 bitPos = (indexArray->At(j-1)-1)%8; |
|
223 TUint8 bitMap; |
|
224 TSmsPreAllocatedFileStoreReassemblyEntry entry; |
|
225 entry = aEntryArray[index2]; |
|
226 entry.GetBitMap(bitMapIndex, bitMap); |
|
227 TUint8 tmpBitMap = 1; |
|
228 tmpBitMap <<= bitPos; |
|
229 if (tmpBitMap == (bitMap & tmpBitMap)) |
|
230 { |
|
231 noOfForwardedEntries++; |
|
232 indexArray->Delete(j-1); |
|
233 smsArray->Delete(j-1); |
|
234 } |
|
235 } |
|
236 if (noOfForwardedEntries > 0) |
|
237 { |
|
238 TStreamId streamId = iEntryArray[index].DataStreamId(); |
|
239 ExternalizeEntryL(streamId, *smsMessage, *indexArray, *smsArray); |
|
240 } |
|
241 CleanupStack::PopAndDestroy(3, smsMessage); // smsMessage, indexArray, smsArray |
|
242 } |
|
243 break; |
|
244 } |
|
245 } |
|
246 if (index2 == aEntryArray.Count()) |
|
247 { |
|
248 DeleteEntryL(index); |
|
249 } |
|
250 } |
|
251 } |
|
252 |
|
253 /** |
|
254 It internalizes its entry array. |
|
255 |
|
256 @internalComponent |
|
257 */ |
|
258 void CSmsPermanentFileStore::InternalizeEntryArrayL() |
|
259 { |
|
260 LOGSMSPROT1("CSmsPermanentFileStore::InternalizeEntryArrayL()"); |
|
261 |
|
262 iEntryArray.Reset(); |
|
263 TStreamId headerid=iFileStore->Root(); |
|
264 RStoreReadStream stream; |
|
265 stream.OpenLC(*iFileStore,headerid); |
|
266 TInt count=stream.ReadInt32L(); |
|
267 for (TInt i=0; i<count; i++) |
|
268 { |
|
269 TSmsReassemblyEntry sarentry; |
|
270 stream >> sarentry; |
|
271 iEntryArray.AppendL(sarentry); |
|
272 } |
|
273 CleanupStack::PopAndDestroy(); // stream |
|
274 } |
|
275 |
|
276 /** |
|
277 It externalizes its entry array. |
|
278 |
|
279 @internalComponent |
|
280 */ |
|
281 void CSmsPermanentFileStore::ExternalizeEntryArrayL() |
|
282 { |
|
283 LOGSMSPROT4("CSmsPermanentFileStore::ExternalizeEntryArrayL(): this=0x%08X count=%d headerid=%d]", |
|
284 this, iEntryArray.Count(), iFileStore->Root().Value()); |
|
285 |
|
286 TStreamId headerid=iFileStore->Root(); |
|
287 RStoreWriteStream stream; |
|
288 if (headerid==KNullStreamId) |
|
289 { |
|
290 headerid=stream.CreateLC(*iFileStore); |
|
291 iFileStore->SetRootL(headerid); |
|
292 } |
|
293 else |
|
294 { |
|
295 stream.ReplaceLC(*iFileStore,headerid); |
|
296 } |
|
297 |
|
298 TInt count1=iEntryArray.Count(); |
|
299 TInt count2=0; |
|
300 TInt i=0; |
|
301 |
|
302 for (; i<count1; i++) |
|
303 { |
|
304 if (!iEntryArray[i].IsDeleted()) |
|
305 { |
|
306 count2++; |
|
307 } |
|
308 } |
|
309 stream.WriteInt32L(count2); |
|
310 for (i=0; i<count1; i++) |
|
311 { |
|
312 if (!iEntryArray[i].IsDeleted()) |
|
313 { |
|
314 stream << iEntryArray[i]; |
|
315 } |
|
316 } |
|
317 |
|
318 stream.CommitL(); |
|
319 CleanupStack::PopAndDestroy(&stream); |
|
320 } |
|
321 |
|
322 /* |
|
323 It adds the new message in permanent store file. |
|
324 |
|
325 @param aIndex (output) index number on which message is added. |
|
326 @param aSmsMessage reference to sms message to be added. |
|
327 @param aGsmSms reference to GsmSms object to be added. |
|
328 |
|
329 @internalComponent |
|
330 */ |
|
331 void CSmsPermanentFileStore::AddNewMessageL(TInt& aIndex, CSmsMessage& aSmsMessage,const TGsmSms& aGsmSms) |
|
332 { |
|
333 LOGSMSPROT1("CSmsPermanentFileStore::AddNewMessageL"); |
|
334 |
|
335 CArrayFix<TInt>* indexArray=new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity); |
|
336 CleanupStack::PushL(indexArray); |
|
337 CArrayFixFlat<TGsmSms>* smsArray=new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity); |
|
338 CleanupStack::PushL(smsArray); |
|
339 //Index must initialize to 0. |
|
340 TInt index = 0; |
|
341 if (!aSmsMessage.IsDecoded()) |
|
342 { |
|
343 index = aSmsMessage.SmsPDU().ConcatenatedMessagePDUIndex(); |
|
344 } |
|
345 indexArray->AppendL(index); |
|
346 smsArray->AppendL(aGsmSms); |
|
347 |
|
348 TStreamId streamid = KNullStreamId; |
|
349 ExternalizeEntryL(streamid, aSmsMessage, *indexArray, *smsArray); |
|
350 |
|
351 TSmsReassemblyEntry tmpEntry; |
|
352 //Fill-up entry information... |
|
353 CReassemblyStoreUtility::PopulateEntry(tmpEntry, aSmsMessage, 1); |
|
354 // Update Data stream id. |
|
355 tmpEntry.SetDataStreamId(streamid); |
|
356 |
|
357 aIndex = iEntryArray.Count(); |
|
358 AddEntryL(tmpEntry); |
|
359 CleanupStack::PopAndDestroy(2); //indexArray, smsArray |
|
360 } |
|
361 |
|
362 /* |
|
363 It updates the existing message in permanent store file. |
|
364 |
|
365 @param aIndex index number on which message is to be updated. |
|
366 @param aSmsMessage reference to sms message to be updated. |
|
367 @param aIndexArray array of index of all the PDUs. |
|
368 @param aSmsArray array of sms of all the PDUs. |
|
369 |
|
370 @internalComponent |
|
371 */ |
|
372 void CSmsPermanentFileStore::UpdateExistingMessageL(TInt aIndex, const CSmsMessage& aSmsMessage,const CArrayFix<TInt>& aIndexArray,const CArrayFix<TGsmSms>& aSmsArray) |
|
373 { |
|
374 LOGSMSPROT1("CSmsPermanentFileStore::UpdateExistingMessageL()"); |
|
375 TStreamId streamid = iEntryArray[aIndex].DataStreamId(); |
|
376 ExternalizeEntryL(streamid, aSmsMessage, aIndexArray, aSmsArray); |
|
377 TSmsReassemblyEntry entry; |
|
378 CReassemblyStoreUtility::PopulateEntry(entry, aSmsMessage, aSmsArray.Count()); |
|
379 entry.SetDataStreamId(streamid); |
|
380 ChangeEntryL(aIndex, entry); |
|
381 } |
|
382 |
|
383 /* |
|
384 It matches the entry with entry in permanent store file & returns |
|
385 the index. If not found it returns KErrNotFound. |
|
386 |
|
387 @param aEntry reference to entry information. |
|
388 @param aIndex (output) returns the index number. |
|
389 |
|
390 @internalComponent |
|
391 */ |
|
392 void CSmsPermanentFileStore::MatchEntryToExistingMessage(const TReassemblyEntry& aEntry, |
|
393 TInt& aIndex) |
|
394 { |
|
395 LOGSMSPROT1("CSmsPermanentFileStore::MatchEntryToExistingMessage()"); |
|
396 |
|
397 aIndex = KErrNotFound; |
|
398 |
|
399 // |
|
400 // Search the reassembly store for a matching entry... |
|
401 // |
|
402 TInt reassemblyCount = iEntryArray.Count(); |
|
403 for (TInt index = 0; index < reassemblyCount; index++) |
|
404 { |
|
405 TSmsReassemblyEntry& entry = iEntryArray[index]; |
|
406 |
|
407 if (entry.Reference() == aEntry.Reference() && |
|
408 entry.Total() == aEntry.Total() && |
|
409 entry.PduType() == aEntry.PduType() && |
|
410 entry.Storage() == aEntry.Storage() && |
|
411 entry.Description2() == aEntry.Description2()) |
|
412 { |
|
413 // |
|
414 // Found it! |
|
415 // |
|
416 aIndex = index; |
|
417 break; |
|
418 } |
|
419 } |
|
420 |
|
421 LOGSMSPROT2("CSmsPermanentFileStore::MatchEntryToExistingMessage(): aIndex=%d", aIndex); |
|
422 } |
|
423 |
|
424 /* |
|
425 It updates the log server id of the message. |
|
426 |
|
427 @param aIndex index number of the message to be updated. |
|
428 @param aLogServerId log server id. |
|
429 |
|
430 @internalComponent |
|
431 */ |
|
432 void CSmsPermanentFileStore::UpdateLogServerIdL(TInt& aIndex, TLogId aLogServerId) |
|
433 { |
|
434 LOGSMSPROT1("CSmsPermanentFileStore::UpdateLogServerIdL"); |
|
435 |
|
436 TSmsReassemblyEntry entry; |
|
437 entry = iEntryArray[aIndex]; |
|
438 |
|
439 if (entry.LogServerId() != aLogServerId) |
|
440 { |
|
441 entry.SetLogServerId(aLogServerId); |
|
442 ChangeEntryL(aIndex, entry); |
|
443 } |
|
444 } |
|
445 |
|
446 /* |
|
447 It sets the message passed to client or not. |
|
448 |
|
449 @param aIndex index number of the message to be updated. |
|
450 @param aBool boolean value indicating whether message is passes or not. |
|
451 |
|
452 @internalComponent |
|
453 */ |
|
454 void CSmsPermanentFileStore::SetPassedToClientL(TInt aIndex, TBool aBool) |
|
455 { |
|
456 LOGSMSPROT2("CSmsPermanentFileStore::SetPassedToClientL(): aIndex=%d", aIndex); |
|
457 |
|
458 TSmsReassemblyEntry entry; |
|
459 entry = iEntryArray[aIndex]; |
|
460 |
|
461 if (entry.PassedToClient() != aBool) |
|
462 { |
|
463 entry.SetPassedToClient(aBool); |
|
464 ChangeEntryL(aIndex, entry); |
|
465 } |
|
466 } |
|
467 |
|
468 /* |
|
469 It adds the new entry in the existing entry array. |
|
470 |
|
471 @param aEntry entry to be added. |
|
472 |
|
473 @internalComponent |
|
474 */ |
|
475 void CSmsPermanentFileStore::AddEntryL(TSmsReassemblyEntry& aEntry) |
|
476 { |
|
477 iEntryArray.AppendL(aEntry); |
|
478 iEntryArray[iEntryArray.Count()-1].SetIsAdded(ETrue); |
|
479 } |
|
480 |
|
481 /* |
|
482 It changes the existing entry with new entry. |
|
483 |
|
484 @param aIndex index number of the entry which will be changed. |
|
485 @param aNewEntry entry to be updated. |
|
486 |
|
487 @internalComponent |
|
488 */ |
|
489 void CSmsPermanentFileStore::ChangeEntryL(TInt aIndex,const TSmsReassemblyEntry& aNewEntry) |
|
490 { |
|
491 LOGSMSPROT2("CSmsPermanentFileStore::ChangeEntryL(): aIndex=%d", aIndex); |
|
492 |
|
493 iEntryArray[aIndex].SetIsDeleted(ETrue); |
|
494 iEntryArray.InsertL(aIndex,aNewEntry); |
|
495 iEntryArray[aIndex].SetIsAdded(ETrue); |
|
496 } |
|
497 |
|
498 /* |
|
499 It deletes the entry. |
|
500 |
|
501 @param aIndex index number of the entry which will be deleted. |
|
502 |
|
503 @internalComponent |
|
504 */ |
|
505 void CSmsPermanentFileStore::DeleteEntryL(TInt aIndex) |
|
506 { |
|
507 iFileStore->DeleteL(iEntryArray[aIndex].DataStreamId()); |
|
508 iEntryArray[aIndex].SetIsDeleted(ETrue); |
|
509 } |
|
510 |
|
511 /* |
|
512 It externalizes(writes) the entry in permanent store file. |
|
513 |
|
514 @param aStreamId stream id which needs to externalized. |
|
515 @param aSmsMessage reference to sms message which needs to be externalized. |
|
516 @param aIndexArray refence to array of index which needs to be externalized. |
|
517 @param aSmsArray refence to array of sms which needs to be externalized. |
|
518 |
|
519 @internalComponent |
|
520 */ |
|
521 void CSmsPermanentFileStore::ExternalizeEntryL(TStreamId& aStreamId,const CSmsMessage& aSmsMessage,const CArrayFix<TInt>& aIndexArray,const CArrayFix<TGsmSms>& aSmsArray) |
|
522 { |
|
523 LOGSMSPROT2("CSmsPermanentFileStore::ExternalizeEntryL Start [sid=%d]", aStreamId.Value()); |
|
524 |
|
525 RStoreWriteStream writestream; |
|
526 if (aStreamId==KNullStreamId) |
|
527 aStreamId=writestream.CreateLC(*iFileStore); |
|
528 else |
|
529 writestream.ReplaceLC(*iFileStore,aStreamId); |
|
530 writestream << aSmsMessage; |
|
531 TInt count=aIndexArray.Count(); |
|
532 writestream.WriteInt32L(count); |
|
533 TInt i=0; |
|
534 for (; i<count; i++) |
|
535 writestream.WriteInt32L(aIndexArray[i]); |
|
536 count=aSmsArray.Count(); |
|
537 writestream.WriteInt32L(count); |
|
538 for (i=0; i<count; i++) |
|
539 { |
|
540 RMobileSmsMessaging::TMobileSmsGsmTpdu pdu; |
|
541 pdu=aSmsArray[i].Pdu(); |
|
542 writestream << pdu; |
|
543 } |
|
544 writestream.CommitL(); |
|
545 CleanupStack::PopAndDestroy(); |
|
546 |
|
547 LOGSMSPROT2("CClass0PermanentFileStore::ExternalizeEntryL End [count=%d]", count); |
|
548 } |
|
549 |
|
550 /* |
|
551 It internalizes(reads) the entry from permanent store file. |
|
552 |
|
553 @param aIndex index number of the message to be internalized. |
|
554 @param aSmsMessage (output) reference to sms message. |
|
555 @param aIndexArray (output) refence to array of index. |
|
556 @param aSmsArray (output) refence to array of sms. |
|
557 |
|
558 @internalComponent |
|
559 */ |
|
560 void CSmsPermanentFileStore::InternalizeEntryL(const TInt aIndex, CSmsMessage& aSmsMessage, CArrayFix<TInt>& aIndexArray, CArrayFix<TGsmSms>& aSmsArray) |
|
561 { |
|
562 TSmsReassemblyEntry& entry = iEntryArray[aIndex]; |
|
563 LOGSMSPROT2("CSmsPermanentFileStore::InternalizeEntryL Start [sid=%d]", entry.DataStreamId().Value()); |
|
564 RStoreReadStream readstream; |
|
565 readstream.OpenLC(*iFileStore, entry.DataStreamId()); |
|
566 readstream >> aSmsMessage; |
|
567 TInt count=readstream.ReadInt32L(); |
|
568 TInt i; |
|
569 for (i=0; i<count; i++) |
|
570 { |
|
571 TInt index=readstream.ReadInt32L(); |
|
572 aIndexArray.AppendL(index); |
|
573 } |
|
574 count=readstream.ReadInt32L(); |
|
575 if(count!=aIndexArray.Count()) |
|
576 { |
|
577 User::Leave(KErrCorrupt); |
|
578 } |
|
579 for (i=0; i<count; i++) |
|
580 { |
|
581 RMobileSmsMessaging::TMobileSmsGsmTpdu pdu; |
|
582 readstream >> pdu; |
|
583 TGsmSms sms; |
|
584 sms.SetPdu(pdu); |
|
585 aSmsArray.AppendL(sms); |
|
586 } |
|
587 CleanupStack::PopAndDestroy(); |
|
588 //Set other properties of CSmsMessage |
|
589 aSmsMessage.SetStorage(entry.Storage()); |
|
590 aSmsMessage.SetLogServerId(entry.LogServerId()); |
|
591 aSmsMessage.SetTime(entry.Time()); |
|
592 LOGSMSPROT2("CSmsPermanentFileStore::InternalizeEntryL End [count=%d]", count); |
|
593 } |
|
594 |
|
595 /* |
|
596 It removes the PDUs from permanent store file. |
|
597 This function is needed because after forwarding the incomplete message |
|
598 to client, the corresponding PDUs needs to be be removed from permanent |
|
599 store file. |
|
600 This functionality is specific to class 0 re-assembly store. |
|
601 |
|
602 @param aIndex index number of the message to be removed. |
|
603 @param aStartPos starting pos of pdu to be removed. |
|
604 @param aEndPos end pos of pdu to be removed. |
|
605 |
|
606 @internalComponent |
|
607 */ |
|
608 void CSmsPermanentFileStore::RemovePDUsL(TInt aIndex, TInt aStartPos, TInt aEndPos) |
|
609 { |
|
610 LOGSMSPROT1("CSmsPermanentFileStore::RemovePDUsL"); |
|
611 |
|
612 CSmsBuffer* buffer = CSmsBuffer::NewL(); |
|
613 CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer); |
|
614 CleanupStack::PushL(smsMessage); |
|
615 |
|
616 CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity); |
|
617 CleanupStack::PushL(indexArray); |
|
618 CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity); |
|
619 CleanupStack::PushL(smsArray); |
|
620 |
|
621 InternalizeEntryL(aIndex, *smsMessage, *indexArray, *smsArray); |
|
622 |
|
623 TInt count = indexArray->Count(); |
|
624 for (TInt i=count; i>0; i--) |
|
625 { |
|
626 if ((indexArray->At(i-1) >= aStartPos) && (indexArray->At(i-1) <= aEndPos)) |
|
627 { |
|
628 indexArray->Delete(i-1); |
|
629 smsArray->Delete(i-1); |
|
630 } |
|
631 } |
|
632 |
|
633 /* |
|
634 There are 3 scenarios in this case: |
|
635 1. If all the entries are removed, |
|
636 then there is no need to store the entry in this permanent file. |
|
637 2. If few entries are removed, |
|
638 then externalize the remaining entries. Update count field also. |
|
639 3. If no entries are removed, then do nothing. |
|
640 */ |
|
641 if (indexArray->Count()==0) |
|
642 { |
|
643 DeleteEntryL(aIndex); |
|
644 } |
|
645 else if (count!=indexArray->Count()) |
|
646 { |
|
647 TStreamId streamid = iEntryArray[aIndex].DataStreamId(); |
|
648 ExternalizeEntryL(streamid, *smsMessage, *indexArray, *smsArray); |
|
649 |
|
650 TSmsReassemblyEntry entry; |
|
651 entry = iEntryArray[aIndex]; |
|
652 entry.SetCount(indexArray->Count()); |
|
653 ChangeEntryL(aIndex, entry); |
|
654 } |
|
655 CleanupStack::PopAndDestroy(3, smsMessage); // smsMessage, indexArray, smsArray |
|
656 } |
|
657 |
|
658 /** |
|
659 * Sets the permanent store as in-transaction. |
|
660 * |
|
661 * The function checks the validity of the call and leaves KErrAccessDenied if |
|
662 * invalid. |
|
663 * @capability None |
|
664 */ |
|
665 void CSmsPermanentFileStore::BeginTransactionL() |
|
666 { |
|
667 LOGSMSPROT4("CSmsPermanentFileStore::BeginTransactionL [this=0x%08X iInTransaction=%d iFileStore=0x%08X]", this, iInTransaction, iFileStore); |
|
668 |
|
669 if (iFileStore == NULL || iInTransaction) |
|
670 { |
|
671 LOGSMSPROT1("WARNING CSmsPermanentFileStore::BeginTransactionL leaving with KErrAccessDenied"); |
|
672 User::Leave(KErrAccessDenied); |
|
673 } |
|
674 |
|
675 iInTransaction = ETrue; |
|
676 } // CSmsPermanentFileStore::BeginTransactionL |
|
677 |
|
678 /** |
|
679 * It reverts the transaction. |
|
680 */ |
|
681 void CSmsPermanentFileStore::Revert() |
|
682 { |
|
683 LOGSMSPROT3("CSmsPermanentFileStore::Revert(): this=0x%08X, iInTransaction=%d", |
|
684 this, iInTransaction); |
|
685 |
|
686 iFileStore->Revert(); |
|
687 iInTransaction = EFalse; |
|
688 ReinstateDeletedEntries(); |
|
689 } // CSmsPermanentFileStore::Revert |
|
690 |
|
691 /** |
|
692 * It commits the transaction. Then it compact the permanent store file. |
|
693 */ |
|
694 void CSmsPermanentFileStore::DoCommitAndCompactL() |
|
695 { |
|
696 LOGSMSPROT1("CSmsPermanentFileStore::DoCommitAndCompactL()"); |
|
697 |
|
698 LOGSMSPROTTIMESTAMP(); |
|
699 iFileStore->CommitL(); |
|
700 LOGSMSPROTTIMESTAMP(); |
|
701 |
|
702 iCommitCount--; |
|
703 if ((iCommitCount < 0) || (iCompact)) |
|
704 { |
|
705 iCommitCount = KNumStoreCommitsBeforeCompaction; |
|
706 iFileStore->CompactL(); |
|
707 iFileStore->CommitL(); |
|
708 iCompact = EFalse; |
|
709 } |
|
710 } // CSmsPermanentFileStore::DoCommitAndCompactL |
|
711 |
|
712 /** |
|
713 * It commits the transaction. |
|
714 */ |
|
715 void CSmsPermanentFileStore::CommitTransactionL() |
|
716 { |
|
717 LOGSMSPROT4("CSmsPermanentFileStore::CommitTransactionL(): this=0x%08X iInTransaction=%d iFileStore=0x%08X", |
|
718 this, iInTransaction, iFileStore); |
|
719 |
|
720 ExternalizeEntryArrayL(); |
|
721 |
|
722 #ifdef _SMS_LOGGING_ENABLED |
|
723 TRAPD(err, DoCommitAndCompactL()); |
|
724 if (err != KErrNone) |
|
725 { |
|
726 LOGGSMU2("WARNING! could not CommitL/CompactL due to %d", err); |
|
727 User::Leave(err); |
|
728 } |
|
729 #else |
|
730 DoCommitAndCompactL(); |
|
731 #endif |
|
732 |
|
733 iInTransaction = EFalse; |
|
734 RemoveDeletedEntries(); |
|
735 } |
|
736 |
|
737 /** |
|
738 * It removes the deleted entries from entry arry. |
|
739 * This function is called after commit. |
|
740 */ |
|
741 void CSmsPermanentFileStore::RemoveDeletedEntries() |
|
742 { |
|
743 LOGSMSPROT1("CSmsPermanentFileStore::RemoveDeletedEntries()"); |
|
744 |
|
745 TInt count=iEntryArray.Count(); |
|
746 while (count--) |
|
747 { |
|
748 TSmsReassemblyEntry& entry = iEntryArray[count]; |
|
749 |
|
750 if (entry.IsDeleted()) |
|
751 { |
|
752 iEntryArray.Delete(count); |
|
753 } |
|
754 else |
|
755 { |
|
756 entry.SetIsAdded(EFalse); |
|
757 } |
|
758 } |
|
759 } // CSmsPermanentFileStore::RemoveDeletedEntries |
|
760 |
|
761 /** |
|
762 * It reinstate the deleted/added entries from entry arry. |
|
763 * This function is called after revert operation. |
|
764 */ |
|
765 void CSmsPermanentFileStore::ReinstateDeletedEntries() |
|
766 { |
|
767 LOGSMSPROT1("CSmsPermanentFileStore::ReinstateDeletedEntries()"); |
|
768 |
|
769 TInt count=iEntryArray.Count(); |
|
770 while (count--) |
|
771 { |
|
772 TSmsReassemblyEntry& entry = iEntryArray[count]; |
|
773 |
|
774 if (entry.IsAdded()) |
|
775 { |
|
776 iEntryArray.Delete(count); |
|
777 } |
|
778 else |
|
779 { |
|
780 entry.SetIsDeleted(EFalse); |
|
781 } |
|
782 } |
|
783 } // CSmsPermanentFileStore::ReinstateDeletedEntries |
|
784 |
|
785 /** |
|
786 * Constructor |
|
787 * |
|
788 * @capability None |
|
789 */ |
|
790 TSmsPreAllocatedFileStoreReassemblyEntry::TSmsPreAllocatedFileStoreReassemblyEntry(): |
|
791 TSmsReassemblyEntry(), |
|
792 iPreAllocatedStorageId(0), |
|
793 iStatus(RMobileSmsStore::EStoredMessageUnknownStatus), |
|
794 iTimeOffset(0), |
|
795 iDecodedOnSim(EFalse), |
|
796 iForwardToClient(EFalse), |
|
797 iForwardedCount(0), |
|
798 iBitMap(NULL) |
|
799 { |
|
800 //Have to externalize so initialize to 0. |
|
801 for (TInt i=0; i<KBitMapLen; i++) |
|
802 { |
|
803 iBitMap.Append(0x00); |
|
804 } |
|
805 } |
|
806 |
|
807 /* |
|
808 It returns the reference of a particular bit-map index. |
|
809 |
|
810 @param aIndex index number of the bit-map. |
|
811 @param aBitMap bit-map value. |
|
812 |
|
813 @internalComponent |
|
814 */ |
|
815 void TSmsPreAllocatedFileStoreReassemblyEntry::GetBitMap(TUint8 aIndex, TUint8& aBitMap) |
|
816 { |
|
817 aBitMap = iBitMap[aIndex]; |
|
818 } |
|
819 |
|
820 /* |
|
821 It sets the value of a bit-map. |
|
822 |
|
823 @param aIndex index number of the bit-map. |
|
824 @param aBitMap bit-map value |
|
825 |
|
826 @internalComponent |
|
827 */ |
|
828 void TSmsPreAllocatedFileStoreReassemblyEntry::SetBitMap(TUint8 aIndex, TUint8 aBitMap) |
|
829 { |
|
830 iBitMap[aIndex] = aBitMap; |
|
831 } |
|
832 |
|
833 /** |
|
834 Static factory constructor. Uses two phase |
|
835 construction and leaves nothing on the CleanupStack. |
|
836 |
|
837 @param aFs File Server handle. |
|
838 @param aFileName Permanent file store name. |
|
839 @param aMaxClass0Msg max class 0 message that can be stored. |
|
840 @param aMaxPDUSeg max number of pdus that can be stored. |
|
841 @param aVersion version number of pre-allocated file. |
|
842 |
|
843 @return A pointer to the newly created CPreallocatedFile object. |
|
844 |
|
845 @pre A connected file server session must be passed as parameter. |
|
846 @post CPreallocatedFile object is now fully initialised |
|
847 |
|
848 @internalComponent |
|
849 */ |
|
850 CPreallocatedFile* CPreallocatedFile::NewL(RFs& aFs, const TDesC& aFileName, TInt aMaxClass0Msg, TInt aMaxPDUSeg, TPreAllocatedFileVersion aVersion) |
|
851 { |
|
852 LOGSMSPROT1("CPreallocatedFile::NewL()"); |
|
853 CPreallocatedFile* self = new (ELeave) CPreallocatedFile(aFs, aMaxClass0Msg, aMaxPDUSeg, aVersion); |
|
854 CleanupStack::PushL(self); |
|
855 self->ConstructL(aFileName); |
|
856 CleanupStack::Pop(self); |
|
857 |
|
858 return self; |
|
859 } |
|
860 |
|
861 void CPreallocatedFile::ConstructL(const TDesC& aFileName) |
|
862 { |
|
863 LOGSMSPROT1("CPreallocatedFile::ConstructL()"); |
|
864 iFileName = aFileName.AllocL(); |
|
865 } |
|
866 |
|
867 /** |
|
868 * Constructor. |
|
869 */ |
|
870 CPreallocatedFile::CPreallocatedFile(RFs& aFs, TInt aMaxClass0Msg, TInt aMaxPDUSeg, TPreAllocatedFileVersion aVersion) |
|
871 :iFs(aFs), iEntryArray(KFlatArrayGranularity), iReinstateEntryInfo(KFlatArrayGranularity), iMaxClass0Msg(aMaxClass0Msg), iMaxPDUSeg(aMaxPDUSeg), iVersion(aVersion) |
|
872 { |
|
873 /* |
|
874 Format of File: |
|
875 Version Number, Header Section & Data Section |
|
876 Version Number - Interger Value. |
|
877 Header Section: Number of entries, Array of Entries, Array of PDU identifier section, Checksum. |
|
878 Data Section: Array of Container. Each container contains Sms slot informatiuon, index number & PDU. |
|
879 */ |
|
880 |
|
881 // Calculate the size of each section. |
|
882 |
|
883 // Entry section will always contain one more entry than configured one by the user. |
|
884 // Because it will provide one extra slot to store the new message for time being |
|
885 // before forwarding the oldest message. |
|
886 iSizeOfEntrySection = (KSizeOfPreAllocatedStoreEntry * (iMaxClass0Msg + 1)); |
|
887 |
|
888 iSizeOfStorageIdentifierSection = ((sizeof(TInt))*(iMaxPDUSeg+1)); |
|
889 |
|
890 TInt sizeOfHeaderSection = KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection + KSizeOfChecksum; |
|
891 |
|
892 TInt sizeOfDataSection = KSizeOfAContainer * (iMaxPDUSeg+1); |
|
893 |
|
894 // Calculate the size of File. |
|
895 iSizeOfFile = KSizeOfPreallocatedFileVersion + 2 * sizeOfHeaderSection + sizeOfDataSection; |
|
896 |
|
897 iBeginOfDuplicateHeaderSection = KSizeOfPreallocatedFileVersion + sizeOfHeaderSection; |
|
898 iBeginOfDataSection = KSizeOfPreallocatedFileVersion + 2 * sizeOfHeaderSection; |
|
899 } |
|
900 |
|
901 /** |
|
902 * Destructor. It destroys all the member variables. |
|
903 */ |
|
904 CPreallocatedFile::~CPreallocatedFile() |
|
905 { |
|
906 delete iFileName; |
|
907 } |
|
908 |
|
909 /** |
|
910 It checks & returns whether the file exist or not. If file is there whether |
|
911 it is corrupted or not. |
|
912 |
|
913 @internalComponent |
|
914 */ |
|
915 TBool CPreallocatedFile::IsFileOK() |
|
916 { |
|
917 LOGSMSPROT1("CPreallocatedFile::IsFileOK()"); |
|
918 |
|
919 TEntry entry; |
|
920 // Check file exists |
|
921 TInt ret=iFs.Entry(iFileName->Des(), entry); |
|
922 // Check the size of file, if size does not match then assume that file |
|
923 // is corrupted, then return KErrNotFound. |
|
924 if ((ret == KErrNone) && (entry.iSize != iSizeOfFile)) |
|
925 { |
|
926 ret = KErrNotFound; |
|
927 } |
|
928 |
|
929 if (ret == KErrNone) |
|
930 { |
|
931 return ETrue; |
|
932 } |
|
933 else |
|
934 { |
|
935 return EFalse; |
|
936 } |
|
937 } |
|
938 |
|
939 /** |
|
940 It creates a pre-allocated file. |
|
941 |
|
942 @internalComponent |
|
943 */ |
|
944 void CPreallocatedFile::CreateL() |
|
945 { |
|
946 LOGSMSPROT1("CPreallocatedFile::CreateL"); |
|
947 |
|
948 User::LeaveIfError(iFile.Replace(iFs, iFileName->Des(), EFileWrite)); |
|
949 User::LeaveIfError(iFile.SetSize(iSizeOfFile)); |
|
950 iFile.Flush(); |
|
951 |
|
952 // Externalize Version Number |
|
953 //TInt version = iVersion; |
|
954 TPtr8 memPtr((TUint8*) &iVersion, KSizeOfPreallocatedFileVersion, KSizeOfPreallocatedFileVersion); |
|
955 iFile.Write(0, memPtr); |
|
956 |
|
957 //Externalize Header Information |
|
958 ExternalizeEntryArray(); |
|
959 |
|
960 // Initialize Storage Identifier Section. |
|
961 TInt storageIdentifier=0; |
|
962 memPtr.Set((TUint8*) &storageIdentifier, sizeof(storageIdentifier), sizeof(storageIdentifier)); |
|
963 TInt pos = KSizeOfNumberOfEntrySection + iSizeOfEntrySection; |
|
964 TInt pos2 = 0; |
|
965 for (TInt count=0; count<iMaxPDUSeg+1; count++) |
|
966 { |
|
967 pos2 = pos + count * sizeof(storageIdentifier); |
|
968 iFile.Write(KBeginOfMasterHeaderSection + pos2, memPtr); |
|
969 //iFile.Write(iBeginOfDuplicateHeaderSection + pos2, memPtr); |
|
970 } |
|
971 |
|
972 // Initialize Checksum |
|
973 PutChecksumValueL(); |
|
974 |
|
975 // Close it to make sure that file is created correctly (defensive approach). |
|
976 iFile.Close(); |
|
977 //Again Open the file |
|
978 OpenL(); |
|
979 } |
|
980 |
|
981 /** |
|
982 It opens the pre-allocated file. Then it internalizes all the entry information. |
|
983 |
|
984 @internalComponent |
|
985 */ |
|
986 void CPreallocatedFile::OpenL() |
|
987 { |
|
988 User::LeaveIfError(iFile.Open(iFs, iFileName->Des(), EFileShareExclusive|EFileRead|EFileWrite)); |
|
989 // Check the validity of the data. |
|
990 CheckDataL(); |
|
991 // Internalize data |
|
992 InternalizeEntryArrayL(); |
|
993 } |
|
994 |
|
995 /** |
|
996 It closes the pre-allocated file. |
|
997 |
|
998 @internalComponent |
|
999 */ |
|
1000 void CPreallocatedFile::Close() |
|
1001 { |
|
1002 iFile.Close(); |
|
1003 iEntryArray.Reset(); |
|
1004 iReinstateEntryInfo.Reset(); |
|
1005 } |
|
1006 |
|
1007 /** |
|
1008 It internalizes the entry info from pre-allocated file. |
|
1009 |
|
1010 @internalComponent |
|
1011 */ |
|
1012 void CPreallocatedFile::InternalizeEntryArrayL() |
|
1013 { |
|
1014 iEntryArray.Reset(); |
|
1015 TInt numberOfMessage; |
|
1016 TPtr8 memPtr((TUint8*) &numberOfMessage, sizeof(numberOfMessage), sizeof(numberOfMessage)); |
|
1017 iFile.Read(KBeginOfMasterHeaderSection, memPtr); |
|
1018 |
|
1019 TSmsPreAllocatedFileStoreReassemblyEntry tmpClass0ReassemblyStore; |
|
1020 memPtr.Set((TUint8*) &tmpClass0ReassemblyStore, KSizeOfPreAllocatedStoreEntry, KSizeOfPreAllocatedStoreEntry); |
|
1021 |
|
1022 TInt pos = 0; |
|
1023 for (TInt count=0; count < numberOfMessage; count++) |
|
1024 { |
|
1025 pos = sizeof(TInt) + (count * KSizeOfPreAllocatedStoreEntry); |
|
1026 iFile.Read(KBeginOfMasterHeaderSection + pos, memPtr); |
|
1027 iEntryArray.AppendL(tmpClass0ReassemblyStore); |
|
1028 } |
|
1029 } |
|
1030 |
|
1031 /** |
|
1032 It externalizes the entry info to pre-allocated file. |
|
1033 |
|
1034 @internalComponent |
|
1035 */ |
|
1036 void CPreallocatedFile::ExternalizeEntryArray() |
|
1037 { |
|
1038 TInt count=iEntryArray.Count(); |
|
1039 TInt numberOfMessage=0; |
|
1040 TInt i=0; |
|
1041 |
|
1042 for (; i<count; i++) |
|
1043 { |
|
1044 if (!iEntryArray[i].IsDeleted()) |
|
1045 { |
|
1046 numberOfMessage++; |
|
1047 } |
|
1048 } |
|
1049 |
|
1050 //Externalize number of mesages. |
|
1051 TPtr8 memPtr((TUint8*) &numberOfMessage, sizeof(numberOfMessage), sizeof(numberOfMessage)); |
|
1052 iFile.Write(KBeginOfMasterHeaderSection, memPtr); |
|
1053 |
|
1054 TInt entryNumber = 0; |
|
1055 //Externalize all the entries. |
|
1056 for (i=0; i<count; i++) |
|
1057 { |
|
1058 if (!iEntryArray[i].IsDeleted()) |
|
1059 { |
|
1060 //At the time of externalizing don't externalize IsAdded(), IsDeleted() value |
|
1061 TBool isAdded = iEntryArray[i].IsAdded(); |
|
1062 TBool isDeleted = iEntryArray[i].IsDeleted(); |
|
1063 iEntryArray[i].SetIsAdded(EFalse); |
|
1064 iEntryArray[i].SetIsDeleted(EFalse); |
|
1065 memPtr.Set((TUint8*) &iEntryArray[i], KSizeOfPreAllocatedStoreEntry, KSizeOfPreAllocatedStoreEntry); |
|
1066 iFile.Write(KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + (entryNumber * KSizeOfPreAllocatedStoreEntry), memPtr); |
|
1067 //Again update IsAdded(), IsDeleted() with previous value |
|
1068 iEntryArray[i].SetIsAdded(isAdded); |
|
1069 iEntryArray[i].SetIsDeleted(isDeleted); |
|
1070 entryNumber++; |
|
1071 } |
|
1072 } |
|
1073 |
|
1074 count = numberOfMessage; |
|
1075 /* |
|
1076 Externalize extra entry information with default information. |
|
1077 This initialization is required because of checksum. |
|
1078 */ |
|
1079 TSmsPreAllocatedFileStoreReassemblyEntry tmpClass0ReassemblyStore; |
|
1080 memPtr.Set((TUint8*) &tmpClass0ReassemblyStore, KSizeOfPreAllocatedStoreEntry, KSizeOfPreAllocatedStoreEntry); |
|
1081 TInt pos = 0; |
|
1082 for (; count<iMaxClass0Msg + 1; count++) |
|
1083 { |
|
1084 pos = KSizeOfNumberOfEntrySection + (count * KSizeOfPreAllocatedStoreEntry); |
|
1085 iFile.Write(KBeginOfMasterHeaderSection + pos, memPtr); |
|
1086 } |
|
1087 iFile.Flush(); |
|
1088 } |
|
1089 |
|
1090 /* |
|
1091 It adds the new message in pre-allocated file. |
|
1092 |
|
1093 @param aIndex (output) index number on which message is added. |
|
1094 @param aSmsMessage reference to sms message to be added. |
|
1095 @param aGsmSms reference to GsmSms object to be added. |
|
1096 |
|
1097 @internalComponent |
|
1098 */ |
|
1099 void CPreallocatedFile::AddNewMessageL(TInt& aIndex, CSmsMessage& aSmsMessage,const TGsmSms& aGsmSms) |
|
1100 { |
|
1101 LOGSMSPROT1("CPreallocatedFile::AddNewMessageL"); |
|
1102 //Gets the next free slot where the message will be stored. |
|
1103 TInt nextFreeSlot = GetFreeContainer(); |
|
1104 TInt pduIndex=aSmsMessage.IsDecoded()? 0: aSmsMessage.SmsPDU().ConcatenatedMessagePDUIndex(); |
|
1105 if (aSmsMessage.Storage() == CSmsMessage::ESmsSIMStorage || |
|
1106 aSmsMessage.Storage() == CSmsMessage::ESmsCombinedStorage) |
|
1107 { |
|
1108 const TGsmSmsSlotEntry& newSlot = aSmsMessage.iSlotArray[0]; |
|
1109 ExternalizeEntry(nextFreeSlot, newSlot, pduIndex, aGsmSms); |
|
1110 } |
|
1111 else |
|
1112 { |
|
1113 ExternalizeEntry(nextFreeSlot, pduIndex, aGsmSms); |
|
1114 } |
|
1115 |
|
1116 /* |
|
1117 Gets the unique id which will identify the containers where the |
|
1118 PDU related to this messsage are stored. |
|
1119 */ |
|
1120 TInt freeStorageId = GetFreeStorageId(); |
|
1121 AddStorageIdL(nextFreeSlot, freeStorageId); |
|
1122 |
|
1123 TSmsPreAllocatedFileStoreReassemblyEntry tmpEntry; |
|
1124 //Fill-up entry information... |
|
1125 CReassemblyStoreUtility::PopulateEntry(tmpEntry, aSmsMessage, 1); |
|
1126 tmpEntry.SetPreAllocatedStorageId(freeStorageId); |
|
1127 //The properties below need to be set only once when a PDU of a new message arrives. |
|
1128 tmpEntry.SetStatus((RMobileSmsStore::TMobileSmsStoreStatus)aSmsMessage.Status()); |
|
1129 tmpEntry.SetUTCOffset(aSmsMessage.UTCOffset()); |
|
1130 tmpEntry.SetDecodedOnSIM(aSmsMessage.DecodedOnSim()); |
|
1131 tmpEntry.SetForwardToClient(aSmsMessage.ForwardToClient()); |
|
1132 |
|
1133 // Add & extrenalize entry array. |
|
1134 aIndex = iEntryArray.Count(); |
|
1135 AddEntryL(tmpEntry); |
|
1136 } |
|
1137 |
|
1138 /* |
|
1139 It updates the existing message in permanent store file. |
|
1140 |
|
1141 @param aIndex index number on which message is to be updated. |
|
1142 @param aSmsMessage reference to sms message to be updated. |
|
1143 @param aPduIndex index of the PDU to be updated. |
|
1144 @param aSms sms of the PDU to be updated. |
|
1145 |
|
1146 @internalComponent |
|
1147 */ |
|
1148 void CPreallocatedFile::UpdateExistingMessageL(TInt aIndex, const CSmsMessage& aSmsMessage, TInt aPduIndex, const TGsmSms& aSms) |
|
1149 { |
|
1150 LOGSMSPROT1("CPreallocatedFile::UpdateExistingMessageL()"); |
|
1151 TInt preAllocatedStorageId = iEntryArray[aIndex].PreAllocatedStorageId(); |
|
1152 if (preAllocatedStorageId == KErrNotFound) |
|
1153 { |
|
1154 /* |
|
1155 This condition arises when part of message is stored in permanent store file & |
|
1156 other parts arrive when system is out of disk. |
|
1157 */ |
|
1158 preAllocatedStorageId = GetFreeStorageId(); |
|
1159 iEntryArray[aIndex].SetPreAllocatedStorageId(preAllocatedStorageId); |
|
1160 } |
|
1161 // Externalize Entry in one of free containers. |
|
1162 TInt freeSlot = GetFreeContainer(); |
|
1163 if (aSmsMessage.Storage() == CSmsMessage::ESmsSIMStorage || |
|
1164 aSmsMessage.Storage() == CSmsMessage::ESmsCombinedStorage) |
|
1165 { |
|
1166 const TGsmSmsSlotEntry& newSlot = aSmsMessage.iSlotArray[0]; |
|
1167 ExternalizeEntry(freeSlot, newSlot, aPduIndex, aSms); |
|
1168 } |
|
1169 else |
|
1170 { |
|
1171 ExternalizeEntry(freeSlot, aPduIndex, aSms); |
|
1172 } |
|
1173 |
|
1174 AddStorageIdL(freeSlot, preAllocatedStorageId); |
|
1175 TSmsPreAllocatedFileStoreReassemblyEntry entry; |
|
1176 entry = iEntryArray[aIndex]; |
|
1177 /* |
|
1178 This value must be set because this may the first PDU of an |
|
1179 existing message which is stored in pre-allocated store file. |
|
1180 */ |
|
1181 entry.SetPreAllocatedStorageId(preAllocatedStorageId); |
|
1182 entry.SetCount(entry.Count()+1); |
|
1183 ChangeEntryL(aIndex, entry); |
|
1184 } |
|
1185 |
|
1186 /* |
|
1187 It matches the entry with entry in pre-allocated file & returns |
|
1188 the index. If not found it returns KErrNotFound. |
|
1189 |
|
1190 @param aEntry reference to entry information. |
|
1191 @param aIndex (output) returns the index number. |
|
1192 |
|
1193 @internalComponent |
|
1194 */ |
|
1195 void CPreallocatedFile::MatchEntryToExistingMessage(const TReassemblyEntry& aEntry, |
|
1196 TInt& aIndex) |
|
1197 { |
|
1198 LOGSMSPROT1("CPreallocatedFile::MatchEntryToExistingMessage()"); |
|
1199 |
|
1200 aIndex = KErrNotFound; |
|
1201 |
|
1202 // |
|
1203 // Search the reassembly store for a matching entry... |
|
1204 // |
|
1205 TInt reassemblyCount = iEntryArray.Count(); |
|
1206 |
|
1207 for (TInt index = 0; index < reassemblyCount; index++) |
|
1208 { |
|
1209 TSmsPreAllocatedFileStoreReassemblyEntry& entry = iEntryArray[index]; |
|
1210 |
|
1211 if (entry.Reference() == aEntry.Reference() && |
|
1212 entry.Total() == aEntry.Total() && |
|
1213 entry.PduType() == aEntry.PduType() && |
|
1214 entry.Storage() == aEntry.Storage() && |
|
1215 entry.Description2() == aEntry.Description2()) |
|
1216 { |
|
1217 // |
|
1218 // Found it! |
|
1219 // |
|
1220 aIndex = index; |
|
1221 break; |
|
1222 } |
|
1223 } |
|
1224 |
|
1225 LOGSMSPROT2("CPreallocatedFile::MatchEntryToExistingMessage(): aIndex=%d", aIndex); |
|
1226 } |
|
1227 |
|
1228 /* |
|
1229 It updates the log server id of the message. |
|
1230 |
|
1231 @param aIndex index number of the message to be updated. |
|
1232 @param aLogServerId log server id. |
|
1233 |
|
1234 @internalComponent |
|
1235 */ |
|
1236 void CPreallocatedFile::UpdateLogServerIdL(TInt& aIndex, TLogId aLogServerId) |
|
1237 { |
|
1238 LOGSMSPROT1("CPreallocatedFile::UpdateLogServerId"); |
|
1239 |
|
1240 TSmsPreAllocatedFileStoreReassemblyEntry entry; |
|
1241 entry = iEntryArray[aIndex]; |
|
1242 |
|
1243 if (entry.LogServerId() != aLogServerId) |
|
1244 { |
|
1245 entry.SetLogServerId(aLogServerId); |
|
1246 ChangeEntryL(aIndex, entry); |
|
1247 } |
|
1248 } |
|
1249 |
|
1250 /* |
|
1251 It sets the message passed to client or not. |
|
1252 |
|
1253 @param aIndex index number of the message to be updated. |
|
1254 @param aBool boolean value indicating whether message is passes or not. |
|
1255 |
|
1256 @internalComponent |
|
1257 */ |
|
1258 void CPreallocatedFile::SetPassedToClientL(TInt aIndex, TBool aBool) |
|
1259 { |
|
1260 LOGSMSPROT2("CPreallocatedFile::SetPassedToClientL(): aIndex=%d", aIndex); |
|
1261 |
|
1262 TSmsPreAllocatedFileStoreReassemblyEntry entry; |
|
1263 entry = iEntryArray[aIndex]; |
|
1264 |
|
1265 if (entry.PassedToClient() != aBool) |
|
1266 { |
|
1267 entry.SetPassedToClient(aBool); |
|
1268 ChangeEntryL(aIndex, entry); |
|
1269 } |
|
1270 } |
|
1271 |
|
1272 /* |
|
1273 It adds the new entry in the existing entry array. |
|
1274 |
|
1275 @param aEntry entry to be added. |
|
1276 |
|
1277 @internalComponent |
|
1278 */ |
|
1279 void CPreallocatedFile::AddEntryL(TSmsPreAllocatedFileStoreReassemblyEntry& aEntry) |
|
1280 { |
|
1281 LOGSMSPROT1("CPreallocatedFile::AddEntryL"); |
|
1282 iEntryArray.AppendL(aEntry); |
|
1283 iEntryArray[iEntryArray.Count()-1].SetIsAdded(ETrue); |
|
1284 } |
|
1285 |
|
1286 /* |
|
1287 It changes the existing entry with new entry. |
|
1288 |
|
1289 @param aIndex index number of the entry which will be changed. |
|
1290 @param aNewEntry entry to be updated. |
|
1291 |
|
1292 @internalComponent |
|
1293 */ |
|
1294 void CPreallocatedFile::ChangeEntryL(TInt aIndex, const TSmsPreAllocatedFileStoreReassemblyEntry& aNewEntry) |
|
1295 { |
|
1296 LOGSMSPROT2("CPreallocatedFile::ChangeEntryL(): aIndex=%d", aIndex); |
|
1297 iEntryArray[aIndex].SetIsDeleted(ETrue); |
|
1298 iEntryArray.InsertL(aIndex,aNewEntry); |
|
1299 iEntryArray[aIndex].SetIsAdded(ETrue); |
|
1300 } |
|
1301 |
|
1302 /* |
|
1303 It deletes the entry. |
|
1304 |
|
1305 @param aIndex index number of the entry which will be deleted. |
|
1306 |
|
1307 @internalComponent |
|
1308 */ |
|
1309 void CPreallocatedFile::DeleteEntryL(TInt aIndex) |
|
1310 { |
|
1311 LOGSMSPROT2("CPreallocatedFile::DeleteEntryL(): aIndex=%d", aIndex); |
|
1312 if (iEntryArray[aIndex].PreAllocatedStorageId() != KErrNotFound) |
|
1313 { |
|
1314 ClearEntryL(iEntryArray[aIndex].PreAllocatedStorageId(), iEntryArray[aIndex].Count()); |
|
1315 } |
|
1316 iEntryArray[aIndex].SetIsDeleted(ETrue); |
|
1317 } |
|
1318 |
|
1319 /* |
|
1320 It searches all the container & clears all the entries which |
|
1321 contain the PDUs of the message (uniquely identified by aStorageId). |
|
1322 |
|
1323 NOTE: |
|
1324 It keeps the record of removed entries (container id, pre-allocated storage id |
|
1325 & operation performed (add/delete)) in iReinstateEntryInfo variable. |
|
1326 It will be required in case of revert operation. As the container which |
|
1327 refers to the container which contains actual PDU is freed, |
|
1328 so it will not be a problem to restore the removed PDUs. |
|
1329 In case of revert operation, the removed information can be found in |
|
1330 iReinstateEntryInfo variable which can be restored easily. |
|
1331 The container can be replaced with previous pre-allocated storage id. |
|
1332 After commiting the transaction, this varaible will be re-initialized. |
|
1333 |
|
1334 @param aStorageId unique id of message to be cleared. |
|
1335 @param aNumberOfPDUs number of PDUs to be cleared. |
|
1336 |
|
1337 @internalComponent |
|
1338 */ |
|
1339 void CPreallocatedFile::ClearEntryL(TInt aStorageId, TInt aNumberOfPDUs) |
|
1340 { |
|
1341 LOGSMSPROT1("CPreallocatedFile::ClearEntryL"); |
|
1342 |
|
1343 //Read storage id. |
|
1344 TInt storageId; |
|
1345 TPtr8 memPtr((TUint8*) &storageId, sizeof(storageId), sizeof(storageId)); |
|
1346 TInt beginOfStorageIdSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection; |
|
1347 TInt beginOfStorageId = 0; |
|
1348 TInt count; |
|
1349 TInt count2(0); |
|
1350 |
|
1351 TInt cleanStorageId=0; |
|
1352 TPtr8 memPtr2((TUint8*) &cleanStorageId, sizeof(cleanStorageId), sizeof(cleanStorageId)); |
|
1353 |
|
1354 for (count=0; count<iMaxPDUSeg+1; count++) |
|
1355 { |
|
1356 TReinstateEntryInfo entry; |
|
1357 entry.iPreAllocatedStorageId=aStorageId; |
|
1358 entry.iFlag=EEntryIsDeleted; |
|
1359 |
|
1360 beginOfStorageId = beginOfStorageIdSection + (count * sizeof(storageId)); |
|
1361 iFile.Read(beginOfStorageId, memPtr); |
|
1362 if (storageId == aStorageId) |
|
1363 { |
|
1364 count2++; |
|
1365 iFile.Write(beginOfStorageId, memPtr2); |
|
1366 entry.iContainerId=count+1; |
|
1367 iReinstateEntryInfo.AppendL(entry); |
|
1368 } |
|
1369 if (count2 >= aNumberOfPDUs) |
|
1370 { |
|
1371 break; |
|
1372 } |
|
1373 } |
|
1374 iFile.Flush(); |
|
1375 } |
|
1376 |
|
1377 /* |
|
1378 It updates the storage identifier section. It updates the corresponding container |
|
1379 in the storage identifier section specifying the PDU where it is stored. |
|
1380 |
|
1381 NOTE: |
|
1382 It keeps the record of added entries in iReinstateEntryInfo variable. |
|
1383 It will be required in case of revert operation. |
|
1384 After commiting the transaction, this varaible should be re-initialized. |
|
1385 |
|
1386 @param aIndex index number of the container where PDU has been stored.. |
|
1387 @param aStorageId unique id of added message. |
|
1388 |
|
1389 @internalComponent |
|
1390 */ |
|
1391 void CPreallocatedFile::AddStorageIdL(TInt aIndex, TInt aStorageId) |
|
1392 { |
|
1393 //Put storage id in master header section |
|
1394 TPtr8 memPtr((TUint8*) &aStorageId, sizeof(aStorageId), sizeof(aStorageId)); |
|
1395 TInt beginOfStorageIdentifierSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection; |
|
1396 iFile.Write( beginOfStorageIdentifierSection + ((aIndex - 1) * sizeof(TInt)), memPtr); |
|
1397 |
|
1398 TReinstateEntryInfo entry; |
|
1399 entry.iContainerId=aIndex; |
|
1400 entry.iPreAllocatedStorageId=aStorageId; |
|
1401 entry.iFlag=EEntryIsAdded; |
|
1402 iReinstateEntryInfo.AppendL(entry); |
|
1403 } |
|
1404 |
|
1405 /* |
|
1406 It returns the next free available free container where next PDU can be stored. |
|
1407 |
|
1408 It goes through storage identifier section, it reads the conents of all storage |
|
1409 identfier & return that container which is free. |
|
1410 All the free container is identifiable by value 0. If the value is not 0 then it |
|
1411 contains the storage id of a particular message. |
|
1412 |
|
1413 @internalComponent |
|
1414 */ |
|
1415 TInt CPreallocatedFile::GetFreeContainer() |
|
1416 { |
|
1417 // Get the next free slot. |
|
1418 TInt storageId; |
|
1419 TPtr8 memPtr((TUint8*) &storageId, sizeof(storageId), sizeof(storageId)); |
|
1420 TInt beginOfStorageIdSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection; |
|
1421 TInt beginOfStorageId = 0; |
|
1422 TInt count; |
|
1423 |
|
1424 for (count=0; count<iMaxPDUSeg+1; count++) |
|
1425 { |
|
1426 beginOfStorageId = beginOfStorageIdSection + (count * sizeof(storageId)); |
|
1427 iFile.Read(beginOfStorageId, memPtr); |
|
1428 if (storageId == 0) |
|
1429 { |
|
1430 break; |
|
1431 } |
|
1432 } |
|
1433 |
|
1434 // Count should never equal to iMaxPDUSeg+1 |
|
1435 __ASSERT_DEBUG(count < iMaxPDUSeg+1, SmspPanic(KSmspPanicPreallocatedFileNoFreeContainer)); |
|
1436 |
|
1437 return (count + 1); |
|
1438 } |
|
1439 |
|
1440 /* |
|
1441 It returns the next free storage id. |
|
1442 |
|
1443 Storage id is used to identify the messages stored in pre-allocated file. |
|
1444 A message might contain multiple PDUs and all those PDUs will be stored in |
|
1445 different container. This storage id will be used to identify on which |
|
1446 container the PDUs of a message are stored. |
|
1447 |
|
1448 This logic is based on the max number of messages that can be stored in |
|
1449 pre-allocated file at one time. So free storage id is always used from |
|
1450 this pool of numbers (from 1 till (max calls 0 message+2)). |
|
1451 |
|
1452 @internalComponent |
|
1453 */ |
|
1454 TInt CPreallocatedFile::GetFreeStorageId() |
|
1455 { |
|
1456 TInt count; |
|
1457 |
|
1458 for (count=1; count < iMaxClass0Msg + 2; count++) |
|
1459 { |
|
1460 TInt numberOfEntries = iEntryArray.Count(); |
|
1461 TInt count2; |
|
1462 for (count2 = 0; count2 < numberOfEntries; count2++) |
|
1463 { |
|
1464 if (count == iEntryArray[count2].PreAllocatedStorageId()) |
|
1465 { |
|
1466 break; |
|
1467 } |
|
1468 } |
|
1469 if (count2 == numberOfEntries) |
|
1470 { |
|
1471 break; |
|
1472 } |
|
1473 } |
|
1474 return count; |
|
1475 } |
|
1476 |
|
1477 /* |
|
1478 It externalizes(writes) the entry in permanent store file. |
|
1479 |
|
1480 @param aContainerId container id where the sms pdu needs to externalized. |
|
1481 @param aSmsSlot reference to slot information. |
|
1482 @param aIndex index number of PDU. |
|
1483 @param aGsmSms refence to sms pdu. |
|
1484 |
|
1485 @internalComponent |
|
1486 */ |
|
1487 void CPreallocatedFile::ExternalizeEntry(TInt aContainerId, const TGsmSmsSlotEntry& aSmsSlot, TInt aIndex, const TGsmSms& aGsmSms) |
|
1488 { |
|
1489 LOGSMSPROT3("CPreallocatedFile::ExternalizeEntry() 1: aContainerId=%d, aIndex=%d", aContainerId, aIndex); |
|
1490 |
|
1491 // Container id must not be greater than max pdu segment. |
|
1492 TInt pos = iBeginOfDataSection + ((aContainerId - 1) * (KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU)); |
|
1493 // Store slot info |
|
1494 TPtr8 memPtr((TUint8*) &aSmsSlot, sizeof(aSmsSlot), sizeof(aSmsSlot)); |
|
1495 iFile.Write(pos, memPtr); |
|
1496 // Store the PDU index value |
|
1497 memPtr.Set((TUint8*) &aIndex, sizeof(aIndex), sizeof(aIndex)); |
|
1498 iFile.Write(pos + KSizeOfGsmSmsSlotEntry, memPtr); |
|
1499 // Store the TGsmSms value |
|
1500 RMobileSmsMessaging::TMobileSmsGsmTpdu pdu; |
|
1501 pdu = aGsmSms.Pdu(); |
|
1502 memPtr.Set((TUint8*) &pdu, KSizeOfSmsGsmPDU, KSizeOfSmsGsmPDU); |
|
1503 iFile.Write(pos + KSizeOfGsmSmsSlotEntry + sizeof(TInt), memPtr); |
|
1504 |
|
1505 __ASSERT_DEBUG(pos + KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU <= iSizeOfFile, |
|
1506 SmspPanic(KSmspPanicPreallocatedFileCorrupt)); |
|
1507 } |
|
1508 |
|
1509 /* |
|
1510 It externalizes(writes) the entry in permanent store file. |
|
1511 |
|
1512 @param aContainerId container id where the sms pdu needs to externalized. |
|
1513 @param aIndex index number of PDU. |
|
1514 @param aGsmSms refence to sms pdu. |
|
1515 |
|
1516 @internalComponent |
|
1517 */ |
|
1518 void CPreallocatedFile::ExternalizeEntry(TInt aContainerId, TInt aIndex, const TGsmSms& aGsmSms) |
|
1519 { |
|
1520 LOGSMSPROT3("CPreallocatedFile::ExternalizeEntry() 2: aContainerId=%d, aIndex=%d", aContainerId, aIndex); |
|
1521 |
|
1522 // Container id must not be greater than max pdu segment. |
|
1523 TInt pos = iBeginOfDataSection + ((aContainerId - 1) * (KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU)); |
|
1524 // Store the PDU index value |
|
1525 TPtr8 memPtr((TUint8*) &aIndex, sizeof(aIndex), sizeof(aIndex)); |
|
1526 iFile.Write(pos + KSizeOfGsmSmsSlotEntry, memPtr); |
|
1527 // Store the TGsmSms value |
|
1528 RMobileSmsMessaging::TMobileSmsGsmTpdu pdu; |
|
1529 pdu = aGsmSms.Pdu(); |
|
1530 memPtr.Set((TUint8*) &pdu, KSizeOfSmsGsmPDU, KSizeOfSmsGsmPDU); |
|
1531 iFile.Write(pos + KSizeOfGsmSmsSlotEntry + sizeof(TInt), memPtr); |
|
1532 |
|
1533 __ASSERT_DEBUG(pos + KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU <= iSizeOfFile, |
|
1534 SmspPanic(KSmspPanicPreallocatedFileCorrupt)); |
|
1535 } |
|
1536 |
|
1537 /* |
|
1538 It internalizes(reads) the entry from permanent store file. |
|
1539 |
|
1540 @param aIndex index number of the message to be internalized. |
|
1541 @param aSmsMessage (output) reference to sms message. |
|
1542 @param aIndexArray (output) refence to array of index. |
|
1543 @param aSmsArray (output) refence to array of sms. |
|
1544 |
|
1545 @internalComponent |
|
1546 */ |
|
1547 void CPreallocatedFile::InternalizeEntryL(const TInt aIndex, CSmsMessage& aSmsMessage, CArrayFix<TInt>& aIndexArray, CArrayFix<TGsmSms>& aSmsArray) |
|
1548 { |
|
1549 LOGSMSPROT1("CPreallocatedFile::InternalizeEntryL"); |
|
1550 TSmsPreAllocatedFileStoreReassemblyEntry& entry = iEntryArray[aIndex]; |
|
1551 //Set other properties of CSmsMessage |
|
1552 aSmsMessage.SetStorage(entry.Storage()); |
|
1553 aSmsMessage.SetStatus((NMobileSmsStore::TMobileSmsStoreStatus)entry.Status()); |
|
1554 aSmsMessage.SetLogServerId(entry.LogServerId()); |
|
1555 aSmsMessage.SetTime(entry.Time()); |
|
1556 aSmsMessage.SetUTCOffset(entry.UTCOffset()); |
|
1557 aSmsMessage.SetDecodedOnSIM(entry.DecodedOnSIM()); |
|
1558 aSmsMessage.SetForwardToClient(entry.ForwardToClient()); |
|
1559 aSmsMessage.SetToFromAddressL(entry.Description2()); |
|
1560 |
|
1561 LOGSMSPROT2("CPreallocatedFile::InternalizeEntryL Start [sid=%d]", entry.PreAllocatedStorageId()); |
|
1562 if (entry.PreAllocatedStorageId()==KErrNotFound) |
|
1563 { |
|
1564 return; |
|
1565 } |
|
1566 |
|
1567 TInt beginOfStorageIdSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection; |
|
1568 //This will be used to read the storgae id which will indicate |
|
1569 //that corresponding container contains actual PDU |
|
1570 TInt storageId=0; |
|
1571 TPtr8 memPtr1((TUint8*) &storageId, sizeof(storageId), sizeof(storageId)); |
|
1572 |
|
1573 TInt storageIdPos = 0; |
|
1574 TInt dataPos = 0; |
|
1575 //This will be used to read the slot information |
|
1576 TGsmSmsSlotEntry smsSlotEntry; |
|
1577 TPtr8 memPtr2((TUint8*) &smsSlotEntry, KSizeOfGsmSmsSlotEntry, KSizeOfGsmSmsSlotEntry); |
|
1578 //This will be used to read the concatenated PDU index. |
|
1579 TInt index=0; |
|
1580 TPtr8 memPtr3((TUint8*) &index, sizeof(index), sizeof(index)); |
|
1581 //This will be used to read PDU. |
|
1582 RMobileSmsMessaging::TMobileSmsGsmTpdu pdu; |
|
1583 TPtr8 memPtr4((TUint8*) &pdu, KSizeOfSmsGsmPDU, KSizeOfSmsGsmPDU); |
|
1584 TGsmSms sms; |
|
1585 |
|
1586 //Number of PDUs stored in this pre-allocated file |
|
1587 TInt noOfPDUs = iEntryArray[aIndex].Count(); |
|
1588 //Will indicate how many number of PDUs already read from pre-allocated file. |
|
1589 TInt noOfPDUsRead = 0; |
|
1590 // Can also get the number of pdu stored in pre-allocated file from count's variable. |
|
1591 for (TInt count=0; count<iMaxPDUSeg+1; count++) |
|
1592 { |
|
1593 storageIdPos = beginOfStorageIdSection + count * sizeof(TInt); |
|
1594 iFile.Read(storageIdPos, memPtr1); |
|
1595 if (storageId == entry.PreAllocatedStorageId()) |
|
1596 {//This means corresponding container contains the actual PDU |
|
1597 noOfPDUsRead++; |
|
1598 //Find the position of container where actaul PDU is stored. |
|
1599 dataPos = iBeginOfDataSection + ((count) * (KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU)); |
|
1600 //Read slot information |
|
1601 if (entry.Storage() == CSmsMessage::ESmsSIMStorage || |
|
1602 entry.Storage() == CSmsMessage::ESmsCombinedStorage) |
|
1603 { |
|
1604 iFile.Read(dataPos + KSizeOfGsmSmsSlotEntry, memPtr2); |
|
1605 aSmsMessage.AddSlotL(smsSlotEntry); |
|
1606 } |
|
1607 //Read index information |
|
1608 iFile.Read(dataPos + KSizeOfGsmSmsSlotEntry, memPtr3); |
|
1609 aIndexArray.AppendL(index); |
|
1610 //Read PDU |
|
1611 iFile.Read(dataPos + KSizeOfGsmSmsSlotEntry + sizeof(index), memPtr4); |
|
1612 sms.SetPdu(pdu); |
|
1613 aSmsArray.AppendL(sms); |
|
1614 if (noOfPDUsRead == noOfPDUs) |
|
1615 { |
|
1616 break; |
|
1617 } |
|
1618 } |
|
1619 } |
|
1620 |
|
1621 LOGSMSPROT2("CPreallocatedFile::InternalizeEntryL End [noOfPDUsRead=%d]", noOfPDUsRead); |
|
1622 } |
|
1623 |
|
1624 /* |
|
1625 It removes the PDUs from pre-allocated store file. |
|
1626 This function is needed because after forwarding the incomplete message |
|
1627 to client, the corresponding PDUs needs to be be removed from permanent |
|
1628 store file. |
|
1629 This functionality is specific to class 0 re-assembly store. |
|
1630 |
|
1631 @param aIndex index number of the message to be removed. |
|
1632 @param aStartPos starting pos of pdu to be removed. |
|
1633 @param aEndPos end pos of pdu to be removed. |
|
1634 |
|
1635 @internalComponent |
|
1636 */ |
|
1637 void CPreallocatedFile::RemovePDUsL(TInt aIndex, TInt aStartPos, TInt aEndPos) |
|
1638 { |
|
1639 LOGSMSPROT1("CPreallocatedFile::RemovePDUsL"); |
|
1640 |
|
1641 if ((aStartPos < 1) || (aEndPos > 256) || (aStartPos > aEndPos)) |
|
1642 { |
|
1643 User::Leave(KErrArgument); |
|
1644 } |
|
1645 |
|
1646 LOGSMSPROT2("CPreallocatedFile::RemovePDUsL Start [sid=%d]", iEntryArray[aIndex].PreAllocatedStorageId()); |
|
1647 if (iEntryArray[aIndex].PreAllocatedStorageId()==KErrNotFound) |
|
1648 { |
|
1649 return; |
|
1650 } |
|
1651 |
|
1652 TInt beginOfStorageIdSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection; |
|
1653 //This will be used to read the storgae id which will indicate |
|
1654 //that corresponding container contains actual PDU |
|
1655 TInt storageId=0; |
|
1656 TPtr8 memPtr1((TUint8*) &storageId, sizeof(storageId), sizeof(storageId)); |
|
1657 |
|
1658 //This will be used to cleanup the storage id. |
|
1659 TInt cleanStorageId=0; |
|
1660 TPtr8 memPtr2((TUint8*) &cleanStorageId, sizeof(cleanStorageId), sizeof(cleanStorageId)); |
|
1661 |
|
1662 //This will be used to read the concatenated PDU index. |
|
1663 TInt index=0; |
|
1664 TPtr8 memPtr3((TUint8*) &index, sizeof(index), sizeof(index)); |
|
1665 |
|
1666 //Number of PDUs stored in this pre-allocated file |
|
1667 TInt noOfPDUs = iEntryArray[aIndex].Count(); |
|
1668 //Will indicate how many number of PDUs already read from pre-allocated file. |
|
1669 TInt noOfPDUsRead = 0; |
|
1670 // Can also get the number of pdu stored in pre-allocated file from count's variable. |
|
1671 TInt noOfEntriesRemoved=0; |
|
1672 for (TInt count=0; count<iMaxPDUSeg+1; count++) |
|
1673 { |
|
1674 TInt storageIdPos = beginOfStorageIdSection + count * sizeof(TInt); |
|
1675 iFile.Read(storageIdPos, memPtr1); |
|
1676 if (storageId == iEntryArray[aIndex].PreAllocatedStorageId()) |
|
1677 {//This means corresponding container contains the actual PDU |
|
1678 noOfPDUsRead++; |
|
1679 //Find the position of container where actaul PDU is stored. |
|
1680 TInt dataPos = iBeginOfDataSection + ((count) * (KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU)); |
|
1681 //Read index information |
|
1682 iFile.Read(dataPos + KSizeOfGsmSmsSlotEntry, memPtr3); |
|
1683 |
|
1684 if ((index >= aStartPos) && (index <= aEndPos)) |
|
1685 { |
|
1686 noOfEntriesRemoved++; |
|
1687 //Remove the PDU entry. |
|
1688 iFile.Write(storageIdPos, memPtr2); |
|
1689 } |
|
1690 |
|
1691 if (noOfPDUsRead == noOfPDUs) |
|
1692 { |
|
1693 break; |
|
1694 } |
|
1695 } |
|
1696 } |
|
1697 |
|
1698 /* |
|
1699 There are 3 scenarios in this case: |
|
1700 1. If all the entries need to be removed, |
|
1701 then there is no need to store the entry in this permanent file. |
|
1702 2. If few entries need to be removed, |
|
1703 then externalize the remaining entries. Update count field also. |
|
1704 3. If no entries need to be removed, then do nothing. |
|
1705 */ |
|
1706 TSmsPreAllocatedFileStoreReassemblyEntry entry; |
|
1707 entry = iEntryArray[aIndex]; |
|
1708 |
|
1709 if (entry.Count() == noOfEntriesRemoved) |
|
1710 { |
|
1711 entry.SetPreAllocatedStorageId(KErrNotFound); |
|
1712 entry.SetCount(0); |
|
1713 ChangeEntryL(aIndex, entry); |
|
1714 } |
|
1715 else if (noOfEntriesRemoved > 0) |
|
1716 { |
|
1717 entry.SetCount(entry.Count() - noOfEntriesRemoved); |
|
1718 ChangeEntryL(aIndex, entry); |
|
1719 } |
|
1720 } |
|
1721 |
|
1722 /* |
|
1723 It stores the forwarded message info in forwarded pdu bit-map. |
|
1724 |
|
1725 @param aIndex index number of the forwarded message. |
|
1726 @param aStartPos starting pos of forwarded pdu. |
|
1727 @param aEndPos end pos of forwarded pdu. |
|
1728 |
|
1729 @internalComponent |
|
1730 */ |
|
1731 void CPreallocatedFile::StoreForwardedPDUsInfoL(TInt aIndex, TInt aStartPos, TInt aEndPos) |
|
1732 { |
|
1733 TSmsPreAllocatedFileStoreReassemblyEntry entry; |
|
1734 entry = iEntryArray[aIndex]; |
|
1735 |
|
1736 TUint8 startBitMapIndex = (aStartPos-1)/8; |
|
1737 TUint8 endBitMapIndex = (aEndPos-1)/8; |
|
1738 TUint8 startBitPos = (aStartPos-1)%8; |
|
1739 TUint8 endBitPos = (aEndPos-1)%8; |
|
1740 |
|
1741 if (startBitMapIndex == endBitMapIndex) |
|
1742 { |
|
1743 TUint8 bitMap; |
|
1744 entry.GetBitMap(startBitMapIndex, bitMap); |
|
1745 TUint8 tmpBitMap = (0 | 0xFF); |
|
1746 tmpBitMap <<= ((8 - endBitPos) - 1); |
|
1747 tmpBitMap >>= (8 - ((endBitPos - startBitPos)+1)); |
|
1748 tmpBitMap <<= startBitPos; |
|
1749 bitMap |= tmpBitMap; |
|
1750 entry.SetBitMap(startBitMapIndex, bitMap); |
|
1751 } |
|
1752 else |
|
1753 { |
|
1754 TUint8 bitMap; |
|
1755 entry.GetBitMap(startBitMapIndex, bitMap); |
|
1756 TUint8 tmpBitMap = (0 | 0xFF); |
|
1757 tmpBitMap >>= (8 - ((7 - startBitPos)+1)); |
|
1758 tmpBitMap <<= startBitPos; |
|
1759 bitMap |= tmpBitMap; |
|
1760 entry.SetBitMap(startBitMapIndex, bitMap); |
|
1761 |
|
1762 entry.GetBitMap(endBitMapIndex, bitMap); |
|
1763 tmpBitMap = (0 | 0xFF); |
|
1764 tmpBitMap <<= ((8 - endBitPos) - 1); |
|
1765 tmpBitMap >>= (8 - ((endBitPos - 0)+1)); |
|
1766 tmpBitMap <<= 0; |
|
1767 bitMap |= tmpBitMap; |
|
1768 entry.SetBitMap(endBitMapIndex, bitMap); |
|
1769 } |
|
1770 |
|
1771 TInt noOfForwardedPDUs = (aEndPos - aStartPos) + 1; |
|
1772 entry.SetNumberOfPDUsForwardToClient(entry.NumberOfPDUsForwardToClient()+noOfForwardedPDUs); |
|
1773 |
|
1774 ChangeEntryL(aIndex, entry); |
|
1775 } |
|
1776 |
|
1777 /* |
|
1778 It checks the validity of master header section by comparing checksum value. |
|
1779 If the checksum value does not match, then it copies data from duplicate header section to |
|
1780 master header section. |
|
1781 */ |
|
1782 void CPreallocatedFile::CheckDataL() |
|
1783 { |
|
1784 TUint32 checksum; |
|
1785 TInt checksumPos = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection; |
|
1786 |
|
1787 TPtr8 memPtr((TUint8*) &checksum, sizeof(checksum), sizeof(checksum)); |
|
1788 iFile.Read(checksumPos, memPtr); |
|
1789 |
|
1790 if (ChecksumValue() != checksum) |
|
1791 { |
|
1792 CopyDuplicateToMasterL(); |
|
1793 } |
|
1794 } |
|
1795 |
|
1796 /* |
|
1797 It writes the checksum value & then copies header information from master section to duplicate section. |
|
1798 */ |
|
1799 void CPreallocatedFile::PutChecksumValueL() |
|
1800 { |
|
1801 TUint32 checksum = ChecksumValue(); |
|
1802 TInt checksumPos = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection; |
|
1803 |
|
1804 TPtr8 memPtr((TUint8*) &checksum, sizeof(checksum), sizeof(checksum)); |
|
1805 iFile.Write(checksumPos, memPtr); |
|
1806 iFile.Flush(); |
|
1807 CopyMasterToDuplicateL(); |
|
1808 } |
|
1809 |
|
1810 /* |
|
1811 It calculates & returns the checksum value of master header section. |
|
1812 */ |
|
1813 TUint32 CPreallocatedFile::ChecksumValue() |
|
1814 { |
|
1815 TInt sizeOfDataToBeChecksum = KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection; |
|
1816 |
|
1817 TUint32 checksum(0); |
|
1818 |
|
1819 TUint32 tmpValue; |
|
1820 TPtr8 memPtr((TUint8*) &tmpValue, sizeof(tmpValue), sizeof(tmpValue)); |
|
1821 |
|
1822 for (TInt i = 0; i < sizeOfDataToBeChecksum/4 ; i++) |
|
1823 { |
|
1824 iFile.Read(KBeginOfMasterHeaderSection + (i*4), memPtr); |
|
1825 checksum += tmpValue; |
|
1826 } |
|
1827 return checksum; |
|
1828 } |
|
1829 |
|
1830 /* |
|
1831 It copies header information from master copy to duplicate copy. |
|
1832 */ |
|
1833 void CPreallocatedFile::CopyMasterToDuplicateL() |
|
1834 { |
|
1835 TInt sizeOfDataToBeCopied = KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection + 4; |
|
1836 |
|
1837 HBufC8* heapBuffer = HBufC8::NewL(sizeOfDataToBeCopied); |
|
1838 CleanupStack::PushL(heapBuffer); |
|
1839 TPtr8 memPtr(heapBuffer->Des()); |
|
1840 iFile.Read(KBeginOfMasterHeaderSection, memPtr); |
|
1841 iFile.Write(iBeginOfDuplicateHeaderSection, memPtr); |
|
1842 iFile.Flush(); |
|
1843 CleanupStack::PopAndDestroy(heapBuffer); |
|
1844 } |
|
1845 |
|
1846 /* |
|
1847 It copies header information from duplicate copy to master copy. |
|
1848 */ |
|
1849 void CPreallocatedFile::CopyDuplicateToMasterL() |
|
1850 { |
|
1851 TInt sizeOfDataToBeCopied = KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection + 4; |
|
1852 |
|
1853 HBufC8* heapBuffer = HBufC8::NewL(sizeOfDataToBeCopied); |
|
1854 CleanupStack::PushL(heapBuffer); |
|
1855 TPtr8 memPtr(heapBuffer->Des()); |
|
1856 iFile.Read(iBeginOfDuplicateHeaderSection, memPtr); |
|
1857 iFile.Write(KBeginOfMasterHeaderSection, memPtr); |
|
1858 iFile.Flush(); |
|
1859 CleanupStack::PopAndDestroy(heapBuffer); |
|
1860 } |
|
1861 |
|
1862 /* |
|
1863 It returns the total number of PDUs stored in pre-allocated file. |
|
1864 */ |
|
1865 TInt CPreallocatedFile::NumberOfPDUStored() |
|
1866 { |
|
1867 TInt noOfPDUs = 0; |
|
1868 for (TInt i = 0; i < iEntryArray.Count(); i++) |
|
1869 { |
|
1870 noOfPDUs += iEntryArray[i].Count(); |
|
1871 } |
|
1872 return noOfPDUs; |
|
1873 } |
|
1874 |
|
1875 /** |
|
1876 * Sets the pre-allocated file store as in-transaction. |
|
1877 * |
|
1878 * The function checks the validity of the call and leaves KErrAccessDenied if |
|
1879 * invalid. |
|
1880 * @capability None |
|
1881 */ |
|
1882 void CPreallocatedFile::BeginTransactionL() |
|
1883 { |
|
1884 LOGSMSPROT3("CPreallocatedFile::BeginTransactionL [this=0x%08X iInTransaction=%d]", this, iInTransaction); |
|
1885 |
|
1886 if (iInTransaction) |
|
1887 { |
|
1888 LOGGSMU1("WARNING CPreallocatedFile::BeginTransactionL leaving with KErrAccessDenied"); |
|
1889 User::Leave(KErrAccessDenied); |
|
1890 } |
|
1891 |
|
1892 iInTransaction = ETrue; |
|
1893 } |
|
1894 |
|
1895 /** |
|
1896 * It commits the transaction. |
|
1897 */ |
|
1898 void CPreallocatedFile::CommitTransactionL() |
|
1899 { |
|
1900 LOGSMSPROT3("CPreallocatedFile::CommitTransactionL(): this=0x%08X iInTransaction=%d", |
|
1901 this, iInTransaction); |
|
1902 |
|
1903 ExternalizeEntryArray(); |
|
1904 //Commit |
|
1905 PutChecksumValueL(); |
|
1906 iInTransaction = EFalse; |
|
1907 iReinstateEntryInfo.Reset(); |
|
1908 RemoveDeletedEntries(); |
|
1909 } |
|
1910 |
|
1911 /* |
|
1912 It reverts the transaction. |
|
1913 */ |
|
1914 void CPreallocatedFile::Revert() |
|
1915 { |
|
1916 LOGSMSPROT3("CPreallocatedFile::Revert(): this=0x%08X, iInTransaction=%d", |
|
1917 this, iInTransaction); |
|
1918 |
|
1919 ReinstateEntries(); |
|
1920 ExternalizeEntryArray(); |
|
1921 iInTransaction = EFalse; |
|
1922 ReinstateDeletedEntries(); |
|
1923 } |
|
1924 |
|
1925 /** |
|
1926 * It removes the deleted entries from entry arry. |
|
1927 * This function is called after commit. |
|
1928 */ |
|
1929 void CPreallocatedFile::RemoveDeletedEntries() |
|
1930 { |
|
1931 LOGSMSPROT1("CPreallocatedFile::RemoveDeletedEntries()"); |
|
1932 |
|
1933 TInt count=iEntryArray.Count(); |
|
1934 while (count--) |
|
1935 { |
|
1936 TSmsPreAllocatedFileStoreReassemblyEntry& entry = iEntryArray[count]; |
|
1937 |
|
1938 if (entry.IsDeleted()) |
|
1939 { |
|
1940 iEntryArray.Delete(count); |
|
1941 } |
|
1942 else |
|
1943 { |
|
1944 entry.SetIsAdded(EFalse); |
|
1945 } |
|
1946 } |
|
1947 } // CPreallocatedFile::RemoveDeletedEntries |
|
1948 |
|
1949 /** |
|
1950 * It reinstate the deleted/added entries from entry arry. |
|
1951 * This function is called after revert operation. |
|
1952 */ |
|
1953 void CPreallocatedFile::ReinstateDeletedEntries() |
|
1954 { |
|
1955 LOGSMSPROT1("CPreallocatedFile::ReinstateDeletedEntries()"); |
|
1956 |
|
1957 TInt count=iEntryArray.Count(); |
|
1958 while (count--) |
|
1959 { |
|
1960 TSmsPreAllocatedFileStoreReassemblyEntry& entry = iEntryArray[count]; |
|
1961 |
|
1962 if (entry.IsAdded()) |
|
1963 { |
|
1964 iEntryArray.Delete(count); |
|
1965 } |
|
1966 else |
|
1967 { |
|
1968 entry.SetIsDeleted(EFalse); |
|
1969 } |
|
1970 } |
|
1971 } // CPreallocatedFile::ReinstateDeletedEntries |
|
1972 |
|
1973 /** |
|
1974 * It reinstate the deleted/added entries from the container. |
|
1975 * This function is called at the time of revert operation. |
|
1976 * Unlike permanent store file which supports revert. pre-allocated |
|
1977 * file (raw data file) supports the revert mecahnism using this function. |
|
1978 */ |
|
1979 void CPreallocatedFile::ReinstateEntries() |
|
1980 { |
|
1981 LOGSMSPROT1("CPreallocatedFile::ReinstateEntries()"); |
|
1982 |
|
1983 TInt containerId; |
|
1984 TInt storageId; |
|
1985 TPtr8 memPtr((TUint8*) &storageId, sizeof(storageId), sizeof(storageId)); |
|
1986 |
|
1987 TInt count = iReinstateEntryInfo.Count(); |
|
1988 |
|
1989 for (TInt i=0; i<count; i++) |
|
1990 { |
|
1991 if (iReinstateEntryInfo[i].iFlag == EEntryIsDeleted) |
|
1992 { |
|
1993 //Add the Pre-allocated storage info in the container. |
|
1994 storageId = iReinstateEntryInfo[i].iPreAllocatedStorageId; |
|
1995 containerId = iReinstateEntryInfo[i].iContainerId; |
|
1996 TInt beginOfStorageIdentifierSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection; |
|
1997 iFile.Write( beginOfStorageIdentifierSection + ((containerId - 1) * sizeof(TInt)), memPtr); |
|
1998 } |
|
1999 else //EEntryIsAdded |
|
2000 { |
|
2001 //Delete the Pre-allocated storage info from the container. |
|
2002 storageId = 0; |
|
2003 containerId = iReinstateEntryInfo[i].iContainerId; |
|
2004 TInt beginOfStorageIdentifierSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection; |
|
2005 iFile.Write( beginOfStorageIdentifierSection + ((containerId - 1) * sizeof(TInt)), memPtr); |
|
2006 } |
|
2007 } |
|
2008 iFile.Flush(); |
|
2009 iReinstateEntryInfo.Reset(); |
|
2010 } |
|
2011 |
|
2012 /* |
|
2013 It returns the index of oldest message in pre-allocated file. |
|
2014 */ |
|
2015 TInt CPreallocatedFile::GetOldestMessageEntryIndex() |
|
2016 { |
|
2017 LOGSMSPROT1("CPreallocatedFile::GetOldestMessageEntryIndex()"); |
|
2018 |
|
2019 TInt index = KErrNotFound; |
|
2020 TTime time; |
|
2021 time.UniversalTime(); |
|
2022 |
|
2023 for (TInt index2=0; index2 < iEntryArray.Count(); index2++) |
|
2024 { |
|
2025 if ((iEntryArray[index2].Time() < time) && (iEntryArray[index2].Count()>0)) |
|
2026 { |
|
2027 time = iEntryArray[index2].Time(); |
|
2028 index = index2; |
|
2029 } |
|
2030 } |
|
2031 return index; |
|
2032 } |
|
2033 |
|
2034 /** |
|
2035 Static factory constructor. Uses two phase |
|
2036 construction and leaves nothing on the CleanupStack. |
|
2037 |
|
2038 @param aClass0ReassemblyStore reference to class 0 reasembly store. |
|
2039 @param aGuardTimeout guard time out in hours. |
|
2040 |
|
2041 @return A pointer to the newly created CGuardTimer object. |
|
2042 |
|
2043 @internalComponent |
|
2044 */ |
|
2045 CGuardTimer* CGuardTimer::NewL(CClass0SmsReassemblyStore& aClass0ReassemblyStore, TInt aGuardTimeout) |
|
2046 { |
|
2047 LOGSMSPROT1("CGuardTimer::NewL()"); |
|
2048 |
|
2049 CGuardTimer* timer = new(ELeave) CGuardTimer(aClass0ReassemblyStore, aGuardTimeout); |
|
2050 CleanupStack::PushL(timer); |
|
2051 timer->ConstructL(); |
|
2052 CleanupStack::Pop(); |
|
2053 return timer; |
|
2054 } // CGuardTimer::NewL |
|
2055 |
|
2056 /** |
|
2057 * Constructor |
|
2058 */ |
|
2059 CGuardTimer::CGuardTimer(CClass0SmsReassemblyStore& aClass0ReassemblyStore, TInt aGuardTimeout) |
|
2060 :CTimer(KSmsSessionPriority), |
|
2061 iClass0ReassemblyStore(aClass0ReassemblyStore), |
|
2062 iTimeoutInSecs(aGuardTimeout*3600) |
|
2063 { |
|
2064 CActiveScheduler::Add(this); |
|
2065 } //CGuardTimer::CGuardTimer |
|
2066 |
|
2067 /** |
|
2068 * Destructor |
|
2069 */ |
|
2070 CGuardTimer::~CGuardTimer() |
|
2071 { |
|
2072 Cancel(); |
|
2073 } // CGuardTimer::~CGuardTimer |
|
2074 |
|
2075 /** |
|
2076 * Enable the Gurad Timer |
|
2077 */ |
|
2078 void CGuardTimer::EnableGuardTimer() |
|
2079 { |
|
2080 LOGSMSPROT1("CGuardTimer::EnableGuardTimer()"); |
|
2081 if (!IsActive()) |
|
2082 { |
|
2083 TTime nextTimeOut; |
|
2084 iClass0ReassemblyStore.GetNextGuardTimeout(nextTimeOut); |
|
2085 At(nextTimeOut); |
|
2086 } |
|
2087 } //CGuardTimer::EnableGuardTimer |
|
2088 |
|
2089 /** |
|
2090 * Disable the Gurad Timer |
|
2091 */ |
|
2092 void CGuardTimer::DisableGuardTimer() |
|
2093 { |
|
2094 Cancel(); |
|
2095 } |
|
2096 |
|
2097 /** |
|
2098 * Timer completed |
|
2099 */ |
|
2100 void CGuardTimer::RunL() |
|
2101 { |
|
2102 LOGSMSPROT2("CGuardTimer::RunL [iStatus=%d]", iStatus.Int()); |
|
2103 iClass0ReassemblyStore.ProcessTimeoutMessageL(); |
|
2104 EnableGuardTimer(); |
|
2105 } // CGuardTimer::RunL |
|
2106 |
|
2107 /** |
|
2108 Static factory constructor. Uses two phase |
|
2109 construction and leaves nothing on the CleanupStack. |
|
2110 |
|
2111 @param aFs File Server handle. |
|
2112 @param aSmsComm reference to MSmsComm event handler. |
|
2113 |
|
2114 @return A pointer to the newly created CClass0SmsReassemblyStore object. |
|
2115 |
|
2116 @pre A connected file server session must be passed as parameter. |
|
2117 @post CClass0SmsReassemblyStore object is now fully initialised |
|
2118 |
|
2119 @internalComponent |
|
2120 */ |
|
2121 CClass0SmsReassemblyStore* CClass0SmsReassemblyStore::NewL(RFs& aFs, MSmsComm& aSmsComm) |
|
2122 { |
|
2123 LOGSMSPROT1("CClass0SmsReassemblyStore::NewL()"); |
|
2124 |
|
2125 CClass0SmsReassemblyStore* self = new (ELeave) CClass0SmsReassemblyStore(aFs, aSmsComm); |
|
2126 CleanupStack::PushL(self); |
|
2127 self->ConstructL(); |
|
2128 CleanupStack::Pop(self); |
|
2129 |
|
2130 return self; |
|
2131 } |
|
2132 |
|
2133 /** |
|
2134 * C'tor |
|
2135 */ |
|
2136 CClass0SmsReassemblyStore::CClass0SmsReassemblyStore(RFs& aFs, MSmsComm& aSmsComm) |
|
2137 :CReassemblyStore(aFs), iSmsComm(aSmsComm), iPermanentFileStore(NULL), iPreallocatedFile(NULL), |
|
2138 iGuardTimer(NULL), iInTransaction(EFalse), iDiskSpaceStatus(ESmsDiskSpaceAvailable) |
|
2139 { |
|
2140 } |
|
2141 |
|
2142 /** |
|
2143 * D'tor |
|
2144 */ |
|
2145 CClass0SmsReassemblyStore::~CClass0SmsReassemblyStore() |
|
2146 { |
|
2147 delete iPermanentFileStore; |
|
2148 delete iPreallocatedFile; |
|
2149 delete iGuardTimer; |
|
2150 } |
|
2151 |
|
2152 /* |
|
2153 It constructs permanent and pre-allocated file to store the class 0 messages. |
|
2154 It creates a guard timer so that messages can be deleted if all the constituent |
|
2155 PDU of a message is not received within configured time-frame. |
|
2156 It also reserves 4KB disk space so that reserved space can be used to |
|
2157 delete a stream from permanent file store in out-of-disk condition. |
|
2158 |
|
2159 @internalComponent |
|
2160 */ |
|
2161 void CClass0SmsReassemblyStore::ConstructL() |
|
2162 { |
|
2163 //Reserve Drive Space |
|
2164 User::LeaveIfError(iFs.ReserveDriveSpace(KStoreDrive, 4*1024)); |
|
2165 |
|
2166 //Read Configuration file |
|
2167 ReadConfigurableClass0SmsSettingsL(iMaxClass0Msg, iMaxPDUSeg, iGuardTimeOut); |
|
2168 //Create Permanent store file |
|
2169 TFileName permanentStoreFileName; |
|
2170 CReassemblyStoreUtility::PrivatePath(iFs, permanentStoreFileName); |
|
2171 permanentStoreFileName.Append(KClass0ReassemblyStoreName); |
|
2172 iPermanentFileStore = CSmsPermanentFileStore::NewL(iFs, permanentStoreFileName, KClass0ReassemblyStoreUid); |
|
2173 //Create Pre-allocated file |
|
2174 TFileName preAllocatedFileName; |
|
2175 CReassemblyStoreUtility::PrivatePath(iFs, preAllocatedFileName); |
|
2176 preAllocatedFileName.Append(KPreAllocatedFileName); |
|
2177 iPreallocatedFile = CPreallocatedFile::NewL(iFs, preAllocatedFileName, iMaxClass0Msg, iMaxPDUSeg); |
|
2178 //Create Gurad Timer |
|
2179 iGuardTimer = CGuardTimer::NewL(*this, iGuardTimeOut); |
|
2180 } |
|
2181 |
|
2182 /* |
|
2183 It reads class 0 re-assembly store configuration information from smswap.sms.esk file. |
|
2184 It reads the following information: MaxClass0Messages, NumberOfPDUSegements, GuardTimeOut. |
|
2185 If any of the above element is missing it takes the default value. |
|
2186 |
|
2187 @internalComponent |
|
2188 */ |
|
2189 void CClass0SmsReassemblyStore::ReadConfigurableClass0SmsSettingsL(TInt& aMaxClass0Msg, TInt& aMaxPDUSeg, TInt& aGuardTimeOut) |
|
2190 { |
|
2191 LOGSMSPROT1("CClass0SmsReassemblyStore::ReadConfigurableClass0SmsSettingsL()"); |
|
2192 |
|
2193 aMaxClass0Msg = KMaxNumberOfClass0MessagesInReassemblyStore; |
|
2194 aMaxPDUSeg = KNumberOfPDUSegmentsStoredInOODCondition; |
|
2195 aGuardTimeOut = KGuardTimeOut; |
|
2196 |
|
2197 CESockIniData* ini = NULL; |
|
2198 TRAPD(ret, ini=CESockIniData::NewL(_L("smswap.sms.esk"))); |
|
2199 if(ret!=KErrNone) |
|
2200 { |
|
2201 LOGSMSPROT2("CESockIniData::NewL() returned=%d", ret); |
|
2202 } |
|
2203 else |
|
2204 { |
|
2205 CleanupStack::PushL(ini); |
|
2206 |
|
2207 TInt var(0); |
|
2208 if(ini->FindVar(_L("ReassemblyStore"),_L("MaxClass0Messages"),var)) |
|
2209 { |
|
2210 if (var > 0) |
|
2211 { |
|
2212 LOGSMSPROT2("MaxClass0Messages [%d]", var); |
|
2213 aMaxClass0Msg = var; |
|
2214 } |
|
2215 } |
|
2216 |
|
2217 if(ini->FindVar(_L("ReassemblyStore"),_L("NumberOfPDUSegements"),var)) |
|
2218 { |
|
2219 if (var > 0) |
|
2220 { |
|
2221 LOGSMSPROT2("MaxClass0Messages [%d]", var); |
|
2222 aMaxPDUSeg = var; |
|
2223 } |
|
2224 } |
|
2225 |
|
2226 if(ini->FindVar(_L("ReassemblyStore"),_L("GuardTimeOut"),var)) |
|
2227 { |
|
2228 if (var > 0) |
|
2229 { |
|
2230 LOGSMSPROT2("MaxClass0Messages [%d]", var); |
|
2231 aGuardTimeOut = var; |
|
2232 } |
|
2233 } |
|
2234 |
|
2235 CleanupStack::PopAndDestroy(ini); |
|
2236 } |
|
2237 |
|
2238 LOGSMSPROT4("CClass0SmsReassemblyStore::ReadConfigurableClass0SmsSettingsL(): aMaxClass0Msg=%d, aMaxPDUSeg=%d, aGuardTimeOut=%d", |
|
2239 aMaxClass0Msg, aMaxPDUSeg, aGuardTimeOut); |
|
2240 } |
|
2241 |
|
2242 /** |
|
2243 It opens the class 0 re-assembly store. |
|
2244 Then it populates the entry information (all the messages stored in re-assembly store). |
|
2245 |
|
2246 @internalComponent |
|
2247 */ |
|
2248 void CClass0SmsReassemblyStore::OpenStoreL() |
|
2249 { |
|
2250 LOGSMSPROT1("CClass0SmsReassemblyStore::OpenStoreL()"); |
|
2251 TFileName pathName; |
|
2252 CReassemblyStoreUtility::PrivatePath(iFs, pathName); |
|
2253 //Create the directory if it is not created. |
|
2254 iFs.MkDirAll(pathName); |
|
2255 // If any one file becomes corrupt or does not exist then we have to create both files. |
|
2256 if (iPreallocatedFile->IsFileOK() && iPermanentFileStore->IsFileOK()) |
|
2257 { |
|
2258 iPreallocatedFile->OpenL(); |
|
2259 iPermanentFileStore->OpenL(); |
|
2260 } |
|
2261 else |
|
2262 { |
|
2263 iPreallocatedFile->CreateL(); |
|
2264 iPermanentFileStore->CreateL(); |
|
2265 } |
|
2266 PopulateEntryArrayL(iEntryArray); |
|
2267 iGuardTimer->EnableGuardTimer(); |
|
2268 } |
|
2269 |
|
2270 /** |
|
2271 It closes the class 0 re-assembly store. |
|
2272 |
|
2273 @internalComponent |
|
2274 */ |
|
2275 void CClass0SmsReassemblyStore::Close() |
|
2276 { |
|
2277 LOGSMSPROT1("CClass0SmsReassemblyStore::CloseStore()"); |
|
2278 iGuardTimer->DisableGuardTimer(); |
|
2279 iEntryArray.Reset(); |
|
2280 iPreallocatedFile->Close(); |
|
2281 iPermanentFileStore->Close(); |
|
2282 } |
|
2283 |
|
2284 /** |
|
2285 It populates the entry information stored in class 0 reassembly store. |
|
2286 |
|
2287 @param aEntryArray reference to entry array. |
|
2288 |
|
2289 @internalComponent |
|
2290 */ |
|
2291 void CClass0SmsReassemblyStore::PopulateEntryArrayL(CArrayFix<TReassemblyEntry>& aEntryArray) |
|
2292 { |
|
2293 LOGSMSPROT1("CClass0SmsReassemblyStore::PopulateEntryArrayL()"); |
|
2294 aEntryArray.Reset(); |
|
2295 //Populate Entries from Pre-allocated file. |
|
2296 for (TInt count = 0; count < iPreallocatedFile->Entries().Count(); count++) |
|
2297 { |
|
2298 TReassemblyEntry entry; |
|
2299 entry.SetReference(iPreallocatedFile->Entries()[count].Reference()); |
|
2300 entry.SetTotal(iPreallocatedFile->Entries()[count].Total()); |
|
2301 entry.SetCount(iPreallocatedFile->Entries()[count].Count()+iPreallocatedFile->Entries()[count].NumberOfPDUsForwardToClient()); |
|
2302 entry.SetLogServerId(iPreallocatedFile->Entries()[count].LogServerId()); |
|
2303 |
|
2304 // Check that descriptor2 (sms address )is not corrupted |
|
2305 TPtrC ptr = iPreallocatedFile->Entries()[count].Description2(); |
|
2306 |
|
2307 if (ptr.Length() <= CSmsAddress::KSmsAddressMaxAddressLength) |
|
2308 { |
|
2309 entry.SetDescription2(iPreallocatedFile->Entries()[count].Description2()); |
|
2310 } |
|
2311 |
|
2312 entry.SetPduType(iPreallocatedFile->Entries()[count].PduType()); |
|
2313 entry.SetStorage(iPreallocatedFile->Entries()[count].Storage()); |
|
2314 entry.SetTime(iPreallocatedFile->Entries()[count].Time()); |
|
2315 entry.SetPassedToClient(iPreallocatedFile->Entries()[count].PassedToClient()); |
|
2316 aEntryArray.AppendL(entry); |
|
2317 } |
|
2318 |
|
2319 /* |
|
2320 Then populate the entries from permanent store file. It is needed |
|
2321 because permanent store file might contain few mesages. |
|
2322 But before populating the entry information it is needed to cleanup |
|
2323 the entries in permanent store file. It is needed to ensure that permanent file |
|
2324 clean itself with pre-allocated file. There migth be a scenario where |
|
2325 user has deleted a message but the corresponding message has not been |
|
2326 deleted from permanent store file due to out-of-disk condition. |
|
2327 And also at the time of forwarding an incomplete message a forwarded |
|
2328 message has not been deleted due to above reason. But the entry/PDU is |
|
2329 invalid because it is no more in the pre-allocated file which |
|
2330 contains master header info. |
|
2331 */ |
|
2332 TInt ret = CleanReassemblyEntries(); |
|
2333 |
|
2334 if (ret == KErrNone) |
|
2335 { |
|
2336 /* |
|
2337 In this case permanent store file contains correct information. |
|
2338 So populate Entry information from Permanent store file. |
|
2339 In this case only count information needs to be updated. |
|
2340 */ |
|
2341 TInt permanentFileStoreIndex; |
|
2342 for (TInt i=0; i<aEntryArray.Count(); i++) |
|
2343 { |
|
2344 permanentFileStoreIndex=KErrNotFound; |
|
2345 iPermanentFileStore->MatchEntryToExistingMessage(aEntryArray[i], permanentFileStoreIndex); |
|
2346 if (permanentFileStoreIndex!=KErrNotFound) |
|
2347 { |
|
2348 aEntryArray[i].SetCount(aEntryArray[i].Count() + iPermanentFileStore->Entries()[permanentFileStoreIndex].Count()); |
|
2349 if (aEntryArray[i].Count() > aEntryArray[i].Total()) |
|
2350 { |
|
2351 aEntryArray[i].SetCount(aEntryArray[i].Total()); |
|
2352 } |
|
2353 } |
|
2354 } |
|
2355 } |
|
2356 else if (ret == KErrDiskFull) |
|
2357 { |
|
2358 LOGSMSPROT1("CleanReassemblyEntries() returns KErrDiskFull"); |
|
2359 /* |
|
2360 In this case permanent store file contains incorrect information. |
|
2361 For example forwarded message might be still stored in this store. |
|
2362 Because it has not been deleted due to out-of-disk condition. |
|
2363 So be careful at the time of updating the count information |
|
2364 about the message. |
|
2365 */ |
|
2366 TInt permanentFileStoreIndex; |
|
2367 for (TInt i=0; i<aEntryArray.Count(); i++) |
|
2368 { |
|
2369 permanentFileStoreIndex=KErrNotFound; |
|
2370 iPermanentFileStore->MatchEntryToExistingMessage(aEntryArray[i], permanentFileStoreIndex); |
|
2371 if (permanentFileStoreIndex!=KErrNotFound) |
|
2372 { |
|
2373 TSmsPreAllocatedFileStoreReassemblyEntry entry = iPreallocatedFile->Entries()[i]; |
|
2374 if (entry.NumberOfPDUsForwardToClient() > 0) |
|
2375 { |
|
2376 //Internalize the entries. |
|
2377 CSmsBuffer* buffer = CSmsBuffer::NewL(); |
|
2378 CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer); |
|
2379 CleanupStack::PushL(smsMessage); |
|
2380 |
|
2381 CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity); |
|
2382 CleanupStack::PushL(indexArray); |
|
2383 CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity); |
|
2384 CleanupStack::PushL(smsArray); |
|
2385 //Internalize to check whether removed PDUs still stored in Permanent store file. |
|
2386 iPermanentFileStore->InternalizeEntryL(permanentFileStoreIndex, *smsMessage, *indexArray, *smsArray); |
|
2387 TInt noOfForwardedEntries=0; |
|
2388 for (TInt j=0; j<indexArray->Count() ;j++) |
|
2389 { |
|
2390 TUint8 bitMapIndex = (indexArray->At(j)-1)/8; |
|
2391 TUint8 bitPos = (indexArray->At(j)-1)%8; |
|
2392 TUint8 bitMap; |
|
2393 entry.GetBitMap(bitMapIndex, bitMap); |
|
2394 TUint8 tmpBitMap = 1; |
|
2395 tmpBitMap <<= bitPos; |
|
2396 if (tmpBitMap == (bitMap & tmpBitMap)) |
|
2397 { |
|
2398 noOfForwardedEntries++; |
|
2399 } |
|
2400 } |
|
2401 TInt count = iPermanentFileStore->Entries()[permanentFileStoreIndex].Count() - noOfForwardedEntries; |
|
2402 aEntryArray[i].SetCount(aEntryArray[i].Count() + count); |
|
2403 |
|
2404 CleanupStack::PopAndDestroy(3, smsMessage); // smsMessage, indexArray, smsArray |
|
2405 } |
|
2406 else |
|
2407 { |
|
2408 aEntryArray[i].SetCount(aEntryArray[i].Count() + iPermanentFileStore->Entries()[permanentFileStoreIndex].Count()); |
|
2409 } |
|
2410 } |
|
2411 } |
|
2412 } |
|
2413 else |
|
2414 { |
|
2415 User::Leave(ret); |
|
2416 } |
|
2417 } |
|
2418 |
|
2419 /** |
|
2420 It sets the disk space status. |
|
2421 If disk space is full, then class 0 re-assembly store stores the incoming message in |
|
2422 pre-allocated file. Otherwise it stores the message in permanent store file. |
|
2423 */ |
|
2424 void CClass0SmsReassemblyStore::SetDiskSpaceState(TSmsDiskSpaceMonitorStatus aDiskSpaceStatus) |
|
2425 { |
|
2426 LOGSMSPROT1("CClass0SmsReassemblyStore::SetDiskSpaceState()"); |
|
2427 iDiskSpaceStatus = aDiskSpaceStatus; |
|
2428 } |
|
2429 |
|
2430 /* |
|
2431 It adds the new message in class 0 reassembly store. |
|
2432 It first tries to add the message in permanent store file. If it is |
|
2433 successful, then it adds the entry information in pre-allocated file. |
|
2434 Because pre-allocated file contains master header entry information. |
|
2435 Otherwise (if disk space is full), it adds the message in pre-allocated file. |
|
2436 |
|
2437 @param aSmsMessage reference to sms message to be added. |
|
2438 @param aGsmSms reference to GsmSms object to be added. |
|
2439 |
|
2440 @internalComponent |
|
2441 */ |
|
2442 void CClass0SmsReassemblyStore::AddNewMessageL(CSmsMessage& aSmsMessage,const TGsmSms& aGsmSms) |
|
2443 { |
|
2444 LOGSMSPROT1("CClass0SmsReassemblyStore::AddNewMessageL"); |
|
2445 |
|
2446 // Add entry in permanent store file |
|
2447 TInt index; |
|
2448 TInt ret = KErrNone; |
|
2449 |
|
2450 if (iDiskSpaceStatus == ESmsDiskSpaceFull) |
|
2451 { |
|
2452 ret = KErrDiskFull; |
|
2453 } |
|
2454 else |
|
2455 { |
|
2456 TRAP(ret, iPermanentFileStore->AddNewMessageL(index, aSmsMessage, aGsmSms)); |
|
2457 } |
|
2458 |
|
2459 if (ret == KErrNone) |
|
2460 { |
|
2461 // Add a new entry in pre-allocated file |
|
2462 TSmsPreAllocatedFileStoreReassemblyEntry tmpEntry; |
|
2463 //Fill-up entry information... |
|
2464 CReassemblyStoreUtility::PopulateEntry(tmpEntry, aSmsMessage, 1); |
|
2465 |
|
2466 //The properties below need to be set only once when a PDU of a new message arrives. |
|
2467 tmpEntry.SetStatus((RMobileSmsStore::TMobileSmsStoreStatus)aSmsMessage.Status()); |
|
2468 tmpEntry.SetUTCOffset(aSmsMessage.UTCOffset()); |
|
2469 tmpEntry.SetDecodedOnSIM(aSmsMessage.DecodedOnSim()); |
|
2470 tmpEntry.SetForwardToClient(aSmsMessage.ForwardToClient()); |
|
2471 //Set KErrNotFound because message corresponding to |
|
2472 //this entry is not in this pr-allocated file. |
|
2473 tmpEntry.SetPreAllocatedStorageId(KErrNotFound); |
|
2474 //Has to set 0 because PDU is stored in Permanent store file instead of pre-allocated file. |
|
2475 tmpEntry.SetCount(0); |
|
2476 |
|
2477 iPreallocatedFile->AddEntryL(tmpEntry); |
|
2478 } |
|
2479 else if (ret == KErrDiskFull) |
|
2480 { |
|
2481 // Add the new message in pre-allocated file |
|
2482 iPreallocatedFile->AddNewMessageL(index, aSmsMessage, aGsmSms); |
|
2483 } |
|
2484 else |
|
2485 { |
|
2486 User::Leave(ret); |
|
2487 } |
|
2488 } |
|
2489 |
|
2490 /* |
|
2491 It updates the existing message in class 0 re-assembly store. |
|
2492 |
|
2493 @param aSmsMessage reference to sms message to be updated. |
|
2494 @param aGsmSms reference to GsmSms object to be added. |
|
2495 @param aDuplicateMsgRef boolean value (output) indicates whether the added PDU is a duplicate or not. |
|
2496 @param aDuplicateSlot boolean value (output) indicates whether the added PDU is a duplicate enumerated PDU. |
|
2497 |
|
2498 @internalComponent |
|
2499 */ |
|
2500 void CClass0SmsReassemblyStore::UpdateExistingMessageL(CSmsMessage& aSmsMessage, const TGsmSms& aGsmSms, TBool& aDuplicateMsgRef, TBool& aDuplicateSlot) |
|
2501 { |
|
2502 LOGSMSPROT1("CClass0SmsReassemblyStore::UpdateExistingMessageL()"); |
|
2503 |
|
2504 aDuplicateMsgRef = EFalse; |
|
2505 aDuplicateSlot = EFalse; |
|
2506 |
|
2507 CSmsBuffer* buffer = CSmsBuffer::NewL(); |
|
2508 CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer); |
|
2509 CleanupStack::PushL(smsMessage); |
|
2510 |
|
2511 CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity); |
|
2512 CleanupStack::PushL(indexArray); |
|
2513 CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity); |
|
2514 CleanupStack::PushL(smsArray); |
|
2515 |
|
2516 //Internalize stored message in permanent store file |
|
2517 TReassemblyEntry entry; |
|
2518 CReassemblyStoreUtility::PopulateEntry(entry, aSmsMessage, 1); |
|
2519 TInt permanentStoreIndex; |
|
2520 iPermanentFileStore->MatchEntryToExistingMessage(entry, permanentStoreIndex); |
|
2521 if (permanentStoreIndex!=KErrNotFound) |
|
2522 { |
|
2523 iPermanentFileStore->InternalizeEntryL(permanentStoreIndex, *smsMessage, *indexArray, *smsArray); |
|
2524 } |
|
2525 |
|
2526 //Internalize stored message in pre-allocated file |
|
2527 TInt preAllocatedFileIndex; |
|
2528 iPreallocatedFile->MatchEntryToExistingMessage(entry, preAllocatedFileIndex); |
|
2529 if (preAllocatedFileIndex!=KErrNotFound) |
|
2530 { |
|
2531 iPreallocatedFile->InternalizeEntryL(preAllocatedFileIndex, *smsMessage, *indexArray, *smsArray); |
|
2532 } |
|
2533 else |
|
2534 { |
|
2535 //This condition should never arise |
|
2536 User::Leave(KErrNotFound); |
|
2537 } |
|
2538 |
|
2539 // |
|
2540 // Check if this is a duplicated enumerated PDU (e.g. on the SIM or phone memory) |
|
2541 // or a duplicated PDU (e.g. in the Reassembly Store)... |
|
2542 // |
|
2543 TInt concatPDUIndex = aSmsMessage.SmsPDU().ConcatenatedMessagePDUIndex(); |
|
2544 |
|
2545 if (smsMessage->Storage() == CSmsMessage::ESmsSIMStorage || |
|
2546 smsMessage->Storage() == CSmsMessage::ESmsCombinedStorage) |
|
2547 { |
|
2548 // |
|
2549 // In most cases this PDU is being enumerated, but not always. It is |
|
2550 // possible for the PDU to be stored on the SIM first before it is |
|
2551 // received. |
|
2552 // |
|
2553 const TGsmSmsSlotEntry& newSlot = aSmsMessage.iSlotArray[0]; |
|
2554 TInt slotArrayCount = smsMessage->iSlotArray.Count(); |
|
2555 |
|
2556 for (TInt slotNum = 0; slotNum < slotArrayCount; slotNum++ ) |
|
2557 { |
|
2558 const TGsmSmsSlotEntry& slot = smsMessage->iSlotArray[slotNum]; |
|
2559 |
|
2560 if (slot.iIndex == newSlot.iIndex && slot.iStore == newSlot.iStore) |
|
2561 { |
|
2562 LOGSMSPROT1("CSmsReassemblyStore::UpdateExistingMessageL(): Duplicate enumerated PDU."); |
|
2563 |
|
2564 // It is a duplicate that was already stored on the SIM... |
|
2565 aDuplicateSlot = ETrue; |
|
2566 break; |
|
2567 } |
|
2568 } |
|
2569 } |
|
2570 |
|
2571 TInt indexArrayCount = indexArray->Count(); |
|
2572 |
|
2573 for (TInt index = 0; index < indexArrayCount; index++ ) |
|
2574 { |
|
2575 if (indexArray->At(index) == concatPDUIndex) |
|
2576 { |
|
2577 LOGSMSPROT1("CSmsReassemblyStore::UpdateExistingMessageL(): Duplicate concatenated PDU."); |
|
2578 |
|
2579 // The PDU is already stored in the reassembly store. |
|
2580 aDuplicateMsgRef = ETrue; |
|
2581 break; |
|
2582 } |
|
2583 } |
|
2584 |
|
2585 //Check whether this PDU is part of forwarded PDU. |
|
2586 TSmsPreAllocatedFileStoreReassemblyEntry preAllocatedFileEntry = iPreallocatedFile->Entries()[preAllocatedFileIndex]; |
|
2587 if (preAllocatedFileEntry.NumberOfPDUsForwardToClient() > 0) |
|
2588 { |
|
2589 TUint8 bitMapIndex = (concatPDUIndex-1)/8; |
|
2590 TUint8 bitPos = (concatPDUIndex-1)%8; |
|
2591 TUint8 bitMap; |
|
2592 preAllocatedFileEntry.GetBitMap(bitMapIndex, bitMap); |
|
2593 TUint8 tmpBitMap = 1; |
|
2594 tmpBitMap <<= bitPos; |
|
2595 if (tmpBitMap == (bitMap & tmpBitMap)) |
|
2596 { |
|
2597 aDuplicateMsgRef = ETrue; |
|
2598 } |
|
2599 } |
|
2600 |
|
2601 if (aDuplicateMsgRef || aDuplicateSlot) |
|
2602 { |
|
2603 CleanupStack::PopAndDestroy(3, smsMessage); // smsMessage, smsArray, indexArray |
|
2604 return; |
|
2605 } |
|
2606 |
|
2607 // |
|
2608 // If the PDU is stored then add the slot information... |
|
2609 // |
|
2610 if (aSmsMessage.Storage() == CSmsMessage::ESmsSIMStorage || |
|
2611 aSmsMessage.Storage() == CSmsMessage::ESmsCombinedStorage) |
|
2612 { |
|
2613 smsMessage->AddSlotL(aSmsMessage.iSlotArray[0]); |
|
2614 } |
|
2615 |
|
2616 // |
|
2617 // If the PDU is Unsent or Unread, then store that information... |
|
2618 // |
|
2619 NMobileSmsStore::TMobileSmsStoreStatus status = aSmsMessage.Status(); |
|
2620 |
|
2621 if (status == NMobileSmsStore::EStoredMessageUnsent || |
|
2622 status == NMobileSmsStore::EStoredMessageUnread) |
|
2623 { |
|
2624 smsMessage->SetStatus(status); |
|
2625 } |
|
2626 |
|
2627 /* |
|
2628 Below logic is written in keeping view of different scenarios that might occur here: |
|
2629 (1) Previous PDUs are in Permanent store file, this PDU arrives in out-of-disk condition (so will be stored in Pre-allocated file). |
|
2630 (2) Previous PDUs are in Pre-allocated file (means PDU arrives in out-of-disk condition), this PDU arrives in normal condition. |
|
2631 (3) Previous PDUs are in Permanent store file, this PDU also arrives in normal condition. |
|
2632 (4) Previous PDUs are in Pre-allocated file (means PDU arrives in out-of-disk condition), this PDU also arrives in out-of-disk condition. |
|
2633 */ |
|
2634 |
|
2635 //Always first try to store the message in permanent store file. |
|
2636 //In case of out-of-disk condition store the message in pre-allocated file |
|
2637 TInt ret = KErrNone; |
|
2638 if (iDiskSpaceStatus == ESmsDiskSpaceFull) |
|
2639 { |
|
2640 ret = KErrDiskFull; |
|
2641 } |
|
2642 else |
|
2643 { |
|
2644 if (permanentStoreIndex==KErrNotFound) |
|
2645 { |
|
2646 // See condition (2) |
|
2647 TInt tmpIndex; |
|
2648 TRAP(ret, iPermanentFileStore->AddNewMessageL(tmpIndex, aSmsMessage, aGsmSms)); |
|
2649 } |
|
2650 else |
|
2651 { |
|
2652 CSmsBuffer* tmpBuffer = CSmsBuffer::NewL(); |
|
2653 CSmsMessage* tmpSmsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, tmpBuffer); |
|
2654 CleanupStack::PushL(tmpSmsMessage); |
|
2655 |
|
2656 indexArray->Reset(); |
|
2657 smsArray->Reset(); |
|
2658 iPermanentFileStore->InternalizeEntryL(permanentStoreIndex, *tmpSmsMessage, *indexArray, *smsArray); |
|
2659 /* |
|
2660 Check & remove those PDU from permanent store file which has already been |
|
2661 forwarded to client. Forwarded PDU might still remain in permanent store |
|
2662 file if it is deleted at the time of out-of-disk condition. |
|
2663 */ |
|
2664 if (preAllocatedFileEntry.NumberOfPDUsForwardToClient()>0) |
|
2665 { |
|
2666 for (TInt j=indexArray->Count(); j>0 ;j--) |
|
2667 { |
|
2668 TUint8 bitMapIndex = (indexArray->At(j-1)-1)/8; |
|
2669 TUint8 bitPos = (indexArray->At(j-1)-1)%8; |
|
2670 TUint8 bitMap; |
|
2671 preAllocatedFileEntry.GetBitMap(bitMapIndex, bitMap); |
|
2672 TUint8 tmpBitMap = 1; |
|
2673 tmpBitMap <<= bitPos; |
|
2674 if (tmpBitMap == (bitMap & tmpBitMap)) |
|
2675 { |
|
2676 indexArray->Delete(j-1); |
|
2677 smsArray->Delete(j-1); |
|
2678 } |
|
2679 } |
|
2680 } |
|
2681 |
|
2682 indexArray->AppendL(concatPDUIndex); |
|
2683 smsArray->AppendL(aGsmSms); |
|
2684 |
|
2685 TRAP(ret, iPermanentFileStore->UpdateExistingMessageL(permanentStoreIndex, *smsMessage, *indexArray, *smsArray)); |
|
2686 |
|
2687 CleanupStack::PopAndDestroy(1); //tmpSmsMessage |
|
2688 } |
|
2689 } |
|
2690 |
|
2691 if (ret == KErrDiskFull) |
|
2692 { |
|
2693 iPreallocatedFile->UpdateExistingMessageL(preAllocatedFileIndex, aSmsMessage, concatPDUIndex, aGsmSms); |
|
2694 } |
|
2695 else if (ret!=KErrNone) |
|
2696 { |
|
2697 User::Leave(ret); |
|
2698 } |
|
2699 |
|
2700 CleanupStack::PopAndDestroy(3, smsMessage); // smsMessage, indexArray, smsArray |
|
2701 } |
|
2702 |
|
2703 /* |
|
2704 It retrieves class 0 message from re-assembly store. |
|
2705 The message which match the passed entry information is returned from this function. |
|
2706 |
|
2707 @param aEntry reference to entry information. |
|
2708 @param aSmsMessage reference to returned sms message. |
|
2709 |
|
2710 @internalComponent |
|
2711 */ |
|
2712 void CClass0SmsReassemblyStore::RetrieveMessageL(const TReassemblyEntry& aEntry, CSmsMessage& aSmsMessage) |
|
2713 { |
|
2714 CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity); |
|
2715 CleanupStack::PushL(indexArray); |
|
2716 CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity); |
|
2717 CleanupStack::PushL(smsArray); |
|
2718 |
|
2719 GetSmsEntriesL(aEntry, aSmsMessage, *indexArray, *smsArray); |
|
2720 |
|
2721 //There is no need to decode a single segment message |
|
2722 if (aEntry.Total()>1) |
|
2723 { |
|
2724 if (smsArray->Count() == aEntry.Total()) |
|
2725 { |
|
2726 aSmsMessage.DecodeMessagePDUsL(*smsArray); |
|
2727 } |
|
2728 } |
|
2729 CleanupStack::PopAndDestroy(2, indexArray); //smsArray, indexArray |
|
2730 } |
|
2731 |
|
2732 /* |
|
2733 It deletes the entry from re-assembly store. |
|
2734 |
|
2735 @param aEntry reference to entry information. |
|
2736 |
|
2737 @internalComponent |
|
2738 */ |
|
2739 void CClass0SmsReassemblyStore::DeleteEntryL(const TReassemblyEntry& aEntry) |
|
2740 { |
|
2741 TInt index; |
|
2742 iPreallocatedFile->MatchEntryToExistingMessage(aEntry, index); |
|
2743 if (index == KErrNotFound) |
|
2744 { |
|
2745 //This condition should never arise |
|
2746 User::Leave(KErrNotFound); |
|
2747 } |
|
2748 iPreallocatedFile->DeleteEntryL(index); |
|
2749 iPermanentFileStore->MatchEntryToExistingMessage(aEntry, index); |
|
2750 if (index != KErrNotFound) |
|
2751 { |
|
2752 TRAP_IGNORE(iPermanentFileStore->DeleteEntryL(index)); |
|
2753 } |
|
2754 } |
|
2755 |
|
2756 /* |
|
2757 It updates the log server id of the passed entry (message). |
|
2758 |
|
2759 @param aEntry reference to entry information. |
|
2760 @param aLogId log id of the message to be updated. |
|
2761 |
|
2762 @internalComponent |
|
2763 */ |
|
2764 void CClass0SmsReassemblyStore::UpdateLogServerIdL(const TReassemblyEntry& aEntry, TLogId aLogServerId) |
|
2765 { |
|
2766 TInt index; |
|
2767 iPreallocatedFile->MatchEntryToExistingMessage(aEntry, index); |
|
2768 if (index == KErrNotFound) |
|
2769 { |
|
2770 //This condition should never arise |
|
2771 User::Leave(KErrNotFound); |
|
2772 } |
|
2773 iPreallocatedFile->UpdateLogServerIdL(index, aLogServerId); |
|
2774 } |
|
2775 |
|
2776 /* |
|
2777 It sets the message passed to client or not. The message, which match the |
|
2778 passed entry information, its passed to client value is set. |
|
2779 |
|
2780 @param aEntry reference to entry information. |
|
2781 @param aBool boolean value indicating whether message is passed or not. |
|
2782 |
|
2783 @internalComponent |
|
2784 */ |
|
2785 void CClass0SmsReassemblyStore::SetPassedToClientL(const TReassemblyEntry& aEntry, TBool aBool) |
|
2786 { |
|
2787 TInt index; |
|
2788 iPreallocatedFile->MatchEntryToExistingMessage(aEntry, index); |
|
2789 if (index == KErrNotFound) |
|
2790 { |
|
2791 //This condition should never arise |
|
2792 User::Leave(KErrNotFound); |
|
2793 } |
|
2794 iPreallocatedFile->SetPassedToClientL(index, aBool); |
|
2795 } |
|
2796 |
|
2797 /** |
|
2798 It forwards the complete class 0 messages to client. |
|
2799 It checks whether the received object is complete or not. |
|
2800 If it is complete, then it forwards the complete message to client. |
|
2801 Otherwise it forms the message & forward the message to client. |
|
2802 In this it might be possible to forward multiple incomplete message. |
|
2803 |
|
2804 @param aSmsComm a reference to aSmsComm object which implemented the events. |
|
2805 |
|
2806 @param aSmsMessage a reference to sms message object. This sms message must be class 0 messages. |
|
2807 |
|
2808 @param aOriginalSmsAddr pointer to the address of the sender of a previously sent |
|
2809 |
|
2810 @param aOriginalSmsMessage pointer to a message previously sent matched to the received |
|
2811 one (e.g. status report). Null if not matched. |
|
2812 |
|
2813 @param aDes user data for the deliver report acknowledging this message to the SC. |
|
2814 Filled in by the observer. |
|
2815 |
|
2816 @internalComponent |
|
2817 */ |
|
2818 void CClass0SmsReassemblyStore::ForwardCompleteClass0SmsMessagesL(MSmsComm& aSmsComm, const CSmsMessage& aSmsMessage,const TSmsAddr* aOriginalSmsAddr,const CSmsMessage* aOriginalSmsMessage,TDes& aDes) |
|
2819 { |
|
2820 TBool passedToClient=ETrue; |
|
2821 |
|
2822 if (aSmsMessage.IsComplete()) |
|
2823 { |
|
2824 //Message is complete so forward it. |
|
2825 TInt ret = aSmsComm.ProcessMessageL(aSmsMessage, aOriginalSmsAddr, aOriginalSmsMessage, aDes); |
|
2826 if (ret!=KErrNone) |
|
2827 { |
|
2828 passedToClient = EFalse; |
|
2829 } |
|
2830 } |
|
2831 else |
|
2832 { |
|
2833 /* |
|
2834 Message is not complete, but re-assembly store contains other constituent PDU |
|
2835 of the message which makes the message complete. |
|
2836 |
|
2837 In case of class 0 messages, it is possible to forward the incomplete messages. So after forwarding |
|
2838 the incomplete message, if we receive other constituent PDU of that message then in that case we |
|
2839 might receive all the constituent PDU of that message but aSmsMesssage will contain partial complete message. |
|
2840 */ |
|
2841 TReassemblyEntry entry; |
|
2842 CReassemblyStoreUtility::PopulateEntry(entry, aSmsMessage, 1); |
|
2843 |
|
2844 CSmsBuffer* buffer = CSmsBuffer::NewL(); |
|
2845 CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer ); |
|
2846 CleanupStack::PushL( smsMessage ); |
|
2847 |
|
2848 CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity); |
|
2849 CleanupStack::PushL(indexArray); |
|
2850 CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity); |
|
2851 CleanupStack::PushL(smsArray); |
|
2852 |
|
2853 GetSmsEntriesL(entry, *smsMessage, *indexArray, *smsArray); |
|
2854 SortPDUsL(*indexArray, *smsArray); |
|
2855 |
|
2856 CArrayFixFlat<TGsmSms>* tmpSmsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity); |
|
2857 CleanupStack::PushL(tmpSmsArray); |
|
2858 |
|
2859 //Form the sequence of incomplete message & forward it to client. |
|
2860 TInt startSeqIndex(0), endSeqIndex(0); |
|
2861 TInt i; |
|
2862 do |
|
2863 { |
|
2864 i = startSeqIndex; |
|
2865 for (; i < indexArray->Count() - 1; i++) |
|
2866 { |
|
2867 if (indexArray->At(i) + 1 != indexArray->At(i+1)) |
|
2868 { |
|
2869 endSeqIndex = i; |
|
2870 break; |
|
2871 } |
|
2872 } |
|
2873 |
|
2874 if (i == (indexArray->Count() - 1)) |
|
2875 { |
|
2876 endSeqIndex = i; |
|
2877 } |
|
2878 |
|
2879 tmpSmsArray->Reset(); |
|
2880 for (TInt j = startSeqIndex; j <= endSeqIndex; j++) |
|
2881 { |
|
2882 tmpSmsArray->AppendL(smsArray->At(j)); |
|
2883 } |
|
2884 |
|
2885 if (tmpSmsArray->Count() == entry.Total()) |
|
2886 { |
|
2887 smsMessage->DecodeMessagePDUsL(*tmpSmsArray); |
|
2888 } |
|
2889 else |
|
2890 { |
|
2891 //Build the partial complete message. |
|
2892 if (endSeqIndex == (indexArray->Count() - 1)) |
|
2893 { |
|
2894 smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, ETrue); |
|
2895 } |
|
2896 else |
|
2897 { |
|
2898 smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, EFalse); |
|
2899 } |
|
2900 } |
|
2901 |
|
2902 //Forward the partial complete message to client. |
|
2903 TInt ret=KErrNone; |
|
2904 TRAP(ret, aSmsComm.ProcessMessageL(*smsMessage, aOriginalSmsAddr, aOriginalSmsMessage, aDes)); |
|
2905 if (ret != KErrNone) |
|
2906 { |
|
2907 passedToClient = EFalse; |
|
2908 } |
|
2909 startSeqIndex = endSeqIndex + 1; |
|
2910 endSeqIndex = startSeqIndex; |
|
2911 } |
|
2912 while (startSeqIndex < indexArray->Count()); |
|
2913 |
|
2914 CleanupStack::PopAndDestroy(4); //tmpSmsArray, indexArray, smsArray, smsMessage |
|
2915 } |
|
2916 |
|
2917 if(passedToClient) |
|
2918 { |
|
2919 SetMessagePassedToClientL(aSmsMessage); |
|
2920 } |
|
2921 |
|
2922 //If the latest segement exceeds the limitation, then we can't wait till ack. |
|
2923 //So call ProcessMessageIfExceedLimitationL() function & delete the oldest message. |
|
2924 if (IsExceedLimitation()) |
|
2925 { |
|
2926 ProcessMessageIfExceedLimitationL(aSmsComm); |
|
2927 } |
|
2928 } |
|
2929 |
|
2930 /** |
|
2931 It frees the space by forwarding the class 0 message if class 0 re-assembly store |
|
2932 exceeds limitation (max class 0 message, max reserved pdu segment). |
|
2933 |
|
2934 @param aSmsComm a reference to aSmsComm object which implemented the events. |
|
2935 |
|
2936 @internalComponent |
|
2937 */ |
|
2938 void CClass0SmsReassemblyStore::ProcessMessageIfExceedLimitationL(MSmsComm& aSmsComm) |
|
2939 { |
|
2940 //Add Comment |
|
2941 TInt class0MsgCount = iEntryArray.Count(); |
|
2942 TInt noOfMsgStoredInPreAllocatedFile = iPreallocatedFile->NumberOfPDUStored(); |
|
2943 if ((class0MsgCount > iMaxClass0Msg) |
|
2944 || (noOfMsgStoredInPreAllocatedFile >= iMaxPDUSeg)) |
|
2945 { |
|
2946 CSmsBuffer* buffer = CSmsBuffer::NewL(); |
|
2947 CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer ); |
|
2948 CleanupStack::PushL( smsMessage ); |
|
2949 |
|
2950 CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity); |
|
2951 CleanupStack::PushL(indexArray); |
|
2952 CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity); |
|
2953 CleanupStack::PushL(smsArray); |
|
2954 |
|
2955 //Add Comment |
|
2956 TInt index; |
|
2957 if (class0MsgCount > iMaxClass0Msg) |
|
2958 { |
|
2959 index = GetIndexOfOldestMessage(); |
|
2960 } |
|
2961 else |
|
2962 { |
|
2963 index = GetIndexOfOldestMessageFromReservedFileL(); |
|
2964 } |
|
2965 |
|
2966 TReassemblyEntry entry = iEntryArray[index]; |
|
2967 |
|
2968 GetSmsEntriesL(entry, *smsMessage, *indexArray, *smsArray); |
|
2969 |
|
2970 SortPDUsL(*indexArray, *smsArray); |
|
2971 |
|
2972 CArrayFixFlat<TGsmSms>* tmpSmsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity); |
|
2973 CleanupStack::PushL(tmpSmsArray); |
|
2974 |
|
2975 //Form the message & forward it to client. |
|
2976 TInt startSeqIndex(0), endSeqIndex(0); |
|
2977 TInt i; |
|
2978 do |
|
2979 { |
|
2980 i = startSeqIndex; |
|
2981 for (; i < indexArray->Count() - 1; i++) |
|
2982 { |
|
2983 if (indexArray->At(i) + 1 != indexArray->At(i+1)) |
|
2984 { |
|
2985 endSeqIndex = i; |
|
2986 break; |
|
2987 } |
|
2988 } |
|
2989 if (i == (indexArray->Count() - 1)) |
|
2990 { |
|
2991 endSeqIndex = i; |
|
2992 } |
|
2993 tmpSmsArray->Reset(); |
|
2994 |
|
2995 for (TInt j = startSeqIndex; j <= endSeqIndex; j++) |
|
2996 { |
|
2997 tmpSmsArray->AppendL(smsArray->At(j)); |
|
2998 } |
|
2999 |
|
3000 if (entry.IsComplete()) |
|
3001 { |
|
3002 if (tmpSmsArray->Count() == entry.Total()) |
|
3003 { |
|
3004 smsMessage->DecodeMessagePDUsL(*tmpSmsArray); |
|
3005 } |
|
3006 else |
|
3007 { |
|
3008 //Build the partial complete message. |
|
3009 if (endSeqIndex == (indexArray->Count() - 1)) |
|
3010 { |
|
3011 smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, ETrue); |
|
3012 } |
|
3013 else |
|
3014 { |
|
3015 smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, EFalse); |
|
3016 } |
|
3017 } |
|
3018 } |
|
3019 else |
|
3020 { |
|
3021 //Build the partial complete message. |
|
3022 smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, EFalse); |
|
3023 } |
|
3024 //Forward the partial complete message to client. |
|
3025 TBuf16<CSmsPDUProcessor::ESmsMaxDeliverReportBufferSize> buffer; |
|
3026 TRAP_IGNORE(aSmsComm.ProcessMessageL(*smsMessage, NULL, NULL, buffer)); |
|
3027 |
|
3028 /* |
|
3029 Can't do much. So free the reserved space & also stored the information |
|
3030 related to forwarded message. If the message is complete then delete |
|
3031 the complete message (see the condition after the while loop)rather |
|
3032 than freeing the memory. No need to store the complete messages forwaded |
|
3033 info. |
|
3034 */ |
|
3035 if ((noOfMsgStoredInPreAllocatedFile > iMaxPDUSeg) && (!entry.IsComplete())) |
|
3036 { |
|
3037 SetIncompleteMessageForwardedToClientL(*smsMessage); |
|
3038 } |
|
3039 startSeqIndex = endSeqIndex + 1; |
|
3040 endSeqIndex = startSeqIndex; |
|
3041 } |
|
3042 while (startSeqIndex < indexArray->Count()); |
|
3043 //Can't do much. So removed the oldest message. |
|
3044 if ((class0MsgCount > iMaxClass0Msg) || |
|
3045 ((noOfMsgStoredInPreAllocatedFile > iMaxPDUSeg) && (entry.IsComplete()))) |
|
3046 { |
|
3047 DeleteMessageL(*smsMessage, EFalse); |
|
3048 } |
|
3049 CleanupStack::PopAndDestroy(4); //tmpSmsArray, indexArray, smsArray, smsMessage |
|
3050 } |
|
3051 } |
|
3052 |
|
3053 /** |
|
3054 Guard timer calls this function when timer expires. |
|
3055 It goes through all the messages stored in re-assembly store & forwards those message |
|
3056 whose time has expired. |
|
3057 It is also called when a new observer is added or a PDU has been received and successfully |
|
3058 processed. It is also called from ProcessCompleteClass0SmsMessagesL. |
|
3059 |
|
3060 @internalComponent |
|
3061 */ |
|
3062 void CClass0SmsReassemblyStore::ProcessTimeoutMessageL() |
|
3063 { |
|
3064 LOGSMSPROT1("CClass0SmsReassemblyStore::ProcessTimeoutMessageL()"); |
|
3065 TBool passedToClient=ETrue; |
|
3066 TInt count=iEntryArray.Count(); |
|
3067 |
|
3068 CSmsBuffer* buffer = CSmsBuffer::NewL(); |
|
3069 CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer ); |
|
3070 CleanupStack::PushL( smsMessage ); |
|
3071 |
|
3072 CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity); |
|
3073 CleanupStack::PushL(indexArray); |
|
3074 CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity); |
|
3075 CleanupStack::PushL(smsArray); |
|
3076 |
|
3077 CArrayFixFlat<TGsmSms>* tmpSmsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity); |
|
3078 CleanupStack::PushL(tmpSmsArray); |
|
3079 |
|
3080 TTime time; |
|
3081 time.UniversalTime(); |
|
3082 |
|
3083 TTimeIntervalSeconds timeOutInSecs = iGuardTimeOut*3600; |
|
3084 |
|
3085 for (TInt k=count-1; k>=0; k--) |
|
3086 { |
|
3087 if (!iEntryArray[k].PassedToClient()) |
|
3088 { |
|
3089 TTimeIntervalSeconds diffInSecs; |
|
3090 time.SecondsFrom(iEntryArray[k].Time(), diffInSecs); |
|
3091 indexArray->Reset(); |
|
3092 smsArray->Reset(); |
|
3093 if (diffInSecs >= timeOutInSecs) |
|
3094 { |
|
3095 GetSmsEntriesL(iEntryArray[k], *smsMessage, *indexArray, *smsArray); |
|
3096 SortPDUsL(*indexArray, *smsArray); |
|
3097 |
|
3098 //Form the message & forward it to client. |
|
3099 TInt startSeqIndex(0), endSeqIndex(0); |
|
3100 TInt i; |
|
3101 do |
|
3102 { |
|
3103 i = startSeqIndex; |
|
3104 for (; i < indexArray->Count() - 1; i++) |
|
3105 { |
|
3106 if (indexArray->At(i) + 1 != indexArray->At(i+1)) |
|
3107 { |
|
3108 endSeqIndex = i; |
|
3109 break; |
|
3110 } |
|
3111 } |
|
3112 if (i == (indexArray->Count() - 1)) |
|
3113 { |
|
3114 endSeqIndex = i; |
|
3115 } |
|
3116 tmpSmsArray->Reset(); |
|
3117 for (TInt j = startSeqIndex; j <= endSeqIndex; j++) |
|
3118 { |
|
3119 tmpSmsArray->AppendL(smsArray->At(j)); |
|
3120 } |
|
3121 |
|
3122 if (iEntryArray[k].IsComplete()) |
|
3123 { |
|
3124 if (tmpSmsArray->Count() == iEntryArray[k].Total()) |
|
3125 { |
|
3126 smsMessage->DecodeMessagePDUsL(*tmpSmsArray); |
|
3127 } |
|
3128 else |
|
3129 { |
|
3130 //Build the partial complete message. |
|
3131 if (endSeqIndex == (indexArray->Count() - 1)) |
|
3132 { |
|
3133 smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, ETrue); |
|
3134 } |
|
3135 else |
|
3136 { |
|
3137 smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, EFalse); |
|
3138 } |
|
3139 } |
|
3140 } |
|
3141 else |
|
3142 { |
|
3143 //Build the partial complete message. |
|
3144 if (endSeqIndex == (indexArray->Count() - 1)) |
|
3145 { |
|
3146 smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, ETrue); |
|
3147 } |
|
3148 else |
|
3149 { |
|
3150 smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, EFalse); |
|
3151 } |
|
3152 } |
|
3153 |
|
3154 //Forward the partial complete message to client. |
|
3155 TInt ret=KErrNone; |
|
3156 TBuf16<CSmsPDUProcessor::ESmsMaxDeliverReportBufferSize> buffer; |
|
3157 ret = iSmsComm.ProcessMessageL(*smsMessage, NULL, NULL, buffer); |
|
3158 if (ret != KErrNone) |
|
3159 { |
|
3160 passedToClient = EFalse; |
|
3161 } |
|
3162 |
|
3163 startSeqIndex = endSeqIndex + 1; |
|
3164 endSeqIndex = startSeqIndex; |
|
3165 } |
|
3166 while (startSeqIndex < indexArray->Count()); |
|
3167 |
|
3168 if(passedToClient) |
|
3169 { |
|
3170 SetMessagePassedToClientL(*smsMessage); |
|
3171 } |
|
3172 } //diffInSecs >= timeOutInSecs |
|
3173 } //!iEntryArray[k].PassedToClient() |
|
3174 } //For k loop |
|
3175 CleanupStack::PopAndDestroy(4); //tmpSmsArray, indexArray, smsArray, smsMessage |
|
3176 } |
|
3177 |
|
3178 /** |
|
3179 It sets the bit-map of forwarded incomplete message to client. |
|
3180 It frees up the memory by removing the forwarded PDUs. |
|
3181 |
|
3182 @param aSmsMessage a reference to forwaded incomplete class 0 sms message object. |
|
3183 |
|
3184 @internalComponent |
|
3185 */ |
|
3186 void CClass0SmsReassemblyStore::SetIncompleteMessageForwardedToClientL(const CSmsMessage& aSmsMessage) |
|
3187 { |
|
3188 LOGSMSPROT1("CClass0SmsReassemblyStore::SetIncompleteMessageForwardedToClientL()"); |
|
3189 TInt index = KErrNotFound; |
|
3190 |
|
3191 if (aSmsMessage.IsComplete()) |
|
3192 { |
|
3193 LOGSMSPROT1("This function must be called when message is incomplete"); |
|
3194 User::Leave(KErrArgument); |
|
3195 } |
|
3196 |
|
3197 if (FindMessageL(aSmsMessage, EFalse, index)) |
|
3198 { |
|
3199 CIncompleteClass0MessageInfo& incompleteClass0MsgInfo = (CIncompleteClass0MessageInfo &) aSmsMessage.GetOperationsForNonIEL(ESmsIncompleteClass0MessageParameter); |
|
3200 // Retrieve incomplete class 0 message information & process |
|
3201 TInt startPos, endPos; |
|
3202 TBool isLastMessage; |
|
3203 incompleteClass0MsgInfo.GetIncompleteMessageInfoL(startPos, endPos, isLastMessage); |
|
3204 |
|
3205 const TReassemblyEntry& entry = iEntryArray[index]; |
|
3206 |
|
3207 //Remove the forwarded PDU entries from pre-allocated file |
|
3208 TInt preAllocatedFileIndex=KErrNotFound; |
|
3209 iPreallocatedFile->MatchEntryToExistingMessage(entry, preAllocatedFileIndex); |
|
3210 if (preAllocatedFileIndex!=KErrNotFound) |
|
3211 { |
|
3212 BeginTransactionLC(); |
|
3213 iPreallocatedFile->RemovePDUsL(preAllocatedFileIndex, startPos, endPos); |
|
3214 iPreallocatedFile->StoreForwardedPDUsInfoL(preAllocatedFileIndex, startPos, endPos); |
|
3215 CommitTransactionL(); |
|
3216 } |
|
3217 else |
|
3218 { |
|
3219 //This situation should never arise |
|
3220 User::Leave(KErrNotFound); |
|
3221 } |
|
3222 |
|
3223 //Remove the forwarded PDU entries from permanent store file |
|
3224 TInt permanentStoreIndex=KErrNotFound; |
|
3225 iPermanentFileStore->MatchEntryToExistingMessage(entry, permanentStoreIndex); |
|
3226 if (permanentStoreIndex!=KErrNotFound) |
|
3227 { |
|
3228 TRAP_IGNORE(BeginTransactionLC(); |
|
3229 iPermanentFileStore->RemovePDUsL(permanentStoreIndex, startPos, endPos); |
|
3230 CommitTransactionL();); |
|
3231 } |
|
3232 } |
|
3233 } |
|
3234 |
|
3235 /** |
|
3236 This function is needed to ensure that permanent file |
|
3237 clean itself with pre-allocated file. |
|
3238 There migth be a scenario where user has deleted a message |
|
3239 but the corresponding message has not been deleted from permanent store file |
|
3240 due to out-of-disk condition. But the entry is invalid because |
|
3241 it is no more in the pre-allocated file which contains master header info. |
|
3242 |
|
3243 @return the error code. |
|
3244 |
|
3245 @internalComponent |
|
3246 */ |
|
3247 TInt CClass0SmsReassemblyStore::CleanReassemblyEntries() |
|
3248 { |
|
3249 LOGSMSPROT1("CleanReassemblyEntries"); |
|
3250 const CArrayFix<TSmsPreAllocatedFileStoreReassemblyEntry>& preAllocatedFileEntryArray = iPreallocatedFile->Entries(); |
|
3251 TInt ret=KErrNone; |
|
3252 TRAP(ret, BeginTransactionLC(); |
|
3253 iPermanentFileStore->CleanupEntriesL(preAllocatedFileEntryArray); |
|
3254 CommitTransactionL();); |
|
3255 |
|
3256 if (ret == KErrDiskFull) |
|
3257 { |
|
3258 LOGSMSPROT1("CleanupEntriesL returns KErrDiskFull"); |
|
3259 /* |
|
3260 Get access to reserve memory, call again to clean the entries with compact. |
|
3261 Compact needs to be called at this instance because permanent store |
|
3262 will use reserve disk space to delete, but after deletion reserve |
|
3263 disk space will be freed. So compact will make sure that reserve disk |
|
3264 space is not used after compaction. |
|
3265 */ |
|
3266 iFs.GetReserveAccess(KStoreDrive); |
|
3267 TRAP(ret, BeginTransactionLC(); |
|
3268 iPermanentFileStore->CleanupEntriesWithCompactL(preAllocatedFileEntryArray); |
|
3269 CommitTransactionL();); |
|
3270 LOGSMSPROT2("CleanupEntriesWithCompactL returns %d", ret); |
|
3271 iFs.ReleaseReserveAccess(KStoreDrive); |
|
3272 } |
|
3273 return ret; |
|
3274 } |
|
3275 |
|
3276 /** |
|
3277 It returns the SMS entries (sms messages, sms pdu arrays & the corresponding index array) |
|
3278 from its permanent store & pre-allocated file. |
|
3279 |
|
3280 @param aEntry reference to entry information. The message which match this entry information |
|
3281 is returned to caller of the function. |
|
3282 @param aSmsMessage a reference to class 0 sms message object. |
|
3283 @param aIndexArray a reference to the array of pdu index. |
|
3284 @param aSmsArray a reference to the array of pdu. |
|
3285 |
|
3286 @internalComponent |
|
3287 */ |
|
3288 void CClass0SmsReassemblyStore::GetSmsEntriesL(const TReassemblyEntry& aEntry, CSmsMessage& aSmsMessage, CArrayFix<TInt>& aIndexArray, CArrayFix<TGsmSms>& aSmsArray) |
|
3289 { |
|
3290 LOGSMSPROT1("CClass0SmsReassemblyStore::GetSmsEntriesL()"); |
|
3291 TInt permanentStoreIndex=KErrNotFound; |
|
3292 iPermanentFileStore->MatchEntryToExistingMessage(aEntry, permanentStoreIndex); |
|
3293 if (permanentStoreIndex!=KErrNotFound) |
|
3294 { |
|
3295 iPermanentFileStore->InternalizeEntryL(permanentStoreIndex, aSmsMessage, aIndexArray, aSmsArray); |
|
3296 } |
|
3297 else |
|
3298 { |
|
3299 LOGSMSPROT1("No PDUs in Permanent store file"); |
|
3300 } |
|
3301 |
|
3302 TInt preAllocatedFileIndex=KErrNotFound; |
|
3303 iPreallocatedFile->MatchEntryToExistingMessage(aEntry, preAllocatedFileIndex); |
|
3304 if (preAllocatedFileIndex!=KErrNotFound) |
|
3305 { |
|
3306 iPreallocatedFile->InternalizeEntryL(preAllocatedFileIndex, aSmsMessage, aIndexArray, aSmsArray); |
|
3307 |
|
3308 //Filter forwarde PDU here..this condition might arise if the PDU |
|
3309 //could not be deleted at the time of OOD condition from permanent store file. |
|
3310 TSmsPreAllocatedFileStoreReassemblyEntry preAllocatedFileEntry = iPreallocatedFile->Entries()[preAllocatedFileIndex]; |
|
3311 if (preAllocatedFileEntry.NumberOfPDUsForwardToClient() > 0) |
|
3312 { |
|
3313 for (TInt j=aIndexArray.Count(); j>0 ;j--) |
|
3314 { |
|
3315 TUint8 bitMapIndex = (aIndexArray.At(j-1)-1)/8; |
|
3316 TUint8 bitPos = (aIndexArray.At(j-1)-1)%8; |
|
3317 TUint8 bitMap; |
|
3318 preAllocatedFileEntry.GetBitMap(bitMapIndex, bitMap); |
|
3319 TUint8 tmpBitMap = 1; |
|
3320 tmpBitMap <<= bitPos; |
|
3321 if (tmpBitMap == (bitMap & tmpBitMap)) |
|
3322 { |
|
3323 aIndexArray.Delete(j-1); |
|
3324 aSmsArray.Delete(j-1); |
|
3325 } |
|
3326 } |
|
3327 } |
|
3328 |
|
3329 if (permanentStoreIndex==KErrNotFound) |
|
3330 { |
|
3331 //In this scenario a CSmsMessage object has to be created from the existing PDU in |
|
3332 //pre-allocated file & then serialized into aSmsMessage. |
|
3333 LOGSMSPROT2("Number of PDUs in Pre-allocated file %d", aIndexArray.Count()); |
|
3334 if (aIndexArray.Count() > 0) |
|
3335 { |
|
3336 CSmsBuffer* smsBuffer = CSmsBuffer::NewL(); |
|
3337 CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, aSmsArray.At(0), smsBuffer, EFalse, ETrue); |
|
3338 CleanupStack::PushL(smsMessage); |
|
3339 |
|
3340 //Update sms messages's properties. |
|
3341 smsMessage->SetStorage(aSmsMessage.Storage()); |
|
3342 smsMessage->SetStatus((NMobileSmsStore::TMobileSmsStoreStatus)aSmsMessage.Status()); |
|
3343 smsMessage->SetLogServerId(aSmsMessage.LogServerId()); |
|
3344 smsMessage->SetTime(aSmsMessage.Time()); |
|
3345 smsMessage->SetUTCOffset(aSmsMessage.UTCOffset()); |
|
3346 smsMessage->SetDecodedOnSIM(aSmsMessage.DecodedOnSim()); |
|
3347 smsMessage->SetForwardToClient(aSmsMessage.ForwardToClient()); |
|
3348 smsMessage->SetToFromAddressL(aSmsMessage.ToFromAddress()); |
|
3349 |
|
3350 CBufSeg* recvbufseg = CBufSeg::NewL(KSmsMaxSegmentLength); |
|
3351 CleanupStack::PushL(recvbufseg); |
|
3352 // Attempt to serialize this message into the buffer |
|
3353 RBufWriteStream writestream(*recvbufseg); |
|
3354 writestream.Open(*recvbufseg); |
|
3355 CleanupClosePushL(writestream); |
|
3356 writestream << *smsMessage; |
|
3357 |
|
3358 // Initialize the read stream with the buffer |
|
3359 RBufReadStream readstream(*recvbufseg); |
|
3360 readstream.Open(*recvbufseg,0); |
|
3361 CleanupClosePushL(readstream); |
|
3362 // De-serialize the message from using the read stream |
|
3363 readstream >> aSmsMessage; |
|
3364 CleanupStack::PopAndDestroy(4); //readstream, writestream, recvbufseg, smsMessage |
|
3365 } |
|
3366 } |
|
3367 } |
|
3368 } |
|
3369 |
|
3370 /* |
|
3371 It returns when the next timeout should occur. |
|
3372 */ |
|
3373 void CClass0SmsReassemblyStore::GetNextGuardTimeout(TTime& aNextTimeout) |
|
3374 { |
|
3375 TTime curTime; |
|
3376 curTime.UniversalTime(); |
|
3377 TTimeIntervalSeconds timeOutInSecs = iGuardTimeOut*3600; |
|
3378 aNextTimeout = curTime + timeOutInSecs; |
|
3379 |
|
3380 TInt class0ReassemblyStoreCount = iEntryArray.Count(); |
|
3381 |
|
3382 if (class0ReassemblyStoreCount > 0) |
|
3383 { |
|
3384 for (TInt i=0; i<class0ReassemblyStoreCount;i++) |
|
3385 { |
|
3386 TTime guradTimeout = iEntryArray[i].Time() + timeOutInSecs; |
|
3387 if ((guradTimeout > curTime) && |
|
3388 (guradTimeout < aNextTimeout)) |
|
3389 { |
|
3390 aNextTimeout = guradTimeout; |
|
3391 } |
|
3392 } |
|
3393 } |
|
3394 } |
|
3395 |
|
3396 /* |
|
3397 It returns the index of oldest message in class 0 re-assembly store. |
|
3398 */ |
|
3399 TInt CClass0SmsReassemblyStore::GetIndexOfOldestMessage() |
|
3400 { |
|
3401 TInt index = 0; |
|
3402 TTime time = iEntryArray[index].Time(); |
|
3403 for (TInt index2=1; index2 < iEntryArray.Count(); index2++) |
|
3404 { |
|
3405 if (iEntryArray[index2].Time() < time) |
|
3406 { |
|
3407 index = index2; |
|
3408 } |
|
3409 } |
|
3410 return index; |
|
3411 } |
|
3412 |
|
3413 /* |
|
3414 It returns the index of oldest message in class 0 re-assembly store. |
|
3415 */ |
|
3416 TInt CClass0SmsReassemblyStore::GetIndexOfOldestMessageFromReservedFileL() |
|
3417 { |
|
3418 TInt index = KErrNotFound; |
|
3419 //Find the index of oldest message in pre-allocated file. |
|
3420 index = iPreallocatedFile->GetOldestMessageEntryIndex(); |
|
3421 if (index == KErrNotFound) |
|
3422 { |
|
3423 //This condition should never arise |
|
3424 User::Leave(KErrNotFound); |
|
3425 } |
|
3426 |
|
3427 //Compare the oldest pre-allocated message entry against class 0 reassembly store entry |
|
3428 //and return the index of class 0 reassembly store entry. |
|
3429 const TSmsPreAllocatedFileStoreReassemblyEntry& preAllocatedFileEntry = iPreallocatedFile->Entries()[index]; |
|
3430 |
|
3431 TInt reassemblyCount = iEntryArray.Count(); |
|
3432 TInt count; |
|
3433 for (count = 0; count < reassemblyCount; count++) |
|
3434 { |
|
3435 TReassemblyEntry& entry = iEntryArray[count]; |
|
3436 |
|
3437 if (entry.Reference() == preAllocatedFileEntry.Reference() && |
|
3438 entry.Total() == preAllocatedFileEntry.Total() && |
|
3439 entry.PduType() == preAllocatedFileEntry.PduType() && |
|
3440 entry.Storage() == preAllocatedFileEntry.Storage() && |
|
3441 entry.Description2() == preAllocatedFileEntry.Description2()) |
|
3442 { |
|
3443 // |
|
3444 // Found it! |
|
3445 // |
|
3446 index = count; |
|
3447 break; |
|
3448 } |
|
3449 } |
|
3450 if (count == reassemblyCount) |
|
3451 { |
|
3452 //This condition should never arise |
|
3453 User::Leave(KErrNotFound); |
|
3454 } |
|
3455 return index; |
|
3456 } |
|
3457 |
|
3458 /* |
|
3459 It returns a boolean value indicating whether the limitation (max class 0 message, |
|
3460 max pdu stored in pre-allocated file) imposed on class 0 reassembly store exceeds or not. |
|
3461 */ |
|
3462 TBool CClass0SmsReassemblyStore::IsExceedLimitation() |
|
3463 { |
|
3464 TInt class0MsgCount = iEntryArray.Count(); |
|
3465 TInt noOfMsgStoredInPreAllocatedFile = iPreallocatedFile->NumberOfPDUStored(); |
|
3466 if ((class0MsgCount > iMaxClass0Msg) |
|
3467 || (noOfMsgStoredInPreAllocatedFile > iMaxPDUSeg)) |
|
3468 { |
|
3469 return ETrue; |
|
3470 } |
|
3471 |
|
3472 return EFalse; |
|
3473 } |
|
3474 |
|
3475 /* |
|
3476 This sorting algorithm is based on bubble sort |
|
3477 */ |
|
3478 void CClass0SmsReassemblyStore::SortPDUsL(CArrayFix<TInt>& aIndexArray, CArrayFix<TGsmSms>& aSmsArray) |
|
3479 { |
|
3480 //Test---Index array count must be equal to sms array count |
|
3481 TBool swapped; |
|
3482 |
|
3483 do |
|
3484 { |
|
3485 swapped = EFalse; |
|
3486 for (TInt i=0; i<aIndexArray.Count()-1 ;i++) |
|
3487 { |
|
3488 if (aIndexArray[i] > aIndexArray[i+1]) |
|
3489 { |
|
3490 aSmsArray.InsertL(i, aSmsArray[i+1]); |
|
3491 aSmsArray.Delete(i+2); |
|
3492 aIndexArray.InsertL(i, aIndexArray[i+1]); |
|
3493 aIndexArray.Delete(i+2); |
|
3494 swapped = ETrue; |
|
3495 } |
|
3496 } |
|
3497 } |
|
3498 while (swapped); |
|
3499 } |
|
3500 |
|
3501 /** |
|
3502 * Utility func for cleanup stack |
|
3503 */ |
|
3504 void CClass0StoreCloseObject(TAny* aObj) |
|
3505 { |
|
3506 LOGGSMU2("WARNING! Hey, CClass0StoreCloseObject called by Untrapper! [0x%08x]", aObj); |
|
3507 ((CClass0SmsReassemblyStore*)aObj)->Revert(); |
|
3508 } |
|
3509 |
|
3510 /** |
|
3511 * Sets the class 0 re-assembly store as in-transaction. |
|
3512 * |
|
3513 * The function checks the validity of the call and leaves KErrAccessDenied if |
|
3514 * invalid. |
|
3515 * @capability None |
|
3516 */ |
|
3517 void CClass0SmsReassemblyStore::BeginTransactionLC() |
|
3518 { |
|
3519 LOGSMSPROT3("CClass0SmsReassemblyStore::BeginTransactionLC [this=0x%08X iInTransaction=%d]", this, iInTransaction); |
|
3520 |
|
3521 if (iInTransaction) |
|
3522 { |
|
3523 LOGGSMU1("WARNING CClass0SmsReassemblyStore::BeginTransactionLC leaving with KErrAccessDenied"); |
|
3524 User::Leave(KErrAccessDenied); |
|
3525 } |
|
3526 |
|
3527 TCleanupItem class0StoreClose(CClass0StoreCloseObject, this); |
|
3528 CleanupStack::PushL(class0StoreClose); |
|
3529 iPreallocatedFile->BeginTransactionL(); |
|
3530 iPermanentFileStore->BeginTransactionL(); |
|
3531 iInTransaction = ETrue; |
|
3532 } |
|
3533 |
|
3534 /** |
|
3535 * It commits the transaction. |
|
3536 */ |
|
3537 void CClass0SmsReassemblyStore::CommitTransactionL() |
|
3538 { |
|
3539 LOGSMSPROT3("CClass0SmsReassemblyStore::CommitTransactionL(): this=0x%08X iInTransaction=%d", |
|
3540 this, iInTransaction); |
|
3541 |
|
3542 //Commit permanent store file |
|
3543 iPermanentFileStore->CommitTransactionL(); |
|
3544 //Commit pre-allocated file |
|
3545 iPreallocatedFile->CommitTransactionL(); |
|
3546 CleanupStack::Pop(this); //CClass0StoreCloseObject |
|
3547 iInTransaction = EFalse; |
|
3548 } |
|
3549 |
|
3550 /** |
|
3551 * It reverts the transaction. |
|
3552 */ |
|
3553 void CClass0SmsReassemblyStore::Revert() |
|
3554 { |
|
3555 LOGSMSPROT3("CClass0SmsReassemblyStore::Revert(): this=0x%08X, iInTransaction=%d", |
|
3556 this, iInTransaction); |
|
3557 |
|
3558 iPreallocatedFile->Revert(); |
|
3559 iPermanentFileStore->Revert(); |
|
3560 iInTransaction = EFalse; |
|
3561 } |