--- a/smsprotocols/smsstack/smsprot/Src/smspclass0stor.cpp Mon May 03 13:37:20 2010 +0300
+++ b/smsprotocols/smsstack/smsprot/Src/smspclass0stor.cpp Thu May 06 15:10:38 2010 +0100
@@ -1,3561 +1,3561 @@
-// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
-// All rights reserved.
-// This component and the accompanying materials are made available
-// under the terms of "Eclipse Public License v1.0"
-// which accompanies this distribution, and is available
-// at the URL "http://www.eclipse.org/legal/epl-v10.html".
-//
-// Initial Contributors:
-// Nokia Corporation - initial contribution.
-//
-// Contributors:
-//
-// Description:
-// Implements CPreallocatedFile.
-//
-//
-
-/**
- @file
-*/
-#include "smspclass0stor.h"
-#include "gsmubuf.h"
-#include "gsmunonieoperations.h"
-
-const TInt KSizeOfPreallocatedFileVersion = sizeof(CPreallocatedFile::TPreAllocatedFileVersion);
-const TInt KSizeOfNumberOfEntrySection = sizeof(TInt);
-//size of 32-bit checksum
-const TInt KSizeOfChecksum = sizeof(TUint32);
-const TInt KSizeOfPreAllocatedStoreEntry = sizeof(TSmsPreAllocatedFileStoreReassemblyEntry);
-const TInt KSizeOfGsmSmsSlotEntry = sizeof(TGsmSmsSlotEntry);
-const TInt KSizeOfIndexEntry = sizeof(TInt);
-const TInt KSizeOfSmsGsmPDU = sizeof(RMobileSmsMessaging::TMobileSmsGsmTpdu);
-const TInt KSizeOfAContainer = KSizeOfGsmSmsSlotEntry + KSizeOfIndexEntry + KSizeOfSmsGsmPDU;
-const TInt KBeginOfMasterHeaderSection = KSizeOfPreallocatedFileVersion;
-
-/**
-Static factory constructor. Uses two phase
-construction and leaves nothing on the CleanupStack.
-
-@param aFs File Server handle.
-@param aFileName Permanent file store name.
-@param aThirdUid Uid of file.
-@leave KErrNoMemory
-
-@return A pointer to the newly created CSmsPermanentFileStore object.
-
-@pre A connected file server session must be passed as parameter.
-@post CSmsPermanentFileStore object is now fully initialised
-
-@internalComponent
-*/
-CSmsPermanentFileStore* CSmsPermanentFileStore::NewL(RFs& aFs, const TDesC& aFileName, const TUid& aThirdUid)
- {
- LOGSMSPROT1("CSmsPermanentFileStore::NewL()");
- CSmsPermanentFileStore* self = new (ELeave) CSmsPermanentFileStore(aFs, aThirdUid);
- CleanupStack::PushL(self);
- self->ConstructL(aFileName);
- CleanupStack::Pop(self);
-
- return self;
- }
-
-void CSmsPermanentFileStore::ConstructL(const TDesC& aFileName)
- {
- LOGSMSPROT1("CSmsPermanentFileStore::ConstructL()");
- iFileName = aFileName.AllocL();
- }
-
-/**
- * Constructor.
-*/
-CSmsPermanentFileStore::CSmsPermanentFileStore(RFs& aFs, const TUid& aThirdUid)
- : iFs(aFs), iFileName(NULL), iThirdUid(aThirdUid), iFileStore(NULL), iEntryArray(KFlatArrayGranularity)
- {
- }
-
-/**
- * Destructor. It destroys all the member variables.
-*/
-CSmsPermanentFileStore::~CSmsPermanentFileStore()
- {
- delete iFileName;
- }
-
-/**
-It checks & returns whether the file exist or not. If file is there whether
-it is corrupted or not.
-
-@internalComponent
-*/
-TBool CSmsPermanentFileStore::IsFileOK()
- {
- TBool retBool(EFalse);
- TUidType uidtype(KPermanentFileStoreLayoutUid,KSARStoreUid,iThirdUid);
- TEntry entry;
- TInt ret=iFs.Entry(iFileName->Des(), entry);
- // Check file existence & corruption
- if ((ret == KErrNone) && (entry.iType == uidtype))
- {
- retBool = ETrue;
- }
- return retBool;
- }
-
-/**
-It creates a permanent store file.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::CreateL()
- {
- LOGSMSPROT1("CSmsPermanentFileStore::CreateL()");
- TUidType uidtype(KPermanentFileStoreLayoutUid,KSARStoreUid,iThirdUid);
- iFileStore=CPermanentFileStore::ReplaceL(iFs, iFileName->Des(), EFileShareExclusive|EFileStream|EFileRead|EFileWrite);
- iFileStore->SetTypeL(uidtype);
- iEntryArray.Reset();
- ExternalizeEntryArrayL();
- iFileStore->CommitL();
- // Close it to make sure that file is created correctly (defensive approach).
- Close();
- //Again Open the file
- OpenL();
- }
-
-/**
-It opens the permanent store file and internalizes the entries.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::OpenL()
- {
- LOGSMSPROT1("CSmsPermanentFileStore::OpenL()");
- iFileStore=CPermanentFileStore::OpenL(iFs,iFileName->Des(),EFileShareExclusive|EFileStream|EFileRead|EFileWrite);
- InternalizeEntryArrayL();
- }
-
-/**
-It closes the permanent store file.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::Close()
- {
- LOGSMSPROT1("CSmsPermanentFileStore::Close()");
- delete iFileStore;
- iFileStore = NULL;
- iEntryArray.Reset();
- }
-
-/*
-This function cleans its entries against the passed entries.
-This is needed because there might be a scenario where user has deleted a message
-but the corresponding message is not deleted from permanent store file
-due to out-of-disk condition. But the entry is invalid because
-it is no more in the pre-allocated file which contains master header info.
-And also at the time of forwarding an incomplete message a forwarded
-message has not been deleted due to above reason.
-This function also compacts the store after deletion.
-
-@param aEntryArray entray array against whose clean up is carried out.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::CleanupEntriesWithCompactL(const CArrayFix<TSmsPreAllocatedFileStoreReassemblyEntry>& aEntryArray)
- {
- // Ignore in code coverage - a previous CleanupEntries would need to have failed with KErrDiskFull
- BULLSEYE_OFF
- LOGSMSPROT1("CSmsPermanentFileStore::CleanupEntriesWithCompactL()");
-
- iCompact = ETrue;
- CleanupEntriesL(aEntryArray);
- BULLSEYE_RESTORE
- }
-
-/*
-This function cleans its entries against the passed entries.
-This is needed because there migth be a scenario where user has deleted a message
-but the corresponding message is not deleted from permanent store file
-due to out-of-disk condition. But the entry is invalid because
-it is no more in the pre-allocated file which contains master header info.
-And also at the time of forwarding an incomplete message a forwarded
-message has not been deleted due to above reason.
-
-@param aEntryArray entray array against whose clean up is carried out.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::CleanupEntriesL(const CArrayFix<TSmsPreAllocatedFileStoreReassemblyEntry>& aEntryArray)
- {
- LOGSMSPROT1("CSmsPermanentFileStore::CleanupEntriesL()");
-
- TInt reassemblyCount = iEntryArray.Count();
- TInt index, index2;
-
- for (index = 0; index < reassemblyCount; index++)
- {
- for (index2 = 0; index2 < aEntryArray.Count(); index2++)
- {
- if (iEntryArray[index].Reference() == aEntryArray[index2].Reference() &&
- iEntryArray[index].Total() == aEntryArray[index2].Total() &&
- iEntryArray[index].PduType() == aEntryArray[index2].PduType() &&
- iEntryArray[index].Storage() == aEntryArray[index2].Storage() &&
- iEntryArray[index].Description2() == aEntryArray[index2].Description2())
- {
- if (aEntryArray[index2].NumberOfPDUsForwardToClient() > 0)
- {
- //Internalize the entries.
- CSmsBuffer* buffer = CSmsBuffer::NewL();
- CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer);
- CleanupStack::PushL(smsMessage);
-
- CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
- CleanupStack::PushL(indexArray);
- CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
- CleanupStack::PushL(smsArray);
-
- InternalizeEntryL(index, *smsMessage, *indexArray, *smsArray);
- TInt noOfForwardedEntries = 0;
- for (TInt j=indexArray->Count(); j>0 ;j--)
- {
- TUint8 bitMapIndex = (indexArray->At(j-1)-1)/8;
- TUint8 bitPos = (indexArray->At(j-1)-1)%8;
- TUint8 bitMap;
- TSmsPreAllocatedFileStoreReassemblyEntry entry;
- entry = aEntryArray[index2];
- entry.GetBitMap(bitMapIndex, bitMap);
- TUint8 tmpBitMap = 1;
- tmpBitMap <<= bitPos;
- if (tmpBitMap == (bitMap & tmpBitMap))
- {
- noOfForwardedEntries++;
- indexArray->Delete(j-1);
- smsArray->Delete(j-1);
- }
- }
- if (noOfForwardedEntries > 0)
- {
- TStreamId streamId = iEntryArray[index].DataStreamId();
- ExternalizeEntryL(streamId, *smsMessage, *indexArray, *smsArray);
- }
- CleanupStack::PopAndDestroy(3, smsMessage); // smsMessage, indexArray, smsArray
- }
- break;
- }
- }
- if (index2 == aEntryArray.Count())
- {
- DeleteEntryL(index);
- }
- }
- }
-
-/**
-It internalizes its entry array.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::InternalizeEntryArrayL()
- {
- LOGSMSPROT1("CSmsPermanentFileStore::InternalizeEntryArrayL()");
-
- iEntryArray.Reset();
- TStreamId headerid=iFileStore->Root();
- RStoreReadStream stream;
- stream.OpenLC(*iFileStore,headerid);
- TInt count=stream.ReadInt32L();
- for (TInt i=0; i<count; i++)
- {
- TSmsReassemblyEntry sarentry;
- stream >> sarentry;
- iEntryArray.AppendL(sarentry);
- }
- CleanupStack::PopAndDestroy(); // stream
- }
-
-/**
-It externalizes its entry array.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::ExternalizeEntryArrayL()
- {
- LOGSMSPROT4("CSmsPermanentFileStore::ExternalizeEntryArrayL(): this=0x%08X count=%d headerid=%d]",
- this, iEntryArray.Count(), iFileStore->Root().Value());
-
- TStreamId headerid=iFileStore->Root();
- RStoreWriteStream stream;
- if (headerid==KNullStreamId)
- {
- headerid=stream.CreateLC(*iFileStore);
- iFileStore->SetRootL(headerid);
- }
- else
- {
- stream.ReplaceLC(*iFileStore,headerid);
- }
-
- TInt count1=iEntryArray.Count();
- TInt count2=0;
- TInt i=0;
-
- for (; i<count1; i++)
- {
- if (!iEntryArray[i].IsDeleted())
- {
- count2++;
- }
- }
- stream.WriteInt32L(count2);
- for (i=0; i<count1; i++)
- {
- if (!iEntryArray[i].IsDeleted())
- {
- stream << iEntryArray[i];
- }
- }
-
- stream.CommitL();
- CleanupStack::PopAndDestroy(&stream);
- }
-
-/*
-It adds the new message in permanent store file.
-
-@param aIndex (output) index number on which message is added.
-@param aSmsMessage reference to sms message to be added.
-@param aGsmSms reference to GsmSms object to be added.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::AddNewMessageL(TInt& aIndex, CSmsMessage& aSmsMessage,const TGsmSms& aGsmSms)
- {
- LOGSMSPROT1("CSmsPermanentFileStore::AddNewMessageL");
-
- CArrayFix<TInt>* indexArray=new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
- CleanupStack::PushL(indexArray);
- CArrayFixFlat<TGsmSms>* smsArray=new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
- CleanupStack::PushL(smsArray);
- //Index must initialize to 0.
- TInt index = 0;
- if (!aSmsMessage.IsDecoded())
- {
- index = aSmsMessage.SmsPDU().ConcatenatedMessagePDUIndex();
- }
- indexArray->AppendL(index);
- smsArray->AppendL(aGsmSms);
-
- TStreamId streamid = KNullStreamId;
- ExternalizeEntryL(streamid, aSmsMessage, *indexArray, *smsArray);
-
- TSmsReassemblyEntry tmpEntry;
- //Fill-up entry information...
- CReassemblyStoreUtility::PopulateEntry(tmpEntry, aSmsMessage, 1);
- // Update Data stream id.
- tmpEntry.SetDataStreamId(streamid);
-
- aIndex = iEntryArray.Count();
- AddEntryL(tmpEntry);
- CleanupStack::PopAndDestroy(2); //indexArray, smsArray
- }
-
-/*
-It updates the existing message in permanent store file.
-
-@param aIndex index number on which message is to be updated.
-@param aSmsMessage reference to sms message to be updated.
-@param aIndexArray array of index of all the PDUs.
-@param aSmsArray array of sms of all the PDUs.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::UpdateExistingMessageL(TInt aIndex, const CSmsMessage& aSmsMessage,const CArrayFix<TInt>& aIndexArray,const CArrayFix<TGsmSms>& aSmsArray)
- {
- LOGSMSPROT1("CSmsPermanentFileStore::UpdateExistingMessageL()");
- TStreamId streamid = iEntryArray[aIndex].DataStreamId();
- ExternalizeEntryL(streamid, aSmsMessage, aIndexArray, aSmsArray);
- TSmsReassemblyEntry entry;
- CReassemblyStoreUtility::PopulateEntry(entry, aSmsMessage, aSmsArray.Count());
- entry.SetDataStreamId(streamid);
- ChangeEntryL(aIndex, entry);
- }
-
-/*
-It matches the entry with entry in permanent store file & returns
-the index. If not found it returns KErrNotFound.
-
-@param aEntry reference to entry information.
-@param aIndex (output) returns the index number.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::MatchEntryToExistingMessage(const TReassemblyEntry& aEntry,
- TInt& aIndex)
- {
- LOGSMSPROT1("CSmsPermanentFileStore::MatchEntryToExistingMessage()");
-
- aIndex = KErrNotFound;
-
- //
- // Search the reassembly store for a matching entry...
- //
- TInt reassemblyCount = iEntryArray.Count();
- for (TInt index = 0; index < reassemblyCount; index++)
- {
- TSmsReassemblyEntry& entry = iEntryArray[index];
-
- if (entry.Reference() == aEntry.Reference() &&
- entry.Total() == aEntry.Total() &&
- entry.PduType() == aEntry.PduType() &&
- entry.Storage() == aEntry.Storage() &&
- entry.Description2() == aEntry.Description2())
- {
- //
- // Found it!
- //
- aIndex = index;
- break;
- }
- }
-
- LOGSMSPROT2("CSmsPermanentFileStore::MatchEntryToExistingMessage(): aIndex=%d", aIndex);
- }
-
-/*
-It updates the log server id of the message.
-
-@param aIndex index number of the message to be updated.
-@param aLogServerId log server id.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::UpdateLogServerIdL(TInt& aIndex, TLogId aLogServerId)
- {
- LOGSMSPROT1("CSmsPermanentFileStore::UpdateLogServerIdL");
-
- TSmsReassemblyEntry entry;
- entry = iEntryArray[aIndex];
-
- if (entry.LogServerId() != aLogServerId)
- {
- entry.SetLogServerId(aLogServerId);
- ChangeEntryL(aIndex, entry);
- }
- }
-
-/*
-It sets the message passed to client or not.
-
-@param aIndex index number of the message to be updated.
-@param aBool boolean value indicating whether message is passes or not.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::SetPassedToClientL(TInt aIndex, TBool aBool)
- {
- LOGSMSPROT2("CSmsPermanentFileStore::SetPassedToClientL(): aIndex=%d", aIndex);
-
- TSmsReassemblyEntry entry;
- entry = iEntryArray[aIndex];
-
- if (entry.PassedToClient() != aBool)
- {
- entry.SetPassedToClient(aBool);
- ChangeEntryL(aIndex, entry);
- }
- }
-
-/*
-It adds the new entry in the existing entry array.
-
-@param aEntry entry to be added.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::AddEntryL(TSmsReassemblyEntry& aEntry)
- {
- iEntryArray.AppendL(aEntry);
- iEntryArray[iEntryArray.Count()-1].SetIsAdded(ETrue);
- }
-
-/*
-It changes the existing entry with new entry.
-
-@param aIndex index number of the entry which will be changed.
-@param aNewEntry entry to be updated.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::ChangeEntryL(TInt aIndex,const TSmsReassemblyEntry& aNewEntry)
- {
- LOGSMSPROT2("CSmsPermanentFileStore::ChangeEntryL(): aIndex=%d", aIndex);
-
- iEntryArray[aIndex].SetIsDeleted(ETrue);
- iEntryArray.InsertL(aIndex,aNewEntry);
- iEntryArray[aIndex].SetIsAdded(ETrue);
- }
-
-/*
-It deletes the entry.
-
-@param aIndex index number of the entry which will be deleted.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::DeleteEntryL(TInt aIndex)
- {
- iFileStore->DeleteL(iEntryArray[aIndex].DataStreamId());
- iEntryArray[aIndex].SetIsDeleted(ETrue);
- }
-
-/*
-It externalizes(writes) the entry in permanent store file.
-
-@param aStreamId stream id which needs to externalized.
-@param aSmsMessage reference to sms message which needs to be externalized.
-@param aIndexArray refence to array of index which needs to be externalized.
-@param aSmsArray refence to array of sms which needs to be externalized.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::ExternalizeEntryL(TStreamId& aStreamId,const CSmsMessage& aSmsMessage,const CArrayFix<TInt>& aIndexArray,const CArrayFix<TGsmSms>& aSmsArray)
- {
- LOGSMSPROT2("CSmsPermanentFileStore::ExternalizeEntryL Start [sid=%d]", aStreamId.Value());
-
- RStoreWriteStream writestream;
- if (aStreamId==KNullStreamId)
- aStreamId=writestream.CreateLC(*iFileStore);
- else
- writestream.ReplaceLC(*iFileStore,aStreamId);
- writestream << aSmsMessage;
- TInt count=aIndexArray.Count();
- writestream.WriteInt32L(count);
- TInt i=0;
- for (; i<count; i++)
- writestream.WriteInt32L(aIndexArray[i]);
- count=aSmsArray.Count();
- writestream.WriteInt32L(count);
- for (i=0; i<count; i++)
- {
- RMobileSmsMessaging::TMobileSmsGsmTpdu pdu;
- pdu=aSmsArray[i].Pdu();
- writestream << pdu;
- }
- writestream.CommitL();
- CleanupStack::PopAndDestroy();
-
- LOGSMSPROT2("CClass0PermanentFileStore::ExternalizeEntryL End [count=%d]", count);
- }
-
-/*
-It internalizes(reads) the entry from permanent store file.
-
-@param aIndex index number of the message to be internalized.
-@param aSmsMessage (output) reference to sms message.
-@param aIndexArray (output) refence to array of index.
-@param aSmsArray (output) refence to array of sms.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::InternalizeEntryL(const TInt aIndex, CSmsMessage& aSmsMessage, CArrayFix<TInt>& aIndexArray, CArrayFix<TGsmSms>& aSmsArray)
- {
- TSmsReassemblyEntry& entry = iEntryArray[aIndex];
- LOGSMSPROT2("CSmsPermanentFileStore::InternalizeEntryL Start [sid=%d]", entry.DataStreamId().Value());
- RStoreReadStream readstream;
- readstream.OpenLC(*iFileStore, entry.DataStreamId());
- readstream >> aSmsMessage;
- TInt count=readstream.ReadInt32L();
- TInt i;
- for (i=0; i<count; i++)
- {
- TInt index=readstream.ReadInt32L();
- aIndexArray.AppendL(index);
- }
- count=readstream.ReadInt32L();
- if(count!=aIndexArray.Count())
- {
- User::Leave(KErrCorrupt);
- }
- for (i=0; i<count; i++)
- {
- RMobileSmsMessaging::TMobileSmsGsmTpdu pdu;
- readstream >> pdu;
- TGsmSms sms;
- sms.SetPdu(pdu);
- aSmsArray.AppendL(sms);
- }
- CleanupStack::PopAndDestroy();
- //Set other properties of CSmsMessage
- aSmsMessage.SetStorage(entry.Storage());
- aSmsMessage.SetLogServerId(entry.LogServerId());
- aSmsMessage.SetTime(entry.Time());
- LOGSMSPROT2("CSmsPermanentFileStore::InternalizeEntryL End [count=%d]", count);
- }
-
-/*
-It removes the PDUs from permanent store file.
-This function is needed because after forwarding the incomplete message
-to client, the corresponding PDUs needs to be be removed from permanent
-store file.
-This functionality is specific to class 0 re-assembly store.
-
-@param aIndex index number of the message to be removed.
-@param aStartPos starting pos of pdu to be removed.
-@param aEndPos end pos of pdu to be removed.
-
-@internalComponent
-*/
-void CSmsPermanentFileStore::RemovePDUsL(TInt aIndex, TInt aStartPos, TInt aEndPos)
- {
- LOGSMSPROT1("CSmsPermanentFileStore::RemovePDUsL");
-
- CSmsBuffer* buffer = CSmsBuffer::NewL();
- CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer);
- CleanupStack::PushL(smsMessage);
-
- CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
- CleanupStack::PushL(indexArray);
- CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
- CleanupStack::PushL(smsArray);
-
- InternalizeEntryL(aIndex, *smsMessage, *indexArray, *smsArray);
-
- TInt count = indexArray->Count();
- for (TInt i=count; i>0; i--)
- {
- if ((indexArray->At(i-1) >= aStartPos) && (indexArray->At(i-1) <= aEndPos))
- {
- indexArray->Delete(i-1);
- smsArray->Delete(i-1);
- }
- }
-
- /*
- There are 3 scenarios in this case:
- 1. If all the entries are removed,
- then there is no need to store the entry in this permanent file.
- 2. If few entries are removed,
- then externalize the remaining entries. Update count field also.
- 3. If no entries are removed, then do nothing.
- */
- if (indexArray->Count()==0)
- {
- DeleteEntryL(aIndex);
- }
- else if (count!=indexArray->Count())
- {
- TStreamId streamid = iEntryArray[aIndex].DataStreamId();
- ExternalizeEntryL(streamid, *smsMessage, *indexArray, *smsArray);
-
- TSmsReassemblyEntry entry;
- entry = iEntryArray[aIndex];
- entry.SetCount(indexArray->Count());
- ChangeEntryL(aIndex, entry);
- }
- CleanupStack::PopAndDestroy(3, smsMessage); // smsMessage, indexArray, smsArray
- }
-
-/**
- * Sets the permanent store as in-transaction.
- *
- * The function checks the validity of the call and leaves KErrAccessDenied if
- * invalid.
- * @capability None
- */
-void CSmsPermanentFileStore::BeginTransactionL()
- {
- LOGSMSPROT4("CSmsPermanentFileStore::BeginTransactionL [this=0x%08X iInTransaction=%d iFileStore=0x%08X]", this, iInTransaction, iFileStore);
-
- if (iFileStore == NULL || iInTransaction)
- {
- LOGSMSPROT1("WARNING CSmsPermanentFileStore::BeginTransactionL leaving with KErrAccessDenied");
- User::Leave(KErrAccessDenied);
- }
-
- iInTransaction = ETrue;
- } // CSmsPermanentFileStore::BeginTransactionL
-
-/**
- * It reverts the transaction.
- */
-void CSmsPermanentFileStore::Revert()
- {
- LOGSMSPROT3("CSmsPermanentFileStore::Revert(): this=0x%08X, iInTransaction=%d",
- this, iInTransaction);
-
- iFileStore->Revert();
- iInTransaction = EFalse;
- ReinstateDeletedEntries();
- } // CSmsPermanentFileStore::Revert
-
-/**
- * It commits the transaction. Then it compact the permanent store file.
- */
-void CSmsPermanentFileStore::DoCommitAndCompactL()
- {
- LOGSMSPROT1("CSmsPermanentFileStore::DoCommitAndCompactL()");
-
- LOGSMSPROTTIMESTAMP();
- iFileStore->CommitL();
- LOGSMSPROTTIMESTAMP();
-
- iCommitCount--;
- if ((iCommitCount < 0) || (iCompact))
- {
- iCommitCount = KNumStoreCommitsBeforeCompaction;
- iFileStore->CompactL();
- iFileStore->CommitL();
- iCompact = EFalse;
- }
- } // CSmsPermanentFileStore::DoCommitAndCompactL
-
-/**
- * It commits the transaction.
- */
-void CSmsPermanentFileStore::CommitTransactionL()
- {
- LOGSMSPROT4("CSmsPermanentFileStore::CommitTransactionL(): this=0x%08X iInTransaction=%d iFileStore=0x%08X",
- this, iInTransaction, iFileStore);
-
- ExternalizeEntryArrayL();
-
-#ifdef _SMS_LOGGING_ENABLED
- TRAPD(err, DoCommitAndCompactL());
- if (err != KErrNone)
- {
- LOGGSMU2("WARNING! could not CommitL/CompactL due to %d", err);
- User::Leave(err);
- }
-#else
- DoCommitAndCompactL();
-#endif
-
- iInTransaction = EFalse;
- RemoveDeletedEntries();
- }
-
-/**
- * It removes the deleted entries from entry arry.
- * This function is called after commit.
- */
-void CSmsPermanentFileStore::RemoveDeletedEntries()
- {
- LOGSMSPROT1("CSmsPermanentFileStore::RemoveDeletedEntries()");
-
- TInt count=iEntryArray.Count();
- while (count--)
- {
- TSmsReassemblyEntry& entry = iEntryArray[count];
-
- if (entry.IsDeleted())
- {
- iEntryArray.Delete(count);
- }
- else
- {
- entry.SetIsAdded(EFalse);
- }
- }
- } // CSmsPermanentFileStore::RemoveDeletedEntries
-
-/**
- * It reinstate the deleted/added entries from entry arry.
- * This function is called after revert operation.
- */
-void CSmsPermanentFileStore::ReinstateDeletedEntries()
- {
- LOGSMSPROT1("CSmsPermanentFileStore::ReinstateDeletedEntries()");
-
- TInt count=iEntryArray.Count();
- while (count--)
- {
- TSmsReassemblyEntry& entry = iEntryArray[count];
-
- if (entry.IsAdded())
- {
- iEntryArray.Delete(count);
- }
- else
- {
- entry.SetIsDeleted(EFalse);
- }
- }
- } // CSmsPermanentFileStore::ReinstateDeletedEntries
-
-/**
- * Constructor
- *
- * @capability None
- */
-TSmsPreAllocatedFileStoreReassemblyEntry::TSmsPreAllocatedFileStoreReassemblyEntry():
- TSmsReassemblyEntry(),
- iPreAllocatedStorageId(0),
- iStatus(RMobileSmsStore::EStoredMessageUnknownStatus),
- iTimeOffset(0),
- iDecodedOnSim(EFalse),
- iForwardToClient(EFalse),
- iForwardedCount(0),
- iBitMap(NULL)
- {
- //Have to externalize so initialize to 0.
- for (TInt i=0; i<KBitMapLen; i++)
- {
- iBitMap.Append(0x00);
- }
- }
-
-/*
-It returns the reference of a particular bit-map index.
-
-@param aIndex index number of the bit-map.
-@param aBitMap bit-map value.
-
-@internalComponent
-*/
-void TSmsPreAllocatedFileStoreReassemblyEntry::GetBitMap(TUint8 aIndex, TUint8& aBitMap)
- {
- aBitMap = iBitMap[aIndex];
- }
-
-/*
-It sets the value of a bit-map.
-
-@param aIndex index number of the bit-map.
-@param aBitMap bit-map value
-
-@internalComponent
-*/
-void TSmsPreAllocatedFileStoreReassemblyEntry::SetBitMap(TUint8 aIndex, TUint8 aBitMap)
- {
- iBitMap[aIndex] = aBitMap;
- }
-
-/**
-Static factory constructor. Uses two phase
-construction and leaves nothing on the CleanupStack.
-
-@param aFs File Server handle.
-@param aFileName Permanent file store name.
-@param aMaxClass0Msg max class 0 message that can be stored.
-@param aMaxPDUSeg max number of pdus that can be stored.
-@param aVersion version number of pre-allocated file.
-
-@return A pointer to the newly created CPreallocatedFile object.
-
-@pre A connected file server session must be passed as parameter.
-@post CPreallocatedFile object is now fully initialised
-
-@internalComponent
-*/
-CPreallocatedFile* CPreallocatedFile::NewL(RFs& aFs, const TDesC& aFileName, TInt aMaxClass0Msg, TInt aMaxPDUSeg, TPreAllocatedFileVersion aVersion)
- {
- LOGSMSPROT1("CPreallocatedFile::NewL()");
- CPreallocatedFile* self = new (ELeave) CPreallocatedFile(aFs, aMaxClass0Msg, aMaxPDUSeg, aVersion);
- CleanupStack::PushL(self);
- self->ConstructL(aFileName);
- CleanupStack::Pop(self);
-
- return self;
- }
-
-void CPreallocatedFile::ConstructL(const TDesC& aFileName)
- {
- LOGSMSPROT1("CPreallocatedFile::ConstructL()");
- iFileName = aFileName.AllocL();
- }
-
-/**
- * Constructor.
-*/
-CPreallocatedFile::CPreallocatedFile(RFs& aFs, TInt aMaxClass0Msg, TInt aMaxPDUSeg, TPreAllocatedFileVersion aVersion)
- :iFs(aFs), iEntryArray(KFlatArrayGranularity), iReinstateEntryInfo(KFlatArrayGranularity), iMaxClass0Msg(aMaxClass0Msg), iMaxPDUSeg(aMaxPDUSeg), iVersion(aVersion)
- {
- /*
- Format of File:
- Version Number, Header Section & Data Section
- Version Number - Interger Value.
- Header Section: Number of entries, Array of Entries, Array of PDU identifier section, Checksum.
- Data Section: Array of Container. Each container contains Sms slot informatiuon, index number & PDU.
- */
-
- // Calculate the size of each section.
-
- // Entry section will always contain one more entry than configured one by the user.
- // Because it will provide one extra slot to store the new message for time being
- // before forwarding the oldest message.
- iSizeOfEntrySection = (KSizeOfPreAllocatedStoreEntry * (iMaxClass0Msg + 1));
-
- iSizeOfStorageIdentifierSection = ((sizeof(TInt))*(iMaxPDUSeg+1));
-
- TInt sizeOfHeaderSection = KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection + KSizeOfChecksum;
-
- TInt sizeOfDataSection = KSizeOfAContainer * (iMaxPDUSeg+1);
-
- // Calculate the size of File.
- iSizeOfFile = KSizeOfPreallocatedFileVersion + 2 * sizeOfHeaderSection + sizeOfDataSection;
-
- iBeginOfDuplicateHeaderSection = KSizeOfPreallocatedFileVersion + sizeOfHeaderSection;
- iBeginOfDataSection = KSizeOfPreallocatedFileVersion + 2 * sizeOfHeaderSection;
- }
-
-/**
- * Destructor. It destroys all the member variables.
-*/
-CPreallocatedFile::~CPreallocatedFile()
- {
- delete iFileName;
- }
-
-/**
-It checks & returns whether the file exist or not. If file is there whether
-it is corrupted or not.
-
-@internalComponent
-*/
-TBool CPreallocatedFile::IsFileOK()
- {
- LOGSMSPROT1("CPreallocatedFile::IsFileOK()");
-
- TEntry entry;
- // Check file exists
- TInt ret=iFs.Entry(iFileName->Des(), entry);
- // Check the size of file, if size does not match then assume that file
- // is corrupted, then return KErrNotFound.
- if ((ret == KErrNone) && (entry.iSize != iSizeOfFile))
- {
- ret = KErrNotFound;
- }
-
- if (ret == KErrNone)
- {
- return ETrue;
- }
- else
- {
- return EFalse;
- }
- }
-
-/**
-It creates a pre-allocated file.
-
-@internalComponent
-*/
-void CPreallocatedFile::CreateL()
- {
- LOGSMSPROT1("CPreallocatedFile::CreateL");
-
- User::LeaveIfError(iFile.Replace(iFs, iFileName->Des(), EFileWrite));
- User::LeaveIfError(iFile.SetSize(iSizeOfFile));
- iFile.Flush();
-
- // Externalize Version Number
- //TInt version = iVersion;
- TPtr8 memPtr((TUint8*) &iVersion, KSizeOfPreallocatedFileVersion, KSizeOfPreallocatedFileVersion);
- iFile.Write(0, memPtr);
-
- //Externalize Header Information
- ExternalizeEntryArray();
-
- // Initialize Storage Identifier Section.
- TInt storageIdentifier=0;
- memPtr.Set((TUint8*) &storageIdentifier, sizeof(storageIdentifier), sizeof(storageIdentifier));
- TInt pos = KSizeOfNumberOfEntrySection + iSizeOfEntrySection;
- TInt pos2 = 0;
- for (TInt count=0; count<iMaxPDUSeg+1; count++)
- {
- pos2 = pos + count * sizeof(storageIdentifier);
- iFile.Write(KBeginOfMasterHeaderSection + pos2, memPtr);
- //iFile.Write(iBeginOfDuplicateHeaderSection + pos2, memPtr);
- }
-
- // Initialize Checksum
- PutChecksumValueL();
-
- // Close it to make sure that file is created correctly (defensive approach).
- iFile.Close();
- //Again Open the file
- OpenL();
- }
-
-/**
-It opens the pre-allocated file. Then it internalizes all the entry information.
-
-@internalComponent
-*/
-void CPreallocatedFile::OpenL()
- {
- User::LeaveIfError(iFile.Open(iFs, iFileName->Des(), EFileShareExclusive|EFileRead|EFileWrite));
- // Check the validity of the data.
- CheckDataL();
- // Internalize data
- InternalizeEntryArrayL();
- }
-
-/**
-It closes the pre-allocated file.
-
-@internalComponent
-*/
-void CPreallocatedFile::Close()
- {
- iFile.Close();
- iEntryArray.Reset();
- iReinstateEntryInfo.Reset();
- }
-
-/**
-It internalizes the entry info from pre-allocated file.
-
-@internalComponent
-*/
-void CPreallocatedFile::InternalizeEntryArrayL()
- {
- iEntryArray.Reset();
- TInt numberOfMessage;
- TPtr8 memPtr((TUint8*) &numberOfMessage, sizeof(numberOfMessage), sizeof(numberOfMessage));
- iFile.Read(KBeginOfMasterHeaderSection, memPtr);
-
- TSmsPreAllocatedFileStoreReassemblyEntry tmpClass0ReassemblyStore;
- memPtr.Set((TUint8*) &tmpClass0ReassemblyStore, KSizeOfPreAllocatedStoreEntry, KSizeOfPreAllocatedStoreEntry);
-
- TInt pos = 0;
- for (TInt count=0; count < numberOfMessage; count++)
- {
- pos = sizeof(TInt) + (count * KSizeOfPreAllocatedStoreEntry);
- iFile.Read(KBeginOfMasterHeaderSection + pos, memPtr);
- iEntryArray.AppendL(tmpClass0ReassemblyStore);
- }
- }
-
-/**
-It externalizes the entry info to pre-allocated file.
-
-@internalComponent
-*/
-void CPreallocatedFile::ExternalizeEntryArray()
- {
- TInt count=iEntryArray.Count();
- TInt numberOfMessage=0;
- TInt i=0;
-
- for (; i<count; i++)
- {
- if (!iEntryArray[i].IsDeleted())
- {
- numberOfMessage++;
- }
- }
-
- //Externalize number of mesages.
- TPtr8 memPtr((TUint8*) &numberOfMessage, sizeof(numberOfMessage), sizeof(numberOfMessage));
- iFile.Write(KBeginOfMasterHeaderSection, memPtr);
-
- TInt entryNumber = 0;
- //Externalize all the entries.
- for (i=0; i<count; i++)
- {
- if (!iEntryArray[i].IsDeleted())
- {
- //At the time of externalizing don't externalize IsAdded(), IsDeleted() value
- TBool isAdded = iEntryArray[i].IsAdded();
- TBool isDeleted = iEntryArray[i].IsDeleted();
- iEntryArray[i].SetIsAdded(EFalse);
- iEntryArray[i].SetIsDeleted(EFalse);
- memPtr.Set((TUint8*) &iEntryArray[i], KSizeOfPreAllocatedStoreEntry, KSizeOfPreAllocatedStoreEntry);
- iFile.Write(KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + (entryNumber * KSizeOfPreAllocatedStoreEntry), memPtr);
- //Again update IsAdded(), IsDeleted() with previous value
- iEntryArray[i].SetIsAdded(isAdded);
- iEntryArray[i].SetIsDeleted(isDeleted);
- entryNumber++;
- }
- }
-
- count = numberOfMessage;
- /*
- Externalize extra entry information with default information.
- This initialization is required because of checksum.
- */
- TSmsPreAllocatedFileStoreReassemblyEntry tmpClass0ReassemblyStore;
- memPtr.Set((TUint8*) &tmpClass0ReassemblyStore, KSizeOfPreAllocatedStoreEntry, KSizeOfPreAllocatedStoreEntry);
- TInt pos = 0;
- for (; count<iMaxClass0Msg + 1; count++)
- {
- pos = KSizeOfNumberOfEntrySection + (count * KSizeOfPreAllocatedStoreEntry);
- iFile.Write(KBeginOfMasterHeaderSection + pos, memPtr);
- }
- iFile.Flush();
- }
-
-/*
-It adds the new message in pre-allocated file.
-
-@param aIndex (output) index number on which message is added.
-@param aSmsMessage reference to sms message to be added.
-@param aGsmSms reference to GsmSms object to be added.
-
-@internalComponent
-*/
-void CPreallocatedFile::AddNewMessageL(TInt& aIndex, CSmsMessage& aSmsMessage,const TGsmSms& aGsmSms)
- {
- LOGSMSPROT1("CPreallocatedFile::AddNewMessageL");
- //Gets the next free slot where the message will be stored.
- TInt nextFreeSlot = GetFreeContainer();
- TInt pduIndex=aSmsMessage.IsDecoded()? 0: aSmsMessage.SmsPDU().ConcatenatedMessagePDUIndex();
- if (aSmsMessage.Storage() == CSmsMessage::ESmsSIMStorage ||
- aSmsMessage.Storage() == CSmsMessage::ESmsCombinedStorage)
- {
- const TGsmSmsSlotEntry& newSlot = aSmsMessage.iSlotArray[0];
- ExternalizeEntry(nextFreeSlot, newSlot, pduIndex, aGsmSms);
- }
- else
- {
- ExternalizeEntry(nextFreeSlot, pduIndex, aGsmSms);
- }
-
- /*
- Gets the unique id which will identify the containers where the
- PDU related to this messsage are stored.
- */
- TInt freeStorageId = GetFreeStorageId();
- AddStorageIdL(nextFreeSlot, freeStorageId);
-
- TSmsPreAllocatedFileStoreReassemblyEntry tmpEntry;
- //Fill-up entry information...
- CReassemblyStoreUtility::PopulateEntry(tmpEntry, aSmsMessage, 1);
- tmpEntry.SetPreAllocatedStorageId(freeStorageId);
- //The properties below need to be set only once when a PDU of a new message arrives.
- tmpEntry.SetStatus((RMobileSmsStore::TMobileSmsStoreStatus)aSmsMessage.Status());
- tmpEntry.SetUTCOffset(aSmsMessage.UTCOffset());
- tmpEntry.SetDecodedOnSIM(aSmsMessage.DecodedOnSim());
- tmpEntry.SetForwardToClient(aSmsMessage.ForwardToClient());
-
- // Add & extrenalize entry array.
- aIndex = iEntryArray.Count();
- AddEntryL(tmpEntry);
- }
-
-/*
-It updates the existing message in permanent store file.
-
-@param aIndex index number on which message is to be updated.
-@param aSmsMessage reference to sms message to be updated.
-@param aPduIndex index of the PDU to be updated.
-@param aSms sms of the PDU to be updated.
-
-@internalComponent
-*/
-void CPreallocatedFile::UpdateExistingMessageL(TInt aIndex, const CSmsMessage& aSmsMessage, TInt aPduIndex, const TGsmSms& aSms)
- {
- LOGSMSPROT1("CPreallocatedFile::UpdateExistingMessageL()");
- TInt preAllocatedStorageId = iEntryArray[aIndex].PreAllocatedStorageId();
- if (preAllocatedStorageId == KErrNotFound)
- {
- /*
- This condition arises when part of message is stored in permanent store file &
- other parts arrive when system is out of disk.
- */
- preAllocatedStorageId = GetFreeStorageId();
- iEntryArray[aIndex].SetPreAllocatedStorageId(preAllocatedStorageId);
- }
- // Externalize Entry in one of free containers.
- TInt freeSlot = GetFreeContainer();
- if (aSmsMessage.Storage() == CSmsMessage::ESmsSIMStorage ||
- aSmsMessage.Storage() == CSmsMessage::ESmsCombinedStorage)
- {
- const TGsmSmsSlotEntry& newSlot = aSmsMessage.iSlotArray[0];
- ExternalizeEntry(freeSlot, newSlot, aPduIndex, aSms);
- }
- else
- {
- ExternalizeEntry(freeSlot, aPduIndex, aSms);
- }
-
- AddStorageIdL(freeSlot, preAllocatedStorageId);
- TSmsPreAllocatedFileStoreReassemblyEntry entry;
- entry = iEntryArray[aIndex];
- /*
- This value must be set because this may the first PDU of an
- existing message which is stored in pre-allocated store file.
- */
- entry.SetPreAllocatedStorageId(preAllocatedStorageId);
- entry.SetCount(entry.Count()+1);
- ChangeEntryL(aIndex, entry);
- }
-
-/*
-It matches the entry with entry in pre-allocated file & returns
-the index. If not found it returns KErrNotFound.
-
-@param aEntry reference to entry information.
-@param aIndex (output) returns the index number.
-
-@internalComponent
-*/
-void CPreallocatedFile::MatchEntryToExistingMessage(const TReassemblyEntry& aEntry,
- TInt& aIndex)
- {
- LOGSMSPROT1("CPreallocatedFile::MatchEntryToExistingMessage()");
-
- aIndex = KErrNotFound;
-
- //
- // Search the reassembly store for a matching entry...
- //
- TInt reassemblyCount = iEntryArray.Count();
-
- for (TInt index = 0; index < reassemblyCount; index++)
- {
- TSmsPreAllocatedFileStoreReassemblyEntry& entry = iEntryArray[index];
-
- if (entry.Reference() == aEntry.Reference() &&
- entry.Total() == aEntry.Total() &&
- entry.PduType() == aEntry.PduType() &&
- entry.Storage() == aEntry.Storage() &&
- entry.Description2() == aEntry.Description2())
- {
- //
- // Found it!
- //
- aIndex = index;
- break;
- }
- }
-
- LOGSMSPROT2("CPreallocatedFile::MatchEntryToExistingMessage(): aIndex=%d", aIndex);
- }
-
-/*
-It updates the log server id of the message.
-
-@param aIndex index number of the message to be updated.
-@param aLogServerId log server id.
-
-@internalComponent
-*/
-void CPreallocatedFile::UpdateLogServerIdL(TInt& aIndex, TLogId aLogServerId)
- {
- LOGSMSPROT1("CPreallocatedFile::UpdateLogServerId");
-
- TSmsPreAllocatedFileStoreReassemblyEntry entry;
- entry = iEntryArray[aIndex];
-
- if (entry.LogServerId() != aLogServerId)
- {
- entry.SetLogServerId(aLogServerId);
- ChangeEntryL(aIndex, entry);
- }
- }
-
-/*
-It sets the message passed to client or not.
-
-@param aIndex index number of the message to be updated.
-@param aBool boolean value indicating whether message is passes or not.
-
-@internalComponent
-*/
-void CPreallocatedFile::SetPassedToClientL(TInt aIndex, TBool aBool)
- {
- LOGSMSPROT2("CPreallocatedFile::SetPassedToClientL(): aIndex=%d", aIndex);
-
- TSmsPreAllocatedFileStoreReassemblyEntry entry;
- entry = iEntryArray[aIndex];
-
- if (entry.PassedToClient() != aBool)
- {
- entry.SetPassedToClient(aBool);
- ChangeEntryL(aIndex, entry);
- }
- }
-
-/*
-It adds the new entry in the existing entry array.
-
-@param aEntry entry to be added.
-
-@internalComponent
-*/
-void CPreallocatedFile::AddEntryL(TSmsPreAllocatedFileStoreReassemblyEntry& aEntry)
- {
- LOGSMSPROT1("CPreallocatedFile::AddEntryL");
- iEntryArray.AppendL(aEntry);
- iEntryArray[iEntryArray.Count()-1].SetIsAdded(ETrue);
- }
-
-/*
-It changes the existing entry with new entry.
-
-@param aIndex index number of the entry which will be changed.
-@param aNewEntry entry to be updated.
-
-@internalComponent
-*/
-void CPreallocatedFile::ChangeEntryL(TInt aIndex, const TSmsPreAllocatedFileStoreReassemblyEntry& aNewEntry)
- {
- LOGSMSPROT2("CPreallocatedFile::ChangeEntryL(): aIndex=%d", aIndex);
- iEntryArray[aIndex].SetIsDeleted(ETrue);
- iEntryArray.InsertL(aIndex,aNewEntry);
- iEntryArray[aIndex].SetIsAdded(ETrue);
- }
-
-/*
-It deletes the entry.
-
-@param aIndex index number of the entry which will be deleted.
-
-@internalComponent
-*/
-void CPreallocatedFile::DeleteEntryL(TInt aIndex)
- {
- LOGSMSPROT2("CPreallocatedFile::DeleteEntryL(): aIndex=%d", aIndex);
- if (iEntryArray[aIndex].PreAllocatedStorageId() != KErrNotFound)
- {
- ClearEntryL(iEntryArray[aIndex].PreAllocatedStorageId(), iEntryArray[aIndex].Count());
- }
- iEntryArray[aIndex].SetIsDeleted(ETrue);
- }
-
-/*
-It searches all the container & clears all the entries which
-contain the PDUs of the message (uniquely identified by aStorageId).
-
-NOTE:
- It keeps the record of removed entries (container id, pre-allocated storage id
- & operation performed (add/delete)) in iReinstateEntryInfo variable.
- It will be required in case of revert operation. As the container which
- refers to the container which contains actual PDU is freed,
- so it will not be a problem to restore the removed PDUs.
- In case of revert operation, the removed information can be found in
- iReinstateEntryInfo variable which can be restored easily.
- The container can be replaced with previous pre-allocated storage id.
- After commiting the transaction, this varaible will be re-initialized.
-
-@param aStorageId unique id of message to be cleared.
-@param aNumberOfPDUs number of PDUs to be cleared.
-
-@internalComponent
-*/
-void CPreallocatedFile::ClearEntryL(TInt aStorageId, TInt aNumberOfPDUs)
- {
- LOGSMSPROT1("CPreallocatedFile::ClearEntryL");
-
- //Read storage id.
- TInt storageId;
- TPtr8 memPtr((TUint8*) &storageId, sizeof(storageId), sizeof(storageId));
- TInt beginOfStorageIdSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection;
- TInt beginOfStorageId = 0;
- TInt count;
- TInt count2(0);
-
- TInt cleanStorageId=0;
- TPtr8 memPtr2((TUint8*) &cleanStorageId, sizeof(cleanStorageId), sizeof(cleanStorageId));
-
- for (count=0; count<iMaxPDUSeg+1; count++)
- {
- TReinstateEntryInfo entry;
- entry.iPreAllocatedStorageId=aStorageId;
- entry.iFlag=EEntryIsDeleted;
-
- beginOfStorageId = beginOfStorageIdSection + (count * sizeof(storageId));
- iFile.Read(beginOfStorageId, memPtr);
- if (storageId == aStorageId)
- {
- count2++;
- iFile.Write(beginOfStorageId, memPtr2);
- entry.iContainerId=count+1;
- iReinstateEntryInfo.AppendL(entry);
- }
- if (count2 >= aNumberOfPDUs)
- {
- break;
- }
- }
- iFile.Flush();
- }
-
-/*
-It updates the storage identifier section. It updates the corresponding container
-in the storage identifier section specifying the PDU where it is stored.
-
-NOTE:
- It keeps the record of added entries in iReinstateEntryInfo variable.
- It will be required in case of revert operation.
- After commiting the transaction, this varaible should be re-initialized.
-
-@param aIndex index number of the container where PDU has been stored..
-@param aStorageId unique id of added message.
-
-@internalComponent
-*/
-void CPreallocatedFile::AddStorageIdL(TInt aIndex, TInt aStorageId)
- {
- //Put storage id in master header section
- TPtr8 memPtr((TUint8*) &aStorageId, sizeof(aStorageId), sizeof(aStorageId));
- TInt beginOfStorageIdentifierSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection;
- iFile.Write( beginOfStorageIdentifierSection + ((aIndex - 1) * sizeof(TInt)), memPtr);
-
- TReinstateEntryInfo entry;
- entry.iContainerId=aIndex;
- entry.iPreAllocatedStorageId=aStorageId;
- entry.iFlag=EEntryIsAdded;
- iReinstateEntryInfo.AppendL(entry);
- }
-
-/*
-It returns the next free available free container where next PDU can be stored.
-
-It goes through storage identifier section, it reads the conents of all storage
-identfier & return that container which is free.
-All the free container is identifiable by value 0. If the value is not 0 then it
-contains the storage id of a particular message.
-
-@internalComponent
-*/
-TInt CPreallocatedFile::GetFreeContainer()
- {
- // Get the next free slot.
- TInt storageId;
- TPtr8 memPtr((TUint8*) &storageId, sizeof(storageId), sizeof(storageId));
- TInt beginOfStorageIdSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection;
- TInt beginOfStorageId = 0;
- TInt count;
-
- for (count=0; count<iMaxPDUSeg+1; count++)
- {
- beginOfStorageId = beginOfStorageIdSection + (count * sizeof(storageId));
- iFile.Read(beginOfStorageId, memPtr);
- if (storageId == 0)
- {
- break;
- }
- }
-
- // Count should never equal to iMaxPDUSeg+1
- __ASSERT_DEBUG(count < iMaxPDUSeg+1, SmspPanic(KSmspPanicPreallocatedFileNoFreeContainer));
-
- return (count + 1);
- }
-
-/*
-It returns the next free storage id.
-
-Storage id is used to identify the messages stored in pre-allocated file.
-A message might contain multiple PDUs and all those PDUs will be stored in
-different container. This storage id will be used to identify on which
-container the PDUs of a message are stored.
-
-This logic is based on the max number of messages that can be stored in
-pre-allocated file at one time. So free storage id is always used from
-this pool of numbers (from 1 till (max calls 0 message+2)).
-
-@internalComponent
-*/
-TInt CPreallocatedFile::GetFreeStorageId()
- {
- TInt count;
-
- for (count=1; count < iMaxClass0Msg + 2; count++)
- {
- TInt numberOfEntries = iEntryArray.Count();
- TInt count2;
- for (count2 = 0; count2 < numberOfEntries; count2++)
- {
- if (count == iEntryArray[count2].PreAllocatedStorageId())
- {
- break;
- }
- }
- if (count2 == numberOfEntries)
- {
- break;
- }
- }
- return count;
- }
-
-/*
-It externalizes(writes) the entry in permanent store file.
-
-@param aContainerId container id where the sms pdu needs to externalized.
-@param aSmsSlot reference to slot information.
-@param aIndex index number of PDU.
-@param aGsmSms refence to sms pdu.
-
-@internalComponent
-*/
-void CPreallocatedFile::ExternalizeEntry(TInt aContainerId, const TGsmSmsSlotEntry& aSmsSlot, TInt aIndex, const TGsmSms& aGsmSms)
- {
- LOGSMSPROT3("CPreallocatedFile::ExternalizeEntry() 1: aContainerId=%d, aIndex=%d", aContainerId, aIndex);
-
- // Container id must not be greater than max pdu segment.
- TInt pos = iBeginOfDataSection + ((aContainerId - 1) * (KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU));
- // Store slot info
- TPtr8 memPtr((TUint8*) &aSmsSlot, sizeof(aSmsSlot), sizeof(aSmsSlot));
- iFile.Write(pos, memPtr);
- // Store the PDU index value
- memPtr.Set((TUint8*) &aIndex, sizeof(aIndex), sizeof(aIndex));
- iFile.Write(pos + KSizeOfGsmSmsSlotEntry, memPtr);
- // Store the TGsmSms value
- RMobileSmsMessaging::TMobileSmsGsmTpdu pdu;
- pdu = aGsmSms.Pdu();
- memPtr.Set((TUint8*) &pdu, KSizeOfSmsGsmPDU, KSizeOfSmsGsmPDU);
- iFile.Write(pos + KSizeOfGsmSmsSlotEntry + sizeof(TInt), memPtr);
-
- __ASSERT_DEBUG(pos + KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU <= iSizeOfFile,
- SmspPanic(KSmspPanicPreallocatedFileCorrupt));
- }
-
-/*
-It externalizes(writes) the entry in permanent store file.
-
-@param aContainerId container id where the sms pdu needs to externalized.
-@param aIndex index number of PDU.
-@param aGsmSms refence to sms pdu.
-
-@internalComponent
-*/
-void CPreallocatedFile::ExternalizeEntry(TInt aContainerId, TInt aIndex, const TGsmSms& aGsmSms)
- {
- LOGSMSPROT3("CPreallocatedFile::ExternalizeEntry() 2: aContainerId=%d, aIndex=%d", aContainerId, aIndex);
-
- // Container id must not be greater than max pdu segment.
- TInt pos = iBeginOfDataSection + ((aContainerId - 1) * (KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU));
- // Store the PDU index value
- TPtr8 memPtr((TUint8*) &aIndex, sizeof(aIndex), sizeof(aIndex));
- iFile.Write(pos + KSizeOfGsmSmsSlotEntry, memPtr);
- // Store the TGsmSms value
- RMobileSmsMessaging::TMobileSmsGsmTpdu pdu;
- pdu = aGsmSms.Pdu();
- memPtr.Set((TUint8*) &pdu, KSizeOfSmsGsmPDU, KSizeOfSmsGsmPDU);
- iFile.Write(pos + KSizeOfGsmSmsSlotEntry + sizeof(TInt), memPtr);
-
- __ASSERT_DEBUG(pos + KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU <= iSizeOfFile,
- SmspPanic(KSmspPanicPreallocatedFileCorrupt));
- }
-
-/*
-It internalizes(reads) the entry from permanent store file.
-
-@param aIndex index number of the message to be internalized.
-@param aSmsMessage (output) reference to sms message.
-@param aIndexArray (output) refence to array of index.
-@param aSmsArray (output) refence to array of sms.
-
-@internalComponent
-*/
-void CPreallocatedFile::InternalizeEntryL(const TInt aIndex, CSmsMessage& aSmsMessage, CArrayFix<TInt>& aIndexArray, CArrayFix<TGsmSms>& aSmsArray)
- {
- LOGSMSPROT1("CPreallocatedFile::InternalizeEntryL");
- TSmsPreAllocatedFileStoreReassemblyEntry& entry = iEntryArray[aIndex];
- //Set other properties of CSmsMessage
- aSmsMessage.SetStorage(entry.Storage());
- aSmsMessage.SetStatus((NMobileSmsStore::TMobileSmsStoreStatus)entry.Status());
- aSmsMessage.SetLogServerId(entry.LogServerId());
- aSmsMessage.SetTime(entry.Time());
- aSmsMessage.SetUTCOffset(entry.UTCOffset());
- aSmsMessage.SetDecodedOnSIM(entry.DecodedOnSIM());
- aSmsMessage.SetForwardToClient(entry.ForwardToClient());
- aSmsMessage.SetToFromAddressL(entry.Description2());
-
- LOGSMSPROT2("CPreallocatedFile::InternalizeEntryL Start [sid=%d]", entry.PreAllocatedStorageId());
- if (entry.PreAllocatedStorageId()==KErrNotFound)
- {
- return;
- }
-
- TInt beginOfStorageIdSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection;
- //This will be used to read the storgae id which will indicate
- //that corresponding container contains actual PDU
- TInt storageId=0;
- TPtr8 memPtr1((TUint8*) &storageId, sizeof(storageId), sizeof(storageId));
-
- TInt storageIdPos = 0;
- TInt dataPos = 0;
- //This will be used to read the slot information
- TGsmSmsSlotEntry smsSlotEntry;
- TPtr8 memPtr2((TUint8*) &smsSlotEntry, KSizeOfGsmSmsSlotEntry, KSizeOfGsmSmsSlotEntry);
- //This will be used to read the concatenated PDU index.
- TInt index=0;
- TPtr8 memPtr3((TUint8*) &index, sizeof(index), sizeof(index));
- //This will be used to read PDU.
- RMobileSmsMessaging::TMobileSmsGsmTpdu pdu;
- TPtr8 memPtr4((TUint8*) &pdu, KSizeOfSmsGsmPDU, KSizeOfSmsGsmPDU);
- TGsmSms sms;
-
- //Number of PDUs stored in this pre-allocated file
- TInt noOfPDUs = iEntryArray[aIndex].Count();
- //Will indicate how many number of PDUs already read from pre-allocated file.
- TInt noOfPDUsRead = 0;
- // Can also get the number of pdu stored in pre-allocated file from count's variable.
- for (TInt count=0; count<iMaxPDUSeg+1; count++)
- {
- storageIdPos = beginOfStorageIdSection + count * sizeof(TInt);
- iFile.Read(storageIdPos, memPtr1);
- if (storageId == entry.PreAllocatedStorageId())
- {//This means corresponding container contains the actual PDU
- noOfPDUsRead++;
- //Find the position of container where actaul PDU is stored.
- dataPos = iBeginOfDataSection + ((count) * (KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU));
- //Read slot information
- if (entry.Storage() == CSmsMessage::ESmsSIMStorage ||
- entry.Storage() == CSmsMessage::ESmsCombinedStorage)
- {
- iFile.Read(dataPos + KSizeOfGsmSmsSlotEntry, memPtr2);
- aSmsMessage.AddSlotL(smsSlotEntry);
- }
- //Read index information
- iFile.Read(dataPos + KSizeOfGsmSmsSlotEntry, memPtr3);
- aIndexArray.AppendL(index);
- //Read PDU
- iFile.Read(dataPos + KSizeOfGsmSmsSlotEntry + sizeof(index), memPtr4);
- sms.SetPdu(pdu);
- aSmsArray.AppendL(sms);
- if (noOfPDUsRead == noOfPDUs)
- {
- break;
- }
- }
- }
-
- LOGSMSPROT2("CPreallocatedFile::InternalizeEntryL End [noOfPDUsRead=%d]", noOfPDUsRead);
- }
-
-/*
-It removes the PDUs from pre-allocated store file.
-This function is needed because after forwarding the incomplete message
-to client, the corresponding PDUs needs to be be removed from permanent
-store file.
-This functionality is specific to class 0 re-assembly store.
-
-@param aIndex index number of the message to be removed.
-@param aStartPos starting pos of pdu to be removed.
-@param aEndPos end pos of pdu to be removed.
-
-@internalComponent
-*/
-void CPreallocatedFile::RemovePDUsL(TInt aIndex, TInt aStartPos, TInt aEndPos)
- {
- LOGSMSPROT1("CPreallocatedFile::RemovePDUsL");
-
- if ((aStartPos < 1) || (aEndPos > 256) || (aStartPos > aEndPos))
- {
- User::Leave(KErrArgument);
- }
-
- LOGSMSPROT2("CPreallocatedFile::RemovePDUsL Start [sid=%d]", iEntryArray[aIndex].PreAllocatedStorageId());
- if (iEntryArray[aIndex].PreAllocatedStorageId()==KErrNotFound)
- {
- return;
- }
-
- TInt beginOfStorageIdSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection;
- //This will be used to read the storgae id which will indicate
- //that corresponding container contains actual PDU
- TInt storageId=0;
- TPtr8 memPtr1((TUint8*) &storageId, sizeof(storageId), sizeof(storageId));
-
- //This will be used to cleanup the storage id.
- TInt cleanStorageId=0;
- TPtr8 memPtr2((TUint8*) &cleanStorageId, sizeof(cleanStorageId), sizeof(cleanStorageId));
-
- //This will be used to read the concatenated PDU index.
- TInt index=0;
- TPtr8 memPtr3((TUint8*) &index, sizeof(index), sizeof(index));
-
- //Number of PDUs stored in this pre-allocated file
- TInt noOfPDUs = iEntryArray[aIndex].Count();
- //Will indicate how many number of PDUs already read from pre-allocated file.
- TInt noOfPDUsRead = 0;
- // Can also get the number of pdu stored in pre-allocated file from count's variable.
- TInt noOfEntriesRemoved=0;
- for (TInt count=0; count<iMaxPDUSeg+1; count++)
- {
- TInt storageIdPos = beginOfStorageIdSection + count * sizeof(TInt);
- iFile.Read(storageIdPos, memPtr1);
- if (storageId == iEntryArray[aIndex].PreAllocatedStorageId())
- {//This means corresponding container contains the actual PDU
- noOfPDUsRead++;
- //Find the position of container where actaul PDU is stored.
- TInt dataPos = iBeginOfDataSection + ((count) * (KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU));
- //Read index information
- iFile.Read(dataPos + KSizeOfGsmSmsSlotEntry, memPtr3);
-
- if ((index >= aStartPos) && (index <= aEndPos))
- {
- noOfEntriesRemoved++;
- //Remove the PDU entry.
- iFile.Write(storageIdPos, memPtr2);
- }
-
- if (noOfPDUsRead == noOfPDUs)
- {
- break;
- }
- }
- }
-
- /*
- There are 3 scenarios in this case:
- 1. If all the entries need to be removed,
- then there is no need to store the entry in this permanent file.
- 2. If few entries need to be removed,
- then externalize the remaining entries. Update count field also.
- 3. If no entries need to be removed, then do nothing.
- */
- TSmsPreAllocatedFileStoreReassemblyEntry entry;
- entry = iEntryArray[aIndex];
-
- if (entry.Count() == noOfEntriesRemoved)
- {
- entry.SetPreAllocatedStorageId(KErrNotFound);
- entry.SetCount(0);
- ChangeEntryL(aIndex, entry);
- }
- else if (noOfEntriesRemoved > 0)
- {
- entry.SetCount(entry.Count() - noOfEntriesRemoved);
- ChangeEntryL(aIndex, entry);
- }
- }
-
-/*
-It stores the forwarded message info in forwarded pdu bit-map.
-
-@param aIndex index number of the forwarded message.
-@param aStartPos starting pos of forwarded pdu.
-@param aEndPos end pos of forwarded pdu.
-
-@internalComponent
-*/
-void CPreallocatedFile::StoreForwardedPDUsInfoL(TInt aIndex, TInt aStartPos, TInt aEndPos)
- {
- TSmsPreAllocatedFileStoreReassemblyEntry entry;
- entry = iEntryArray[aIndex];
-
- TUint8 startBitMapIndex = (aStartPos-1)/8;
- TUint8 endBitMapIndex = (aEndPos-1)/8;
- TUint8 startBitPos = (aStartPos-1)%8;
- TUint8 endBitPos = (aEndPos-1)%8;
-
- if (startBitMapIndex == endBitMapIndex)
- {
- TUint8 bitMap;
- entry.GetBitMap(startBitMapIndex, bitMap);
- TUint8 tmpBitMap = (0 | 0xFF);
- tmpBitMap <<= ((8 - endBitPos) - 1);
- tmpBitMap >>= (8 - ((endBitPos - startBitPos)+1));
- tmpBitMap <<= startBitPos;
- bitMap |= tmpBitMap;
- entry.SetBitMap(startBitMapIndex, bitMap);
- }
- else
- {
- TUint8 bitMap;
- entry.GetBitMap(startBitMapIndex, bitMap);
- TUint8 tmpBitMap = (0 | 0xFF);
- tmpBitMap >>= (8 - ((7 - startBitPos)+1));
- tmpBitMap <<= startBitPos;
- bitMap |= tmpBitMap;
- entry.SetBitMap(startBitMapIndex, bitMap);
-
- entry.GetBitMap(endBitMapIndex, bitMap);
- tmpBitMap = (0 | 0xFF);
- tmpBitMap <<= ((8 - endBitPos) - 1);
- tmpBitMap >>= (8 - ((endBitPos - 0)+1));
- tmpBitMap <<= 0;
- bitMap |= tmpBitMap;
- entry.SetBitMap(endBitMapIndex, bitMap);
- }
-
- TInt noOfForwardedPDUs = (aEndPos - aStartPos) + 1;
- entry.SetNumberOfPDUsForwardToClient(entry.NumberOfPDUsForwardToClient()+noOfForwardedPDUs);
-
- ChangeEntryL(aIndex, entry);
- }
-
-/*
-It checks the validity of master header section by comparing checksum value.
-If the checksum value does not match, then it copies data from duplicate header section to
-master header section.
-*/
-void CPreallocatedFile::CheckDataL()
- {
- TUint32 checksum;
- TInt checksumPos = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection;
-
- TPtr8 memPtr((TUint8*) &checksum, sizeof(checksum), sizeof(checksum));
- iFile.Read(checksumPos, memPtr);
-
- if (ChecksumValue() != checksum)
- {
- CopyDuplicateToMasterL();
- }
- }
-
-/*
-It writes the checksum value & then copies header information from master section to duplicate section.
-*/
-void CPreallocatedFile::PutChecksumValueL()
- {
- TUint32 checksum = ChecksumValue();
- TInt checksumPos = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection;
-
- TPtr8 memPtr((TUint8*) &checksum, sizeof(checksum), sizeof(checksum));
- iFile.Write(checksumPos, memPtr);
- iFile.Flush();
- CopyMasterToDuplicateL();
- }
-
-/*
-It calculates & returns the checksum value of master header section.
-*/
-TUint32 CPreallocatedFile::ChecksumValue()
- {
- TInt sizeOfDataToBeChecksum = KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection;
-
- TUint32 checksum(0);
-
- TUint32 tmpValue;
- TPtr8 memPtr((TUint8*) &tmpValue, sizeof(tmpValue), sizeof(tmpValue));
-
- for (TInt i = 0; i < sizeOfDataToBeChecksum/4 ; i++)
- {
- iFile.Read(KBeginOfMasterHeaderSection + (i*4), memPtr);
- checksum += tmpValue;
- }
- return checksum;
- }
-
-/*
-It copies header information from master copy to duplicate copy.
-*/
-void CPreallocatedFile::CopyMasterToDuplicateL()
- {
- TInt sizeOfDataToBeCopied = KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection + 4;
-
- HBufC8* heapBuffer = HBufC8::NewL(sizeOfDataToBeCopied);
- CleanupStack::PushL(heapBuffer);
- TPtr8 memPtr(heapBuffer->Des());
- iFile.Read(KBeginOfMasterHeaderSection, memPtr);
- iFile.Write(iBeginOfDuplicateHeaderSection, memPtr);
- iFile.Flush();
- CleanupStack::PopAndDestroy(heapBuffer);
- }
-
-/*
-It copies header information from duplicate copy to master copy.
-*/
-void CPreallocatedFile::CopyDuplicateToMasterL()
- {
- TInt sizeOfDataToBeCopied = KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection + 4;
-
- HBufC8* heapBuffer = HBufC8::NewL(sizeOfDataToBeCopied);
- CleanupStack::PushL(heapBuffer);
- TPtr8 memPtr(heapBuffer->Des());
- iFile.Read(iBeginOfDuplicateHeaderSection, memPtr);
- iFile.Write(KBeginOfMasterHeaderSection, memPtr);
- iFile.Flush();
- CleanupStack::PopAndDestroy(heapBuffer);
- }
-
-/*
-It returns the total number of PDUs stored in pre-allocated file.
-*/
-TInt CPreallocatedFile::NumberOfPDUStored()
- {
- TInt noOfPDUs = 0;
- for (TInt i = 0; i < iEntryArray.Count(); i++)
- {
- noOfPDUs += iEntryArray[i].Count();
- }
- return noOfPDUs;
- }
-
-/**
- * Sets the pre-allocated file store as in-transaction.
- *
- * The function checks the validity of the call and leaves KErrAccessDenied if
- * invalid.
- * @capability None
- */
-void CPreallocatedFile::BeginTransactionL()
- {
- LOGSMSPROT3("CPreallocatedFile::BeginTransactionL [this=0x%08X iInTransaction=%d]", this, iInTransaction);
-
- if (iInTransaction)
- {
- LOGGSMU1("WARNING CPreallocatedFile::BeginTransactionL leaving with KErrAccessDenied");
- User::Leave(KErrAccessDenied);
- }
-
- iInTransaction = ETrue;
- }
-
-/**
- * It commits the transaction.
- */
-void CPreallocatedFile::CommitTransactionL()
- {
- LOGSMSPROT3("CPreallocatedFile::CommitTransactionL(): this=0x%08X iInTransaction=%d",
- this, iInTransaction);
-
- ExternalizeEntryArray();
- //Commit
- PutChecksumValueL();
- iInTransaction = EFalse;
- iReinstateEntryInfo.Reset();
- RemoveDeletedEntries();
- }
-
-/*
-It reverts the transaction.
-*/
-void CPreallocatedFile::Revert()
- {
- LOGSMSPROT3("CPreallocatedFile::Revert(): this=0x%08X, iInTransaction=%d",
- this, iInTransaction);
-
- ReinstateEntries();
- ExternalizeEntryArray();
- iInTransaction = EFalse;
- ReinstateDeletedEntries();
- }
-
-/**
- * It removes the deleted entries from entry arry.
- * This function is called after commit.
- */
-void CPreallocatedFile::RemoveDeletedEntries()
- {
- LOGSMSPROT1("CPreallocatedFile::RemoveDeletedEntries()");
-
- TInt count=iEntryArray.Count();
- while (count--)
- {
- TSmsPreAllocatedFileStoreReassemblyEntry& entry = iEntryArray[count];
-
- if (entry.IsDeleted())
- {
- iEntryArray.Delete(count);
- }
- else
- {
- entry.SetIsAdded(EFalse);
- }
- }
- } // CPreallocatedFile::RemoveDeletedEntries
-
-/**
- * It reinstate the deleted/added entries from entry arry.
- * This function is called after revert operation.
- */
-void CPreallocatedFile::ReinstateDeletedEntries()
- {
- LOGSMSPROT1("CPreallocatedFile::ReinstateDeletedEntries()");
-
- TInt count=iEntryArray.Count();
- while (count--)
- {
- TSmsPreAllocatedFileStoreReassemblyEntry& entry = iEntryArray[count];
-
- if (entry.IsAdded())
- {
- iEntryArray.Delete(count);
- }
- else
- {
- entry.SetIsDeleted(EFalse);
- }
- }
- } // CPreallocatedFile::ReinstateDeletedEntries
-
-/**
- * It reinstate the deleted/added entries from the container.
- * This function is called at the time of revert operation.
- * Unlike permanent store file which supports revert. pre-allocated
- * file (raw data file) supports the revert mecahnism using this function.
- */
-void CPreallocatedFile::ReinstateEntries()
- {
- LOGSMSPROT1("CPreallocatedFile::ReinstateEntries()");
-
- TInt containerId;
- TInt storageId;
- TPtr8 memPtr((TUint8*) &storageId, sizeof(storageId), sizeof(storageId));
-
- TInt count = iReinstateEntryInfo.Count();
-
- for (TInt i=0; i<count; i++)
- {
- if (iReinstateEntryInfo[i].iFlag == EEntryIsDeleted)
- {
- //Add the Pre-allocated storage info in the container.
- storageId = iReinstateEntryInfo[i].iPreAllocatedStorageId;
- containerId = iReinstateEntryInfo[i].iContainerId;
- TInt beginOfStorageIdentifierSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection;
- iFile.Write( beginOfStorageIdentifierSection + ((containerId - 1) * sizeof(TInt)), memPtr);
- }
- else //EEntryIsAdded
- {
- //Delete the Pre-allocated storage info from the container.
- storageId = 0;
- containerId = iReinstateEntryInfo[i].iContainerId;
- TInt beginOfStorageIdentifierSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection;
- iFile.Write( beginOfStorageIdentifierSection + ((containerId - 1) * sizeof(TInt)), memPtr);
- }
- }
- iFile.Flush();
- iReinstateEntryInfo.Reset();
- }
-
-/*
-It returns the index of oldest message in pre-allocated file.
-*/
-TInt CPreallocatedFile::GetOldestMessageEntryIndex()
- {
- LOGSMSPROT1("CPreallocatedFile::GetOldestMessageEntryIndex()");
-
- TInt index = KErrNotFound;
- TTime time;
- time.UniversalTime();
-
- for (TInt index2=0; index2 < iEntryArray.Count(); index2++)
- {
- if ((iEntryArray[index2].Time() < time) && (iEntryArray[index2].Count()>0))
- {
- time = iEntryArray[index2].Time();
- index = index2;
- }
- }
- return index;
- }
-
-/**
-Static factory constructor. Uses two phase
-construction and leaves nothing on the CleanupStack.
-
-@param aClass0ReassemblyStore reference to class 0 reasembly store.
-@param aGuardTimeout guard time out in hours.
-
-@return A pointer to the newly created CGuardTimer object.
-
-@internalComponent
-*/
-CGuardTimer* CGuardTimer::NewL(CClass0SmsReassemblyStore& aClass0ReassemblyStore, TInt aGuardTimeout)
- {
- LOGSMSPROT1("CGuardTimer::NewL()");
-
- CGuardTimer* timer = new(ELeave) CGuardTimer(aClass0ReassemblyStore, aGuardTimeout);
- CleanupStack::PushL(timer);
- timer->ConstructL();
- CleanupStack::Pop();
- return timer;
- } // CGuardTimer::NewL
-
-/**
- * Constructor
- */
-CGuardTimer::CGuardTimer(CClass0SmsReassemblyStore& aClass0ReassemblyStore, TInt aGuardTimeout)
- :CTimer(KSmsSessionPriority),
- iClass0ReassemblyStore(aClass0ReassemblyStore),
- iTimeoutInSecs(aGuardTimeout*3600)
- {
- CActiveScheduler::Add(this);
- } //CGuardTimer::CGuardTimer
-
-/**
- * Destructor
- */
-CGuardTimer::~CGuardTimer()
- {
- Cancel();
- } // CGuardTimer::~CGuardTimer
-
-/**
- * Enable the Gurad Timer
- */
-void CGuardTimer::EnableGuardTimer()
- {
- LOGSMSPROT1("CGuardTimer::EnableGuardTimer()");
- if (!IsActive())
- {
- TTime nextTimeOut;
- iClass0ReassemblyStore.GetNextGuardTimeout(nextTimeOut);
- At(nextTimeOut);
- }
- } //CGuardTimer::EnableGuardTimer
-
-/**
- * Disable the Gurad Timer
- */
-void CGuardTimer::DisableGuardTimer()
- {
- Cancel();
- }
-
-/**
- * Timer completed
- */
-void CGuardTimer::RunL()
- {
- LOGSMSPROT2("CGuardTimer::RunL [iStatus=%d]", iStatus.Int());
- iClass0ReassemblyStore.ProcessTimeoutMessageL();
- EnableGuardTimer();
- } // CGuardTimer::RunL
-
-/**
-Static factory constructor. Uses two phase
-construction and leaves nothing on the CleanupStack.
-
-@param aFs File Server handle.
-@param aSmsComm reference to MSmsComm event handler.
-
-@return A pointer to the newly created CClass0SmsReassemblyStore object.
-
-@pre A connected file server session must be passed as parameter.
-@post CClass0SmsReassemblyStore object is now fully initialised
-
-@internalComponent
-*/
-CClass0SmsReassemblyStore* CClass0SmsReassemblyStore::NewL(RFs& aFs, MSmsComm& aSmsComm)
- {
- LOGSMSPROT1("CClass0SmsReassemblyStore::NewL()");
-
- CClass0SmsReassemblyStore* self = new (ELeave) CClass0SmsReassemblyStore(aFs, aSmsComm);
- CleanupStack::PushL(self);
- self->ConstructL();
- CleanupStack::Pop(self);
-
- return self;
- }
-
-/**
- * C'tor
- */
-CClass0SmsReassemblyStore::CClass0SmsReassemblyStore(RFs& aFs, MSmsComm& aSmsComm)
- :CReassemblyStore(aFs), iSmsComm(aSmsComm), iPermanentFileStore(NULL), iPreallocatedFile(NULL),
- iGuardTimer(NULL), iInTransaction(EFalse), iDiskSpaceStatus(ESmsDiskSpaceAvailable)
- {
- }
-
-/**
- * D'tor
- */
-CClass0SmsReassemblyStore::~CClass0SmsReassemblyStore()
- {
- delete iPermanentFileStore;
- delete iPreallocatedFile;
- delete iGuardTimer;
- }
-
-/*
-It constructs permanent and pre-allocated file to store the class 0 messages.
-It creates a guard timer so that messages can be deleted if all the constituent
-PDU of a message is not received within configured time-frame.
-It also reserves 4KB disk space so that reserved space can be used to
-delete a stream from permanent file store in out-of-disk condition.
-
-@internalComponent
-*/
-void CClass0SmsReassemblyStore::ConstructL()
- {
- //Reserve Drive Space
- User::LeaveIfError(iFs.ReserveDriveSpace(KStoreDrive, 4*1024));
-
- //Read Configuration file
- ReadConfigurableClass0SmsSettingsL(iMaxClass0Msg, iMaxPDUSeg, iGuardTimeOut);
- //Create Permanent store file
- TFileName permanentStoreFileName;
- CReassemblyStoreUtility::PrivatePath(iFs, permanentStoreFileName);
- permanentStoreFileName.Append(KClass0ReassemblyStoreName);
- iPermanentFileStore = CSmsPermanentFileStore::NewL(iFs, permanentStoreFileName, KClass0ReassemblyStoreUid);
- //Create Pre-allocated file
- TFileName preAllocatedFileName;
- CReassemblyStoreUtility::PrivatePath(iFs, preAllocatedFileName);
- preAllocatedFileName.Append(KPreAllocatedFileName);
- iPreallocatedFile = CPreallocatedFile::NewL(iFs, preAllocatedFileName, iMaxClass0Msg, iMaxPDUSeg);
- //Create Gurad Timer
- iGuardTimer = CGuardTimer::NewL(*this, iGuardTimeOut);
- }
-
-/*
-It reads class 0 re-assembly store configuration information from smswap.sms.esk file.
-It reads the following information: MaxClass0Messages, NumberOfPDUSegements, GuardTimeOut.
-If any of the above element is missing it takes the default value.
-
-@internalComponent
-*/
-void CClass0SmsReassemblyStore::ReadConfigurableClass0SmsSettingsL(TInt& aMaxClass0Msg, TInt& aMaxPDUSeg, TInt& aGuardTimeOut)
- {
- LOGSMSPROT1("CClass0SmsReassemblyStore::ReadConfigurableClass0SmsSettingsL()");
-
- aMaxClass0Msg = KMaxNumberOfClass0MessagesInReassemblyStore;
- aMaxPDUSeg = KNumberOfPDUSegmentsStoredInOODCondition;
- aGuardTimeOut = KGuardTimeOut;
-
- CESockIniData* ini = NULL;
- TRAPD(ret, ini=CESockIniData::NewL(_L("smswap.sms.esk")));
- if(ret!=KErrNone)
- {
- LOGSMSPROT2("CESockIniData::NewL() returned=%d", ret);
- }
- else
- {
- CleanupStack::PushL(ini);
-
- TInt var(0);
- if(ini->FindVar(_L("ReassemblyStore"),_L("MaxClass0Messages"),var))
- {
- if (var > 0)
- {
- LOGSMSPROT2("MaxClass0Messages [%d]", var);
- aMaxClass0Msg = var;
- }
- }
-
- if(ini->FindVar(_L("ReassemblyStore"),_L("NumberOfPDUSegements"),var))
- {
- if (var > 0)
- {
- LOGSMSPROT2("MaxClass0Messages [%d]", var);
- aMaxPDUSeg = var;
- }
- }
-
- if(ini->FindVar(_L("ReassemblyStore"),_L("GuardTimeOut"),var))
- {
- if (var > 0)
- {
- LOGSMSPROT2("MaxClass0Messages [%d]", var);
- aGuardTimeOut = var;
- }
- }
-
- CleanupStack::PopAndDestroy(ini);
- }
-
- LOGSMSPROT4("CClass0SmsReassemblyStore::ReadConfigurableClass0SmsSettingsL(): aMaxClass0Msg=%d, aMaxPDUSeg=%d, aGuardTimeOut=%d",
- aMaxClass0Msg, aMaxPDUSeg, aGuardTimeOut);
- }
-
-/**
-It opens the class 0 re-assembly store.
-Then it populates the entry information (all the messages stored in re-assembly store).
-
-@internalComponent
-*/
-void CClass0SmsReassemblyStore::OpenStoreL()
- {
- LOGSMSPROT1("CClass0SmsReassemblyStore::OpenStoreL()");
- TFileName pathName;
- CReassemblyStoreUtility::PrivatePath(iFs, pathName);
- //Create the directory if it is not created.
- iFs.MkDirAll(pathName);
- // If any one file becomes corrupt or does not exist then we have to create both files.
- if (iPreallocatedFile->IsFileOK() && iPermanentFileStore->IsFileOK())
- {
- iPreallocatedFile->OpenL();
- iPermanentFileStore->OpenL();
- }
- else
- {
- iPreallocatedFile->CreateL();
- iPermanentFileStore->CreateL();
- }
- PopulateEntryArrayL(iEntryArray);
- iGuardTimer->EnableGuardTimer();
- }
-
-/**
-It closes the class 0 re-assembly store.
-
-@internalComponent
-*/
-void CClass0SmsReassemblyStore::Close()
- {
- LOGSMSPROT1("CClass0SmsReassemblyStore::CloseStore()");
- iGuardTimer->DisableGuardTimer();
- iEntryArray.Reset();
- iPreallocatedFile->Close();
- iPermanentFileStore->Close();
- }
-
-/**
-It populates the entry information stored in class 0 reassembly store.
-
-@param aEntryArray reference to entry array.
-
-@internalComponent
-*/
-void CClass0SmsReassemblyStore::PopulateEntryArrayL(CArrayFix<TReassemblyEntry>& aEntryArray)
- {
- LOGSMSPROT1("CClass0SmsReassemblyStore::PopulateEntryArrayL()");
- aEntryArray.Reset();
- //Populate Entries from Pre-allocated file.
- for (TInt count = 0; count < iPreallocatedFile->Entries().Count(); count++)
- {
- TReassemblyEntry entry;
- entry.SetReference(iPreallocatedFile->Entries()[count].Reference());
- entry.SetTotal(iPreallocatedFile->Entries()[count].Total());
- entry.SetCount(iPreallocatedFile->Entries()[count].Count()+iPreallocatedFile->Entries()[count].NumberOfPDUsForwardToClient());
- entry.SetLogServerId(iPreallocatedFile->Entries()[count].LogServerId());
-
- // Check that descriptor2 (sms address )is not corrupted
- TPtrC ptr = iPreallocatedFile->Entries()[count].Description2();
-
- if (ptr.Length() <= CSmsAddress::KSmsAddressMaxAddressLength)
- {
- entry.SetDescription2(iPreallocatedFile->Entries()[count].Description2());
- }
-
- entry.SetPduType(iPreallocatedFile->Entries()[count].PduType());
- entry.SetStorage(iPreallocatedFile->Entries()[count].Storage());
- entry.SetTime(iPreallocatedFile->Entries()[count].Time());
- entry.SetPassedToClient(iPreallocatedFile->Entries()[count].PassedToClient());
- aEntryArray.AppendL(entry);
- }
-
- /*
- Then populate the entries from permanent store file. It is needed
- because permanent store file might contain few mesages.
- But before populating the entry information it is needed to cleanup
- the entries in permanent store file. It is needed to ensure that permanent file
- clean itself with pre-allocated file. There migth be a scenario where
- user has deleted a message but the corresponding message has not been
- deleted from permanent store file due to out-of-disk condition.
- And also at the time of forwarding an incomplete message a forwarded
- message has not been deleted due to above reason. But the entry/PDU is
- invalid because it is no more in the pre-allocated file which
- contains master header info.
- */
- TInt ret = CleanReassemblyEntries();
-
- if (ret == KErrNone)
- {
- /*
- In this case permanent store file contains correct information.
- So populate Entry information from Permanent store file.
- In this case only count information needs to be updated.
- */
- TInt permanentFileStoreIndex;
- for (TInt i=0; i<aEntryArray.Count(); i++)
- {
- permanentFileStoreIndex=KErrNotFound;
- iPermanentFileStore->MatchEntryToExistingMessage(aEntryArray[i], permanentFileStoreIndex);
- if (permanentFileStoreIndex!=KErrNotFound)
- {
- aEntryArray[i].SetCount(aEntryArray[i].Count() + iPermanentFileStore->Entries()[permanentFileStoreIndex].Count());
- if (aEntryArray[i].Count() > aEntryArray[i].Total())
- {
- aEntryArray[i].SetCount(aEntryArray[i].Total());
- }
- }
- }
- }
- else if (ret == KErrDiskFull)
- {
- LOGSMSPROT1("CleanReassemblyEntries() returns KErrDiskFull");
- /*
- In this case permanent store file contains incorrect information.
- For example forwarded message might be still stored in this store.
- Because it has not been deleted due to out-of-disk condition.
- So be careful at the time of updating the count information
- about the message.
- */
- TInt permanentFileStoreIndex;
- for (TInt i=0; i<aEntryArray.Count(); i++)
- {
- permanentFileStoreIndex=KErrNotFound;
- iPermanentFileStore->MatchEntryToExistingMessage(aEntryArray[i], permanentFileStoreIndex);
- if (permanentFileStoreIndex!=KErrNotFound)
- {
- TSmsPreAllocatedFileStoreReassemblyEntry entry = iPreallocatedFile->Entries()[i];
- if (entry.NumberOfPDUsForwardToClient() > 0)
- {
- //Internalize the entries.
- CSmsBuffer* buffer = CSmsBuffer::NewL();
- CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer);
- CleanupStack::PushL(smsMessage);
-
- CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
- CleanupStack::PushL(indexArray);
- CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
- CleanupStack::PushL(smsArray);
- //Internalize to check whether removed PDUs still stored in Permanent store file.
- iPermanentFileStore->InternalizeEntryL(permanentFileStoreIndex, *smsMessage, *indexArray, *smsArray);
- TInt noOfForwardedEntries=0;
- for (TInt j=0; j<indexArray->Count() ;j++)
- {
- TUint8 bitMapIndex = (indexArray->At(j)-1)/8;
- TUint8 bitPos = (indexArray->At(j)-1)%8;
- TUint8 bitMap;
- entry.GetBitMap(bitMapIndex, bitMap);
- TUint8 tmpBitMap = 1;
- tmpBitMap <<= bitPos;
- if (tmpBitMap == (bitMap & tmpBitMap))
- {
- noOfForwardedEntries++;
- }
- }
- TInt count = iPermanentFileStore->Entries()[permanentFileStoreIndex].Count() - noOfForwardedEntries;
- aEntryArray[i].SetCount(aEntryArray[i].Count() + count);
-
- CleanupStack::PopAndDestroy(3, smsMessage); // smsMessage, indexArray, smsArray
- }
- else
- {
- aEntryArray[i].SetCount(aEntryArray[i].Count() + iPermanentFileStore->Entries()[permanentFileStoreIndex].Count());
- }
- }
- }
- }
- else
- {
- User::Leave(ret);
- }
- }
-
-/**
-It sets the disk space status.
-If disk space is full, then class 0 re-assembly store stores the incoming message in
-pre-allocated file. Otherwise it stores the message in permanent store file.
-*/
-void CClass0SmsReassemblyStore::SetDiskSpaceState(TSmsDiskSpaceMonitorStatus aDiskSpaceStatus)
- {
- LOGSMSPROT1("CClass0SmsReassemblyStore::SetDiskSpaceState()");
- iDiskSpaceStatus = aDiskSpaceStatus;
- }
-
-/*
-It adds the new message in class 0 reassembly store.
-It first tries to add the message in permanent store file. If it is
-successful, then it adds the entry information in pre-allocated file.
-Because pre-allocated file contains master header entry information.
-Otherwise (if disk space is full), it adds the message in pre-allocated file.
-
-@param aSmsMessage reference to sms message to be added.
-@param aGsmSms reference to GsmSms object to be added.
-
-@internalComponent
-*/
-void CClass0SmsReassemblyStore::AddNewMessageL(CSmsMessage& aSmsMessage,const TGsmSms& aGsmSms)
- {
- LOGSMSPROT1("CClass0SmsReassemblyStore::AddNewMessageL");
-
- // Add entry in permanent store file
- TInt index;
- TInt ret = KErrNone;
-
- if (iDiskSpaceStatus == ESmsDiskSpaceFull)
- {
- ret = KErrDiskFull;
- }
- else
- {
- TRAP(ret, iPermanentFileStore->AddNewMessageL(index, aSmsMessage, aGsmSms));
- }
-
- if (ret == KErrNone)
- {
- // Add a new entry in pre-allocated file
- TSmsPreAllocatedFileStoreReassemblyEntry tmpEntry;
- //Fill-up entry information...
- CReassemblyStoreUtility::PopulateEntry(tmpEntry, aSmsMessage, 1);
-
- //The properties below need to be set only once when a PDU of a new message arrives.
- tmpEntry.SetStatus((RMobileSmsStore::TMobileSmsStoreStatus)aSmsMessage.Status());
- tmpEntry.SetUTCOffset(aSmsMessage.UTCOffset());
- tmpEntry.SetDecodedOnSIM(aSmsMessage.DecodedOnSim());
- tmpEntry.SetForwardToClient(aSmsMessage.ForwardToClient());
- //Set KErrNotFound because message corresponding to
- //this entry is not in this pr-allocated file.
- tmpEntry.SetPreAllocatedStorageId(KErrNotFound);
- //Has to set 0 because PDU is stored in Permanent store file instead of pre-allocated file.
- tmpEntry.SetCount(0);
-
- iPreallocatedFile->AddEntryL(tmpEntry);
- }
- else if (ret == KErrDiskFull)
- {
- // Add the new message in pre-allocated file
- iPreallocatedFile->AddNewMessageL(index, aSmsMessage, aGsmSms);
- }
- else
- {
- User::Leave(ret);
- }
- }
-
-/*
-It updates the existing message in class 0 re-assembly store.
-
-@param aSmsMessage reference to sms message to be updated.
-@param aGsmSms reference to GsmSms object to be added.
-@param aDuplicateMsgRef boolean value (output) indicates whether the added PDU is a duplicate or not.
-@param aDuplicateSlot boolean value (output) indicates whether the added PDU is a duplicate enumerated PDU.
-
-@internalComponent
-*/
-void CClass0SmsReassemblyStore::UpdateExistingMessageL(CSmsMessage& aSmsMessage, const TGsmSms& aGsmSms, TBool& aDuplicateMsgRef, TBool& aDuplicateSlot)
- {
- LOGSMSPROT1("CClass0SmsReassemblyStore::UpdateExistingMessageL()");
-
- aDuplicateMsgRef = EFalse;
- aDuplicateSlot = EFalse;
-
- CSmsBuffer* buffer = CSmsBuffer::NewL();
- CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer);
- CleanupStack::PushL(smsMessage);
-
- CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
- CleanupStack::PushL(indexArray);
- CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
- CleanupStack::PushL(smsArray);
-
- //Internalize stored message in permanent store file
- TReassemblyEntry entry;
- CReassemblyStoreUtility::PopulateEntry(entry, aSmsMessage, 1);
- TInt permanentStoreIndex;
- iPermanentFileStore->MatchEntryToExistingMessage(entry, permanentStoreIndex);
- if (permanentStoreIndex!=KErrNotFound)
- {
- iPermanentFileStore->InternalizeEntryL(permanentStoreIndex, *smsMessage, *indexArray, *smsArray);
- }
-
- //Internalize stored message in pre-allocated file
- TInt preAllocatedFileIndex;
- iPreallocatedFile->MatchEntryToExistingMessage(entry, preAllocatedFileIndex);
- if (preAllocatedFileIndex!=KErrNotFound)
- {
- iPreallocatedFile->InternalizeEntryL(preAllocatedFileIndex, *smsMessage, *indexArray, *smsArray);
- }
- else
- {
- //This condition should never arise
- User::Leave(KErrNotFound);
- }
-
- //
- // Check if this is a duplicated enumerated PDU (e.g. on the SIM or phone memory)
- // or a duplicated PDU (e.g. in the Reassembly Store)...
- //
- TInt concatPDUIndex = aSmsMessage.SmsPDU().ConcatenatedMessagePDUIndex();
-
- if (smsMessage->Storage() == CSmsMessage::ESmsSIMStorage ||
- smsMessage->Storage() == CSmsMessage::ESmsCombinedStorage)
- {
- //
- // In most cases this PDU is being enumerated, but not always. It is
- // possible for the PDU to be stored on the SIM first before it is
- // received.
- //
- const TGsmSmsSlotEntry& newSlot = aSmsMessage.iSlotArray[0];
- TInt slotArrayCount = smsMessage->iSlotArray.Count();
-
- for (TInt slotNum = 0; slotNum < slotArrayCount; slotNum++ )
- {
- const TGsmSmsSlotEntry& slot = smsMessage->iSlotArray[slotNum];
-
- if (slot.iIndex == newSlot.iIndex && slot.iStore == newSlot.iStore)
- {
- LOGSMSPROT1("CSmsReassemblyStore::UpdateExistingMessageL(): Duplicate enumerated PDU.");
-
- // It is a duplicate that was already stored on the SIM...
- aDuplicateSlot = ETrue;
- break;
- }
- }
- }
-
- TInt indexArrayCount = indexArray->Count();
-
- for (TInt index = 0; index < indexArrayCount; index++ )
- {
- if (indexArray->At(index) == concatPDUIndex)
- {
- LOGSMSPROT1("CSmsReassemblyStore::UpdateExistingMessageL(): Duplicate concatenated PDU.");
-
- // The PDU is already stored in the reassembly store.
- aDuplicateMsgRef = ETrue;
- break;
- }
- }
-
- //Check whether this PDU is part of forwarded PDU.
- TSmsPreAllocatedFileStoreReassemblyEntry preAllocatedFileEntry = iPreallocatedFile->Entries()[preAllocatedFileIndex];
- if (preAllocatedFileEntry.NumberOfPDUsForwardToClient() > 0)
- {
- TUint8 bitMapIndex = (concatPDUIndex-1)/8;
- TUint8 bitPos = (concatPDUIndex-1)%8;
- TUint8 bitMap;
- preAllocatedFileEntry.GetBitMap(bitMapIndex, bitMap);
- TUint8 tmpBitMap = 1;
- tmpBitMap <<= bitPos;
- if (tmpBitMap == (bitMap & tmpBitMap))
- {
- aDuplicateMsgRef = ETrue;
- }
- }
-
- if (aDuplicateMsgRef || aDuplicateSlot)
- {
- CleanupStack::PopAndDestroy(3, smsMessage); // smsMessage, smsArray, indexArray
- return;
- }
-
- //
- // If the PDU is stored then add the slot information...
- //
- if (aSmsMessage.Storage() == CSmsMessage::ESmsSIMStorage ||
- aSmsMessage.Storage() == CSmsMessage::ESmsCombinedStorage)
- {
- smsMessage->AddSlotL(aSmsMessage.iSlotArray[0]);
- }
-
- //
- // If the PDU is Unsent or Unread, then store that information...
- //
- NMobileSmsStore::TMobileSmsStoreStatus status = aSmsMessage.Status();
-
- if (status == NMobileSmsStore::EStoredMessageUnsent ||
- status == NMobileSmsStore::EStoredMessageUnread)
- {
- smsMessage->SetStatus(status);
- }
-
- /*
- Below logic is written in keeping view of different scenarios that might occur here:
- (1) Previous PDUs are in Permanent store file, this PDU arrives in out-of-disk condition (so will be stored in Pre-allocated file).
- (2) Previous PDUs are in Pre-allocated file (means PDU arrives in out-of-disk condition), this PDU arrives in normal condition.
- (3) Previous PDUs are in Permanent store file, this PDU also arrives in normal condition.
- (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.
- */
-
- //Always first try to store the message in permanent store file.
- //In case of out-of-disk condition store the message in pre-allocated file
- TInt ret = KErrNone;
- if (iDiskSpaceStatus == ESmsDiskSpaceFull)
- {
- ret = KErrDiskFull;
- }
- else
- {
- if (permanentStoreIndex==KErrNotFound)
- {
- // See condition (2)
- TInt tmpIndex;
- TRAP(ret, iPermanentFileStore->AddNewMessageL(tmpIndex, aSmsMessage, aGsmSms));
- }
- else
- {
- CSmsBuffer* tmpBuffer = CSmsBuffer::NewL();
- CSmsMessage* tmpSmsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, tmpBuffer);
- CleanupStack::PushL(tmpSmsMessage);
-
- indexArray->Reset();
- smsArray->Reset();
- iPermanentFileStore->InternalizeEntryL(permanentStoreIndex, *tmpSmsMessage, *indexArray, *smsArray);
- /*
- Check & remove those PDU from permanent store file which has already been
- forwarded to client. Forwarded PDU might still remain in permanent store
- file if it is deleted at the time of out-of-disk condition.
- */
- if (preAllocatedFileEntry.NumberOfPDUsForwardToClient()>0)
- {
- for (TInt j=indexArray->Count(); j>0 ;j--)
- {
- TUint8 bitMapIndex = (indexArray->At(j-1)-1)/8;
- TUint8 bitPos = (indexArray->At(j-1)-1)%8;
- TUint8 bitMap;
- preAllocatedFileEntry.GetBitMap(bitMapIndex, bitMap);
- TUint8 tmpBitMap = 1;
- tmpBitMap <<= bitPos;
- if (tmpBitMap == (bitMap & tmpBitMap))
- {
- indexArray->Delete(j-1);
- smsArray->Delete(j-1);
- }
- }
- }
-
- indexArray->AppendL(concatPDUIndex);
- smsArray->AppendL(aGsmSms);
-
- TRAP(ret, iPermanentFileStore->UpdateExistingMessageL(permanentStoreIndex, *smsMessage, *indexArray, *smsArray));
-
- CleanupStack::PopAndDestroy(1); //tmpSmsMessage
- }
- }
-
- if (ret == KErrDiskFull)
- {
- iPreallocatedFile->UpdateExistingMessageL(preAllocatedFileIndex, aSmsMessage, concatPDUIndex, aGsmSms);
- }
- else if (ret!=KErrNone)
- {
- User::Leave(ret);
- }
-
- CleanupStack::PopAndDestroy(3, smsMessage); // smsMessage, indexArray, smsArray
- }
-
-/*
-It retrieves class 0 message from re-assembly store.
-The message which match the passed entry information is returned from this function.
-
-@param aEntry reference to entry information.
-@param aSmsMessage reference to returned sms message.
-
-@internalComponent
-*/
-void CClass0SmsReassemblyStore::RetrieveMessageL(const TReassemblyEntry& aEntry, CSmsMessage& aSmsMessage)
- {
- CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
- CleanupStack::PushL(indexArray);
- CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
- CleanupStack::PushL(smsArray);
-
- GetSmsEntriesL(aEntry, aSmsMessage, *indexArray, *smsArray);
-
- //There is no need to decode a single segment message
- if (aEntry.Total()>1)
- {
- if (smsArray->Count() == aEntry.Total())
- {
- aSmsMessage.DecodeMessagePDUsL(*smsArray);
- }
- }
- CleanupStack::PopAndDestroy(2, indexArray); //smsArray, indexArray
- }
-
-/*
-It deletes the entry from re-assembly store.
-
-@param aEntry reference to entry information.
-
-@internalComponent
-*/
-void CClass0SmsReassemblyStore::DeleteEntryL(const TReassemblyEntry& aEntry)
- {
- TInt index;
- iPreallocatedFile->MatchEntryToExistingMessage(aEntry, index);
- if (index == KErrNotFound)
- {
- //This condition should never arise
- User::Leave(KErrNotFound);
- }
- iPreallocatedFile->DeleteEntryL(index);
- iPermanentFileStore->MatchEntryToExistingMessage(aEntry, index);
- if (index != KErrNotFound)
- {
- TRAP_IGNORE(iPermanentFileStore->DeleteEntryL(index));
- }
- }
-
-/*
-It updates the log server id of the passed entry (message).
-
-@param aEntry reference to entry information.
-@param aLogId log id of the message to be updated.
-
-@internalComponent
-*/
-void CClass0SmsReassemblyStore::UpdateLogServerIdL(const TReassemblyEntry& aEntry, TLogId aLogServerId)
- {
- TInt index;
- iPreallocatedFile->MatchEntryToExistingMessage(aEntry, index);
- if (index == KErrNotFound)
- {
- //This condition should never arise
- User::Leave(KErrNotFound);
- }
- iPreallocatedFile->UpdateLogServerIdL(index, aLogServerId);
- }
-
-/*
-It sets the message passed to client or not. The message, which match the
-passed entry information, its passed to client value is set.
-
-@param aEntry reference to entry information.
-@param aBool boolean value indicating whether message is passed or not.
-
-@internalComponent
-*/
-void CClass0SmsReassemblyStore::SetPassedToClientL(const TReassemblyEntry& aEntry, TBool aBool)
- {
- TInt index;
- iPreallocatedFile->MatchEntryToExistingMessage(aEntry, index);
- if (index == KErrNotFound)
- {
- //This condition should never arise
- User::Leave(KErrNotFound);
- }
- iPreallocatedFile->SetPassedToClientL(index, aBool);
- }
-
-/**
-It forwards the complete class 0 messages to client.
-It checks whether the received object is complete or not.
-If it is complete, then it forwards the complete message to client.
-Otherwise it forms the message & forward the message to client.
-In this it might be possible to forward multiple incomplete message.
-
-@param aSmsComm a reference to aSmsComm object which implemented the events.
-
-@param aSmsMessage a reference to sms message object. This sms message must be class 0 messages.
-
-@param aOriginalSmsAddr pointer to the address of the sender of a previously sent
-
-@param aOriginalSmsMessage pointer to a message previously sent matched to the received
- one (e.g. status report). Null if not matched.
-
-@param aDes user data for the deliver report acknowledging this message to the SC.
- Filled in by the observer.
-
-@internalComponent
-*/
-void CClass0SmsReassemblyStore::ForwardCompleteClass0SmsMessagesL(MSmsComm& aSmsComm, const CSmsMessage& aSmsMessage,const TSmsAddr* aOriginalSmsAddr,const CSmsMessage* aOriginalSmsMessage,TDes& aDes)
- {
- TBool passedToClient=ETrue;
-
- if (aSmsMessage.IsComplete())
- {
- //Message is complete so forward it.
- TInt ret = aSmsComm.ProcessMessageL(aSmsMessage, aOriginalSmsAddr, aOriginalSmsMessage, aDes);
- if (ret!=KErrNone)
- {
- passedToClient = EFalse;
- }
- }
- else
- {
- /*
- Message is not complete, but re-assembly store contains other constituent PDU
- of the message which makes the message complete.
-
- In case of class 0 messages, it is possible to forward the incomplete messages. So after forwarding
- the incomplete message, if we receive other constituent PDU of that message then in that case we
- might receive all the constituent PDU of that message but aSmsMesssage will contain partial complete message.
- */
- TReassemblyEntry entry;
- CReassemblyStoreUtility::PopulateEntry(entry, aSmsMessage, 1);
-
- CSmsBuffer* buffer = CSmsBuffer::NewL();
- CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer );
- CleanupStack::PushL( smsMessage );
-
- CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
- CleanupStack::PushL(indexArray);
- CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
- CleanupStack::PushL(smsArray);
-
- GetSmsEntriesL(entry, *smsMessage, *indexArray, *smsArray);
- SortPDUsL(*indexArray, *smsArray);
-
- CArrayFixFlat<TGsmSms>* tmpSmsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
- CleanupStack::PushL(tmpSmsArray);
-
- //Form the sequence of incomplete message & forward it to client.
- TInt startSeqIndex(0), endSeqIndex(0);
- TInt i;
- do
- {
- i = startSeqIndex;
- for (; i < indexArray->Count() - 1; i++)
- {
- if (indexArray->At(i) + 1 != indexArray->At(i+1))
- {
- endSeqIndex = i;
- break;
- }
- }
-
- if (i == (indexArray->Count() - 1))
- {
- endSeqIndex = i;
- }
-
- tmpSmsArray->Reset();
- for (TInt j = startSeqIndex; j <= endSeqIndex; j++)
- {
- tmpSmsArray->AppendL(smsArray->At(j));
- }
-
- if (tmpSmsArray->Count() == entry.Total())
- {
- smsMessage->DecodeMessagePDUsL(*tmpSmsArray);
- }
- else
- {
- //Build the partial complete message.
- if (endSeqIndex == (indexArray->Count() - 1))
- {
- smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, ETrue);
- }
- else
- {
- smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, EFalse);
- }
- }
-
- //Forward the partial complete message to client.
- TInt ret=KErrNone;
- TRAP(ret, aSmsComm.ProcessMessageL(*smsMessage, aOriginalSmsAddr, aOriginalSmsMessage, aDes));
- if (ret != KErrNone)
- {
- passedToClient = EFalse;
- }
- startSeqIndex = endSeqIndex + 1;
- endSeqIndex = startSeqIndex;
- }
- while (startSeqIndex < indexArray->Count());
-
- CleanupStack::PopAndDestroy(4); //tmpSmsArray, indexArray, smsArray, smsMessage
- }
-
- if(passedToClient)
- {
- SetMessagePassedToClientL(aSmsMessage);
- }
-
- //If the latest segement exceeds the limitation, then we can't wait till ack.
- //So call ProcessMessageIfExceedLimitationL() function & delete the oldest message.
- if (IsExceedLimitation())
- {
- ProcessMessageIfExceedLimitationL(aSmsComm);
- }
- }
-
-/**
-It frees the space by forwarding the class 0 message if class 0 re-assembly store
-exceeds limitation (max class 0 message, max reserved pdu segment).
-
-@param aSmsComm a reference to aSmsComm object which implemented the events.
-
-@internalComponent
-*/
-void CClass0SmsReassemblyStore::ProcessMessageIfExceedLimitationL(MSmsComm& aSmsComm)
- {
- //Add Comment
- TInt class0MsgCount = iEntryArray.Count();
- TInt noOfMsgStoredInPreAllocatedFile = iPreallocatedFile->NumberOfPDUStored();
- if ((class0MsgCount > iMaxClass0Msg)
- || (noOfMsgStoredInPreAllocatedFile >= iMaxPDUSeg))
- {
- CSmsBuffer* buffer = CSmsBuffer::NewL();
- CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer );
- CleanupStack::PushL( smsMessage );
-
- CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
- CleanupStack::PushL(indexArray);
- CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
- CleanupStack::PushL(smsArray);
-
- //Add Comment
- TInt index;
- if (class0MsgCount > iMaxClass0Msg)
- {
- index = GetIndexOfOldestMessage();
- }
- else
- {
- index = GetIndexOfOldestMessageFromReservedFileL();
- }
-
- TReassemblyEntry entry = iEntryArray[index];
-
- GetSmsEntriesL(entry, *smsMessage, *indexArray, *smsArray);
-
- SortPDUsL(*indexArray, *smsArray);
-
- CArrayFixFlat<TGsmSms>* tmpSmsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
- CleanupStack::PushL(tmpSmsArray);
-
- //Form the message & forward it to client.
- TInt startSeqIndex(0), endSeqIndex(0);
- TInt i;
- do
- {
- i = startSeqIndex;
- for (; i < indexArray->Count() - 1; i++)
- {
- if (indexArray->At(i) + 1 != indexArray->At(i+1))
- {
- endSeqIndex = i;
- break;
- }
- }
- if (i == (indexArray->Count() - 1))
- {
- endSeqIndex = i;
- }
- tmpSmsArray->Reset();
-
- for (TInt j = startSeqIndex; j <= endSeqIndex; j++)
- {
- tmpSmsArray->AppendL(smsArray->At(j));
- }
-
- if (entry.IsComplete())
- {
- if (tmpSmsArray->Count() == entry.Total())
- {
- smsMessage->DecodeMessagePDUsL(*tmpSmsArray);
- }
- else
- {
- //Build the partial complete message.
- if (endSeqIndex == (indexArray->Count() - 1))
- {
- smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, ETrue);
- }
- else
- {
- smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, EFalse);
- }
- }
- }
- else
- {
- //Build the partial complete message.
- smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, EFalse);
- }
- //Forward the partial complete message to client.
- TBuf16<CSmsPDUProcessor::ESmsMaxDeliverReportBufferSize> buffer;
- TRAP_IGNORE(aSmsComm.ProcessMessageL(*smsMessage, NULL, NULL, buffer));
-
- /*
- Can't do much. So free the reserved space & also stored the information
- related to forwarded message. If the message is complete then delete
- the complete message (see the condition after the while loop)rather
- than freeing the memory. No need to store the complete messages forwaded
- info.
- */
- if ((noOfMsgStoredInPreAllocatedFile > iMaxPDUSeg) && (!entry.IsComplete()))
- {
- SetIncompleteMessageForwardedToClientL(*smsMessage);
- }
- startSeqIndex = endSeqIndex + 1;
- endSeqIndex = startSeqIndex;
- }
- while (startSeqIndex < indexArray->Count());
- //Can't do much. So removed the oldest message.
- if ((class0MsgCount > iMaxClass0Msg) ||
- ((noOfMsgStoredInPreAllocatedFile > iMaxPDUSeg) && (entry.IsComplete())))
- {
- DeleteMessageL(*smsMessage, EFalse);
- }
- CleanupStack::PopAndDestroy(4); //tmpSmsArray, indexArray, smsArray, smsMessage
- }
- }
-
-/**
-Guard timer calls this function when timer expires.
-It goes through all the messages stored in re-assembly store & forwards those message
-whose time has expired.
-It is also called when a new observer is added or a PDU has been received and successfully
-processed. It is also called from ProcessCompleteClass0SmsMessagesL.
-
-@internalComponent
-*/
-void CClass0SmsReassemblyStore::ProcessTimeoutMessageL()
- {
- LOGSMSPROT1("CClass0SmsReassemblyStore::ProcessTimeoutMessageL()");
- TBool passedToClient=ETrue;
- TInt count=iEntryArray.Count();
-
- CSmsBuffer* buffer = CSmsBuffer::NewL();
- CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer );
- CleanupStack::PushL( smsMessage );
-
- CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
- CleanupStack::PushL(indexArray);
- CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
- CleanupStack::PushL(smsArray);
-
- CArrayFixFlat<TGsmSms>* tmpSmsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
- CleanupStack::PushL(tmpSmsArray);
-
- TTime time;
- time.UniversalTime();
-
- TTimeIntervalSeconds timeOutInSecs = iGuardTimeOut*3600;
-
- for (TInt k=count-1; k>=0; k--)
- {
- if (!iEntryArray[k].PassedToClient())
- {
- TTimeIntervalSeconds diffInSecs;
- time.SecondsFrom(iEntryArray[k].Time(), diffInSecs);
- indexArray->Reset();
- smsArray->Reset();
- if (diffInSecs >= timeOutInSecs)
- {
- GetSmsEntriesL(iEntryArray[k], *smsMessage, *indexArray, *smsArray);
- SortPDUsL(*indexArray, *smsArray);
-
- //Form the message & forward it to client.
- TInt startSeqIndex(0), endSeqIndex(0);
- TInt i;
- do
- {
- i = startSeqIndex;
- for (; i < indexArray->Count() - 1; i++)
- {
- if (indexArray->At(i) + 1 != indexArray->At(i+1))
- {
- endSeqIndex = i;
- break;
- }
- }
- if (i == (indexArray->Count() - 1))
- {
- endSeqIndex = i;
- }
- tmpSmsArray->Reset();
- for (TInt j = startSeqIndex; j <= endSeqIndex; j++)
- {
- tmpSmsArray->AppendL(smsArray->At(j));
- }
-
- if (iEntryArray[k].IsComplete())
- {
- if (tmpSmsArray->Count() == iEntryArray[k].Total())
- {
- smsMessage->DecodeMessagePDUsL(*tmpSmsArray);
- }
- else
- {
- //Build the partial complete message.
- if (endSeqIndex == (indexArray->Count() - 1))
- {
- smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, ETrue);
- }
- else
- {
- smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, EFalse);
- }
- }
- }
- else
- {
- //Build the partial complete message.
- if (endSeqIndex == (indexArray->Count() - 1))
- {
- smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, ETrue);
- }
- else
- {
- smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, EFalse);
- }
- }
-
- //Forward the partial complete message to client.
- TInt ret=KErrNone;
- TBuf16<CSmsPDUProcessor::ESmsMaxDeliverReportBufferSize> buffer;
- ret = iSmsComm.ProcessMessageL(*smsMessage, NULL, NULL, buffer);
- if (ret != KErrNone)
- {
- passedToClient = EFalse;
- }
-
- startSeqIndex = endSeqIndex + 1;
- endSeqIndex = startSeqIndex;
- }
- while (startSeqIndex < indexArray->Count());
-
- if(passedToClient)
- {
- SetMessagePassedToClientL(*smsMessage);
- }
- } //diffInSecs >= timeOutInSecs
- } //!iEntryArray[k].PassedToClient()
- } //For k loop
- CleanupStack::PopAndDestroy(4); //tmpSmsArray, indexArray, smsArray, smsMessage
- }
-
-/**
-It sets the bit-map of forwarded incomplete message to client.
-It frees up the memory by removing the forwarded PDUs.
-
-@param aSmsMessage a reference to forwaded incomplete class 0 sms message object.
-
-@internalComponent
-*/
-void CClass0SmsReassemblyStore::SetIncompleteMessageForwardedToClientL(const CSmsMessage& aSmsMessage)
- {
- LOGSMSPROT1("CClass0SmsReassemblyStore::SetIncompleteMessageForwardedToClientL()");
- TInt index = KErrNotFound;
-
- if (aSmsMessage.IsComplete())
- {
- LOGSMSPROT1("This function must be called when message is incomplete");
- User::Leave(KErrArgument);
- }
-
- if (FindMessageL(aSmsMessage, EFalse, index))
- {
- CIncompleteClass0MessageInfo& incompleteClass0MsgInfo = (CIncompleteClass0MessageInfo &) aSmsMessage.GetOperationsForNonIEL(ESmsIncompleteClass0MessageParameter);
- // Retrieve incomplete class 0 message information & process
- TInt startPos, endPos;
- TBool isLastMessage;
- incompleteClass0MsgInfo.GetIncompleteMessageInfoL(startPos, endPos, isLastMessage);
-
- const TReassemblyEntry& entry = iEntryArray[index];
-
- //Remove the forwarded PDU entries from pre-allocated file
- TInt preAllocatedFileIndex=KErrNotFound;
- iPreallocatedFile->MatchEntryToExistingMessage(entry, preAllocatedFileIndex);
- if (preAllocatedFileIndex!=KErrNotFound)
- {
- BeginTransactionLC();
- iPreallocatedFile->RemovePDUsL(preAllocatedFileIndex, startPos, endPos);
- iPreallocatedFile->StoreForwardedPDUsInfoL(preAllocatedFileIndex, startPos, endPos);
- CommitTransactionL();
- }
- else
- {
- //This situation should never arise
- User::Leave(KErrNotFound);
- }
-
- //Remove the forwarded PDU entries from permanent store file
- TInt permanentStoreIndex=KErrNotFound;
- iPermanentFileStore->MatchEntryToExistingMessage(entry, permanentStoreIndex);
- if (permanentStoreIndex!=KErrNotFound)
- {
- TRAP_IGNORE(BeginTransactionLC();
- iPermanentFileStore->RemovePDUsL(permanentStoreIndex, startPos, endPos);
- CommitTransactionL(););
- }
- }
- }
-
-/**
-This function is needed to ensure that permanent file
-clean itself with pre-allocated file.
-There migth be a scenario where user has deleted a message
-but the corresponding message has not been deleted from permanent store file
-due to out-of-disk condition. But the entry is invalid because
-it is no more in the pre-allocated file which contains master header info.
-
-@return the error code.
-
-@internalComponent
-*/
-TInt CClass0SmsReassemblyStore::CleanReassemblyEntries()
- {
- LOGSMSPROT1("CleanReassemblyEntries");
- const CArrayFix<TSmsPreAllocatedFileStoreReassemblyEntry>& preAllocatedFileEntryArray = iPreallocatedFile->Entries();
- TInt ret=KErrNone;
- TRAP(ret, BeginTransactionLC();
- iPermanentFileStore->CleanupEntriesL(preAllocatedFileEntryArray);
- CommitTransactionL(););
-
- if (ret == KErrDiskFull)
- {
- LOGSMSPROT1("CleanupEntriesL returns KErrDiskFull");
- /*
- Get access to reserve memory, call again to clean the entries with compact.
- Compact needs to be called at this instance because permanent store
- will use reserve disk space to delete, but after deletion reserve
- disk space will be freed. So compact will make sure that reserve disk
- space is not used after compaction.
- */
- iFs.GetReserveAccess(KStoreDrive);
- TRAP(ret, BeginTransactionLC();
- iPermanentFileStore->CleanupEntriesWithCompactL(preAllocatedFileEntryArray);
- CommitTransactionL(););
- LOGSMSPROT2("CleanupEntriesWithCompactL returns %d", ret);
- iFs.ReleaseReserveAccess(KStoreDrive);
- }
- return ret;
- }
-
-/**
-It returns the SMS entries (sms messages, sms pdu arrays & the corresponding index array)
-from its permanent store & pre-allocated file.
-
-@param aEntry reference to entry information. The message which match this entry information
- is returned to caller of the function.
-@param aSmsMessage a reference to class 0 sms message object.
-@param aIndexArray a reference to the array of pdu index.
-@param aSmsArray a reference to the array of pdu.
-
-@internalComponent
-*/
-void CClass0SmsReassemblyStore::GetSmsEntriesL(const TReassemblyEntry& aEntry, CSmsMessage& aSmsMessage, CArrayFix<TInt>& aIndexArray, CArrayFix<TGsmSms>& aSmsArray)
- {
- LOGSMSPROT1("CClass0SmsReassemblyStore::GetSmsEntriesL()");
- TInt permanentStoreIndex=KErrNotFound;
- iPermanentFileStore->MatchEntryToExistingMessage(aEntry, permanentStoreIndex);
- if (permanentStoreIndex!=KErrNotFound)
- {
- iPermanentFileStore->InternalizeEntryL(permanentStoreIndex, aSmsMessage, aIndexArray, aSmsArray);
- }
- else
- {
- LOGSMSPROT1("No PDUs in Permanent store file");
- }
-
- TInt preAllocatedFileIndex=KErrNotFound;
- iPreallocatedFile->MatchEntryToExistingMessage(aEntry, preAllocatedFileIndex);
- if (preAllocatedFileIndex!=KErrNotFound)
- {
- iPreallocatedFile->InternalizeEntryL(preAllocatedFileIndex, aSmsMessage, aIndexArray, aSmsArray);
-
- //Filter forwarde PDU here..this condition might arise if the PDU
- //could not be deleted at the time of OOD condition from permanent store file.
- TSmsPreAllocatedFileStoreReassemblyEntry preAllocatedFileEntry = iPreallocatedFile->Entries()[preAllocatedFileIndex];
- if (preAllocatedFileEntry.NumberOfPDUsForwardToClient() > 0)
- {
- for (TInt j=aIndexArray.Count(); j>0 ;j--)
- {
- TUint8 bitMapIndex = (aIndexArray.At(j-1)-1)/8;
- TUint8 bitPos = (aIndexArray.At(j-1)-1)%8;
- TUint8 bitMap;
- preAllocatedFileEntry.GetBitMap(bitMapIndex, bitMap);
- TUint8 tmpBitMap = 1;
- tmpBitMap <<= bitPos;
- if (tmpBitMap == (bitMap & tmpBitMap))
- {
- aIndexArray.Delete(j-1);
- aSmsArray.Delete(j-1);
- }
- }
- }
-
- if (permanentStoreIndex==KErrNotFound)
- {
- //In this scenario a CSmsMessage object has to be created from the existing PDU in
- //pre-allocated file & then serialized into aSmsMessage.
- LOGSMSPROT2("Number of PDUs in Pre-allocated file %d", aIndexArray.Count());
- if (aIndexArray.Count() > 0)
- {
- CSmsBuffer* smsBuffer = CSmsBuffer::NewL();
- CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, aSmsArray.At(0), smsBuffer, EFalse, ETrue);
- CleanupStack::PushL(smsMessage);
-
- //Update sms messages's properties.
- smsMessage->SetStorage(aSmsMessage.Storage());
- smsMessage->SetStatus((NMobileSmsStore::TMobileSmsStoreStatus)aSmsMessage.Status());
- smsMessage->SetLogServerId(aSmsMessage.LogServerId());
- smsMessage->SetTime(aSmsMessage.Time());
- smsMessage->SetUTCOffset(aSmsMessage.UTCOffset());
- smsMessage->SetDecodedOnSIM(aSmsMessage.DecodedOnSim());
- smsMessage->SetForwardToClient(aSmsMessage.ForwardToClient());
- smsMessage->SetToFromAddressL(aSmsMessage.ToFromAddress());
-
- CBufSeg* recvbufseg = CBufSeg::NewL(KSmsMaxSegmentLength);
- CleanupStack::PushL(recvbufseg);
- // Attempt to serialize this message into the buffer
- RBufWriteStream writestream(*recvbufseg);
- writestream.Open(*recvbufseg);
- CleanupClosePushL(writestream);
- writestream << *smsMessage;
-
- // Initialize the read stream with the buffer
- RBufReadStream readstream(*recvbufseg);
- readstream.Open(*recvbufseg,0);
- CleanupClosePushL(readstream);
- // De-serialize the message from using the read stream
- readstream >> aSmsMessage;
- CleanupStack::PopAndDestroy(4); //readstream, writestream, recvbufseg, smsMessage
- }
- }
- }
- }
-
-/*
-It returns when the next timeout should occur.
-*/
-void CClass0SmsReassemblyStore::GetNextGuardTimeout(TTime& aNextTimeout)
- {
- TTime curTime;
- curTime.UniversalTime();
- TTimeIntervalSeconds timeOutInSecs = iGuardTimeOut*3600;
- aNextTimeout = curTime + timeOutInSecs;
-
- TInt class0ReassemblyStoreCount = iEntryArray.Count();
-
- if (class0ReassemblyStoreCount > 0)
- {
- for (TInt i=0; i<class0ReassemblyStoreCount;i++)
- {
- TTime guradTimeout = iEntryArray[i].Time() + timeOutInSecs;
- if ((guradTimeout > curTime) &&
- (guradTimeout < aNextTimeout))
- {
- aNextTimeout = guradTimeout;
- }
- }
- }
- }
-
-/*
-It returns the index of oldest message in class 0 re-assembly store.
-*/
-TInt CClass0SmsReassemblyStore::GetIndexOfOldestMessage()
- {
- TInt index = 0;
- TTime time = iEntryArray[index].Time();
- for (TInt index2=1; index2 < iEntryArray.Count(); index2++)
- {
- if (iEntryArray[index2].Time() < time)
- {
- index = index2;
- }
- }
- return index;
- }
-
-/*
-It returns the index of oldest message in class 0 re-assembly store.
-*/
-TInt CClass0SmsReassemblyStore::GetIndexOfOldestMessageFromReservedFileL()
- {
- TInt index = KErrNotFound;
- //Find the index of oldest message in pre-allocated file.
- index = iPreallocatedFile->GetOldestMessageEntryIndex();
- if (index == KErrNotFound)
- {
- //This condition should never arise
- User::Leave(KErrNotFound);
- }
-
- //Compare the oldest pre-allocated message entry against class 0 reassembly store entry
- //and return the index of class 0 reassembly store entry.
- const TSmsPreAllocatedFileStoreReassemblyEntry& preAllocatedFileEntry = iPreallocatedFile->Entries()[index];
-
- TInt reassemblyCount = iEntryArray.Count();
- TInt count;
- for (count = 0; count < reassemblyCount; count++)
- {
- TReassemblyEntry& entry = iEntryArray[count];
-
- if (entry.Reference() == preAllocatedFileEntry.Reference() &&
- entry.Total() == preAllocatedFileEntry.Total() &&
- entry.PduType() == preAllocatedFileEntry.PduType() &&
- entry.Storage() == preAllocatedFileEntry.Storage() &&
- entry.Description2() == preAllocatedFileEntry.Description2())
- {
- //
- // Found it!
- //
- index = count;
- break;
- }
- }
- if (count == reassemblyCount)
- {
- //This condition should never arise
- User::Leave(KErrNotFound);
- }
- return index;
- }
-
-/*
-It returns a boolean value indicating whether the limitation (max class 0 message,
-max pdu stored in pre-allocated file) imposed on class 0 reassembly store exceeds or not.
-*/
-TBool CClass0SmsReassemblyStore::IsExceedLimitation()
- {
- TInt class0MsgCount = iEntryArray.Count();
- TInt noOfMsgStoredInPreAllocatedFile = iPreallocatedFile->NumberOfPDUStored();
- if ((class0MsgCount > iMaxClass0Msg)
- || (noOfMsgStoredInPreAllocatedFile > iMaxPDUSeg))
- {
- return ETrue;
- }
-
- return EFalse;
- }
-
-/*
-This sorting algorithm is based on bubble sort
-*/
-void CClass0SmsReassemblyStore::SortPDUsL(CArrayFix<TInt>& aIndexArray, CArrayFix<TGsmSms>& aSmsArray)
- {
- //Test---Index array count must be equal to sms array count
- TBool swapped;
-
- do
- {
- swapped = EFalse;
- for (TInt i=0; i<aIndexArray.Count()-1 ;i++)
- {
- if (aIndexArray[i] > aIndexArray[i+1])
- {
- aSmsArray.InsertL(i, aSmsArray[i+1]);
- aSmsArray.Delete(i+2);
- aIndexArray.InsertL(i, aIndexArray[i+1]);
- aIndexArray.Delete(i+2);
- swapped = ETrue;
- }
- }
- }
- while (swapped);
- }
-
-/**
- * Utility func for cleanup stack
- */
-void CClass0StoreCloseObject(TAny* aObj)
- {
- LOGGSMU2("WARNING! Hey, CClass0StoreCloseObject called by Untrapper! [0x%08x]", aObj);
- ((CClass0SmsReassemblyStore*)aObj)->Revert();
- }
-
-/**
- * Sets the class 0 re-assembly store as in-transaction.
- *
- * The function checks the validity of the call and leaves KErrAccessDenied if
- * invalid.
- * @capability None
- */
-void CClass0SmsReassemblyStore::BeginTransactionLC()
- {
- LOGSMSPROT3("CClass0SmsReassemblyStore::BeginTransactionLC [this=0x%08X iInTransaction=%d]", this, iInTransaction);
-
- if (iInTransaction)
- {
- LOGGSMU1("WARNING CClass0SmsReassemblyStore::BeginTransactionLC leaving with KErrAccessDenied");
- User::Leave(KErrAccessDenied);
- }
-
- TCleanupItem class0StoreClose(CClass0StoreCloseObject, this);
- CleanupStack::PushL(class0StoreClose);
- iPreallocatedFile->BeginTransactionL();
- iPermanentFileStore->BeginTransactionL();
- iInTransaction = ETrue;
- }
-
-/**
- * It commits the transaction.
- */
-void CClass0SmsReassemblyStore::CommitTransactionL()
- {
- LOGSMSPROT3("CClass0SmsReassemblyStore::CommitTransactionL(): this=0x%08X iInTransaction=%d",
- this, iInTransaction);
-
- //Commit permanent store file
- iPermanentFileStore->CommitTransactionL();
- //Commit pre-allocated file
- iPreallocatedFile->CommitTransactionL();
- CleanupStack::Pop(this); //CClass0StoreCloseObject
- iInTransaction = EFalse;
- }
-
-/**
- * It reverts the transaction.
- */
-void CClass0SmsReassemblyStore::Revert()
- {
- LOGSMSPROT3("CClass0SmsReassemblyStore::Revert(): this=0x%08X, iInTransaction=%d",
- this, iInTransaction);
-
- iPreallocatedFile->Revert();
- iPermanentFileStore->Revert();
- iInTransaction = EFalse;
- }
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implements CPreallocatedFile.
+//
+//
+
+/**
+ @file
+*/
+#include "smspclass0stor.h"
+#include "gsmubuf.h"
+#include "gsmunonieoperations.h"
+
+const TInt KSizeOfPreallocatedFileVersion = sizeof(CPreallocatedFile::TPreAllocatedFileVersion);
+const TInt KSizeOfNumberOfEntrySection = sizeof(TInt);
+//size of 32-bit checksum
+const TInt KSizeOfChecksum = sizeof(TUint32);
+const TInt KSizeOfPreAllocatedStoreEntry = sizeof(TSmsPreAllocatedFileStoreReassemblyEntry);
+const TInt KSizeOfGsmSmsSlotEntry = sizeof(TGsmSmsSlotEntry);
+const TInt KSizeOfIndexEntry = sizeof(TInt);
+const TInt KSizeOfSmsGsmPDU = sizeof(RMobileSmsMessaging::TMobileSmsGsmTpdu);
+const TInt KSizeOfAContainer = KSizeOfGsmSmsSlotEntry + KSizeOfIndexEntry + KSizeOfSmsGsmPDU;
+const TInt KBeginOfMasterHeaderSection = KSizeOfPreallocatedFileVersion;
+
+/**
+Static factory constructor. Uses two phase
+construction and leaves nothing on the CleanupStack.
+
+@param aFs File Server handle.
+@param aFileName Permanent file store name.
+@param aThirdUid Uid of file.
+@leave KErrNoMemory
+
+@return A pointer to the newly created CSmsPermanentFileStore object.
+
+@pre A connected file server session must be passed as parameter.
+@post CSmsPermanentFileStore object is now fully initialised
+
+@internalComponent
+*/
+CSmsPermanentFileStore* CSmsPermanentFileStore::NewL(RFs& aFs, const TDesC& aFileName, const TUid& aThirdUid)
+ {
+ LOGSMSPROT1("CSmsPermanentFileStore::NewL()");
+ CSmsPermanentFileStore* self = new (ELeave) CSmsPermanentFileStore(aFs, aThirdUid);
+ CleanupStack::PushL(self);
+ self->ConstructL(aFileName);
+ CleanupStack::Pop(self);
+
+ return self;
+ }
+
+void CSmsPermanentFileStore::ConstructL(const TDesC& aFileName)
+ {
+ LOGSMSPROT1("CSmsPermanentFileStore::ConstructL()");
+ iFileName = aFileName.AllocL();
+ }
+
+/**
+ * Constructor.
+*/
+CSmsPermanentFileStore::CSmsPermanentFileStore(RFs& aFs, const TUid& aThirdUid)
+ : iFs(aFs), iFileName(NULL), iThirdUid(aThirdUid), iFileStore(NULL), iEntryArray(KFlatArrayGranularity)
+ {
+ }
+
+/**
+ * Destructor. It destroys all the member variables.
+*/
+CSmsPermanentFileStore::~CSmsPermanentFileStore()
+ {
+ delete iFileName;
+ }
+
+/**
+It checks & returns whether the file exist or not. If file is there whether
+it is corrupted or not.
+
+@internalComponent
+*/
+TBool CSmsPermanentFileStore::IsFileOK()
+ {
+ TBool retBool(EFalse);
+ TUidType uidtype(KPermanentFileStoreLayoutUid,KSARStoreUid,iThirdUid);
+ TEntry entry;
+ TInt ret=iFs.Entry(iFileName->Des(), entry);
+ // Check file existence & corruption
+ if ((ret == KErrNone) && (entry.iType == uidtype))
+ {
+ retBool = ETrue;
+ }
+ return retBool;
+ }
+
+/**
+It creates a permanent store file.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::CreateL()
+ {
+ LOGSMSPROT1("CSmsPermanentFileStore::CreateL()");
+ TUidType uidtype(KPermanentFileStoreLayoutUid,KSARStoreUid,iThirdUid);
+ iFileStore=CPermanentFileStore::ReplaceL(iFs, iFileName->Des(), EFileShareExclusive|EFileStream|EFileRead|EFileWrite);
+ iFileStore->SetTypeL(uidtype);
+ iEntryArray.Reset();
+ ExternalizeEntryArrayL();
+ iFileStore->CommitL();
+ // Close it to make sure that file is created correctly (defensive approach).
+ Close();
+ //Again Open the file
+ OpenL();
+ }
+
+/**
+It opens the permanent store file and internalizes the entries.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::OpenL()
+ {
+ LOGSMSPROT1("CSmsPermanentFileStore::OpenL()");
+ iFileStore=CPermanentFileStore::OpenL(iFs,iFileName->Des(),EFileShareExclusive|EFileStream|EFileRead|EFileWrite);
+ InternalizeEntryArrayL();
+ }
+
+/**
+It closes the permanent store file.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::Close()
+ {
+ LOGSMSPROT1("CSmsPermanentFileStore::Close()");
+ delete iFileStore;
+ iFileStore = NULL;
+ iEntryArray.Reset();
+ }
+
+/*
+This function cleans its entries against the passed entries.
+This is needed because there might be a scenario where user has deleted a message
+but the corresponding message is not deleted from permanent store file
+due to out-of-disk condition. But the entry is invalid because
+it is no more in the pre-allocated file which contains master header info.
+And also at the time of forwarding an incomplete message a forwarded
+message has not been deleted due to above reason.
+This function also compacts the store after deletion.
+
+@param aEntryArray entray array against whose clean up is carried out.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::CleanupEntriesWithCompactL(const CArrayFix<TSmsPreAllocatedFileStoreReassemblyEntry>& aEntryArray)
+ {
+ // Ignore in code coverage - a previous CleanupEntries would need to have failed with KErrDiskFull
+ BULLSEYE_OFF
+ LOGSMSPROT1("CSmsPermanentFileStore::CleanupEntriesWithCompactL()");
+
+ iCompact = ETrue;
+ CleanupEntriesL(aEntryArray);
+ BULLSEYE_RESTORE
+ }
+
+/*
+This function cleans its entries against the passed entries.
+This is needed because there migth be a scenario where user has deleted a message
+but the corresponding message is not deleted from permanent store file
+due to out-of-disk condition. But the entry is invalid because
+it is no more in the pre-allocated file which contains master header info.
+And also at the time of forwarding an incomplete message a forwarded
+message has not been deleted due to above reason.
+
+@param aEntryArray entray array against whose clean up is carried out.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::CleanupEntriesL(const CArrayFix<TSmsPreAllocatedFileStoreReassemblyEntry>& aEntryArray)
+ {
+ LOGSMSPROT1("CSmsPermanentFileStore::CleanupEntriesL()");
+
+ TInt reassemblyCount = iEntryArray.Count();
+ TInt index, index2;
+
+ for (index = 0; index < reassemblyCount; index++)
+ {
+ for (index2 = 0; index2 < aEntryArray.Count(); index2++)
+ {
+ if (iEntryArray[index].Reference() == aEntryArray[index2].Reference() &&
+ iEntryArray[index].Total() == aEntryArray[index2].Total() &&
+ iEntryArray[index].PduType() == aEntryArray[index2].PduType() &&
+ iEntryArray[index].Storage() == aEntryArray[index2].Storage() &&
+ iEntryArray[index].Description2() == aEntryArray[index2].Description2())
+ {
+ if (aEntryArray[index2].NumberOfPDUsForwardToClient() > 0)
+ {
+ //Internalize the entries.
+ CSmsBuffer* buffer = CSmsBuffer::NewL();
+ CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer);
+ CleanupStack::PushL(smsMessage);
+
+ CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
+ CleanupStack::PushL(indexArray);
+ CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
+ CleanupStack::PushL(smsArray);
+
+ InternalizeEntryL(index, *smsMessage, *indexArray, *smsArray);
+ TInt noOfForwardedEntries = 0;
+ for (TInt j=indexArray->Count(); j>0 ;j--)
+ {
+ TUint8 bitMapIndex = (indexArray->At(j-1)-1)/8;
+ TUint8 bitPos = (indexArray->At(j-1)-1)%8;
+ TUint8 bitMap;
+ TSmsPreAllocatedFileStoreReassemblyEntry entry;
+ entry = aEntryArray[index2];
+ entry.GetBitMap(bitMapIndex, bitMap);
+ TUint8 tmpBitMap = 1;
+ tmpBitMap <<= bitPos;
+ if (tmpBitMap == (bitMap & tmpBitMap))
+ {
+ noOfForwardedEntries++;
+ indexArray->Delete(j-1);
+ smsArray->Delete(j-1);
+ }
+ }
+ if (noOfForwardedEntries > 0)
+ {
+ TStreamId streamId = iEntryArray[index].DataStreamId();
+ ExternalizeEntryL(streamId, *smsMessage, *indexArray, *smsArray);
+ }
+ CleanupStack::PopAndDestroy(3, smsMessage); // smsMessage, indexArray, smsArray
+ }
+ break;
+ }
+ }
+ if (index2 == aEntryArray.Count())
+ {
+ DeleteEntryL(index);
+ }
+ }
+ }
+
+/**
+It internalizes its entry array.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::InternalizeEntryArrayL()
+ {
+ LOGSMSPROT1("CSmsPermanentFileStore::InternalizeEntryArrayL()");
+
+ iEntryArray.Reset();
+ TStreamId headerid=iFileStore->Root();
+ RStoreReadStream stream;
+ stream.OpenLC(*iFileStore,headerid);
+ TInt count=stream.ReadInt32L();
+ for (TInt i=0; i<count; i++)
+ {
+ TSmsReassemblyEntry sarentry;
+ stream >> sarentry;
+ iEntryArray.AppendL(sarentry);
+ }
+ CleanupStack::PopAndDestroy(); // stream
+ }
+
+/**
+It externalizes its entry array.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::ExternalizeEntryArrayL()
+ {
+ LOGSMSPROT4("CSmsPermanentFileStore::ExternalizeEntryArrayL(): this=0x%08X count=%d headerid=%d]",
+ this, iEntryArray.Count(), iFileStore->Root().Value());
+
+ TStreamId headerid=iFileStore->Root();
+ RStoreWriteStream stream;
+ if (headerid==KNullStreamId)
+ {
+ headerid=stream.CreateLC(*iFileStore);
+ iFileStore->SetRootL(headerid);
+ }
+ else
+ {
+ stream.ReplaceLC(*iFileStore,headerid);
+ }
+
+ TInt count1=iEntryArray.Count();
+ TInt count2=0;
+ TInt i=0;
+
+ for (; i<count1; i++)
+ {
+ if (!iEntryArray[i].IsDeleted())
+ {
+ count2++;
+ }
+ }
+ stream.WriteInt32L(count2);
+ for (i=0; i<count1; i++)
+ {
+ if (!iEntryArray[i].IsDeleted())
+ {
+ stream << iEntryArray[i];
+ }
+ }
+
+ stream.CommitL();
+ CleanupStack::PopAndDestroy(&stream);
+ }
+
+/*
+It adds the new message in permanent store file.
+
+@param aIndex (output) index number on which message is added.
+@param aSmsMessage reference to sms message to be added.
+@param aGsmSms reference to GsmSms object to be added.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::AddNewMessageL(TInt& aIndex, CSmsMessage& aSmsMessage,const TGsmSms& aGsmSms)
+ {
+ LOGSMSPROT1("CSmsPermanentFileStore::AddNewMessageL");
+
+ CArrayFix<TInt>* indexArray=new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
+ CleanupStack::PushL(indexArray);
+ CArrayFixFlat<TGsmSms>* smsArray=new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
+ CleanupStack::PushL(smsArray);
+ //Index must initialize to 0.
+ TInt index = 0;
+ if (!aSmsMessage.IsDecoded())
+ {
+ index = aSmsMessage.SmsPDU().ConcatenatedMessagePDUIndex();
+ }
+ indexArray->AppendL(index);
+ smsArray->AppendL(aGsmSms);
+
+ TStreamId streamid = KNullStreamId;
+ ExternalizeEntryL(streamid, aSmsMessage, *indexArray, *smsArray);
+
+ TSmsReassemblyEntry tmpEntry;
+ //Fill-up entry information...
+ CReassemblyStoreUtility::PopulateEntry(tmpEntry, aSmsMessage, 1);
+ // Update Data stream id.
+ tmpEntry.SetDataStreamId(streamid);
+
+ aIndex = iEntryArray.Count();
+ AddEntryL(tmpEntry);
+ CleanupStack::PopAndDestroy(2); //indexArray, smsArray
+ }
+
+/*
+It updates the existing message in permanent store file.
+
+@param aIndex index number on which message is to be updated.
+@param aSmsMessage reference to sms message to be updated.
+@param aIndexArray array of index of all the PDUs.
+@param aSmsArray array of sms of all the PDUs.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::UpdateExistingMessageL(TInt aIndex, const CSmsMessage& aSmsMessage,const CArrayFix<TInt>& aIndexArray,const CArrayFix<TGsmSms>& aSmsArray)
+ {
+ LOGSMSPROT1("CSmsPermanentFileStore::UpdateExistingMessageL()");
+ TStreamId streamid = iEntryArray[aIndex].DataStreamId();
+ ExternalizeEntryL(streamid, aSmsMessage, aIndexArray, aSmsArray);
+ TSmsReassemblyEntry entry;
+ CReassemblyStoreUtility::PopulateEntry(entry, aSmsMessage, aSmsArray.Count());
+ entry.SetDataStreamId(streamid);
+ ChangeEntryL(aIndex, entry);
+ }
+
+/*
+It matches the entry with entry in permanent store file & returns
+the index. If not found it returns KErrNotFound.
+
+@param aEntry reference to entry information.
+@param aIndex (output) returns the index number.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::MatchEntryToExistingMessage(const TReassemblyEntry& aEntry,
+ TInt& aIndex)
+ {
+ LOGSMSPROT1("CSmsPermanentFileStore::MatchEntryToExistingMessage()");
+
+ aIndex = KErrNotFound;
+
+ //
+ // Search the reassembly store for a matching entry...
+ //
+ TInt reassemblyCount = iEntryArray.Count();
+ for (TInt index = 0; index < reassemblyCount; index++)
+ {
+ TSmsReassemblyEntry& entry = iEntryArray[index];
+
+ if (entry.Reference() == aEntry.Reference() &&
+ entry.Total() == aEntry.Total() &&
+ entry.PduType() == aEntry.PduType() &&
+ entry.Storage() == aEntry.Storage() &&
+ entry.Description2() == aEntry.Description2())
+ {
+ //
+ // Found it!
+ //
+ aIndex = index;
+ break;
+ }
+ }
+
+ LOGSMSPROT2("CSmsPermanentFileStore::MatchEntryToExistingMessage(): aIndex=%d", aIndex);
+ }
+
+/*
+It updates the log server id of the message.
+
+@param aIndex index number of the message to be updated.
+@param aLogServerId log server id.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::UpdateLogServerIdL(TInt& aIndex, TLogId aLogServerId)
+ {
+ LOGSMSPROT1("CSmsPermanentFileStore::UpdateLogServerIdL");
+
+ TSmsReassemblyEntry entry;
+ entry = iEntryArray[aIndex];
+
+ if (entry.LogServerId() != aLogServerId)
+ {
+ entry.SetLogServerId(aLogServerId);
+ ChangeEntryL(aIndex, entry);
+ }
+ }
+
+/*
+It sets the message passed to client or not.
+
+@param aIndex index number of the message to be updated.
+@param aBool boolean value indicating whether message is passes or not.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::SetPassedToClientL(TInt aIndex, TBool aBool)
+ {
+ LOGSMSPROT2("CSmsPermanentFileStore::SetPassedToClientL(): aIndex=%d", aIndex);
+
+ TSmsReassemblyEntry entry;
+ entry = iEntryArray[aIndex];
+
+ if (entry.PassedToClient() != aBool)
+ {
+ entry.SetPassedToClient(aBool);
+ ChangeEntryL(aIndex, entry);
+ }
+ }
+
+/*
+It adds the new entry in the existing entry array.
+
+@param aEntry entry to be added.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::AddEntryL(TSmsReassemblyEntry& aEntry)
+ {
+ iEntryArray.AppendL(aEntry);
+ iEntryArray[iEntryArray.Count()-1].SetIsAdded(ETrue);
+ }
+
+/*
+It changes the existing entry with new entry.
+
+@param aIndex index number of the entry which will be changed.
+@param aNewEntry entry to be updated.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::ChangeEntryL(TInt aIndex,const TSmsReassemblyEntry& aNewEntry)
+ {
+ LOGSMSPROT2("CSmsPermanentFileStore::ChangeEntryL(): aIndex=%d", aIndex);
+
+ iEntryArray[aIndex].SetIsDeleted(ETrue);
+ iEntryArray.InsertL(aIndex,aNewEntry);
+ iEntryArray[aIndex].SetIsAdded(ETrue);
+ }
+
+/*
+It deletes the entry.
+
+@param aIndex index number of the entry which will be deleted.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::DeleteEntryL(TInt aIndex)
+ {
+ iFileStore->DeleteL(iEntryArray[aIndex].DataStreamId());
+ iEntryArray[aIndex].SetIsDeleted(ETrue);
+ }
+
+/*
+It externalizes(writes) the entry in permanent store file.
+
+@param aStreamId stream id which needs to externalized.
+@param aSmsMessage reference to sms message which needs to be externalized.
+@param aIndexArray refence to array of index which needs to be externalized.
+@param aSmsArray refence to array of sms which needs to be externalized.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::ExternalizeEntryL(TStreamId& aStreamId,const CSmsMessage& aSmsMessage,const CArrayFix<TInt>& aIndexArray,const CArrayFix<TGsmSms>& aSmsArray)
+ {
+ LOGSMSPROT2("CSmsPermanentFileStore::ExternalizeEntryL Start [sid=%d]", aStreamId.Value());
+
+ RStoreWriteStream writestream;
+ if (aStreamId==KNullStreamId)
+ aStreamId=writestream.CreateLC(*iFileStore);
+ else
+ writestream.ReplaceLC(*iFileStore,aStreamId);
+ writestream << aSmsMessage;
+ TInt count=aIndexArray.Count();
+ writestream.WriteInt32L(count);
+ TInt i=0;
+ for (; i<count; i++)
+ writestream.WriteInt32L(aIndexArray[i]);
+ count=aSmsArray.Count();
+ writestream.WriteInt32L(count);
+ for (i=0; i<count; i++)
+ {
+ RMobileSmsMessaging::TMobileSmsGsmTpdu pdu;
+ pdu=aSmsArray[i].Pdu();
+ writestream << pdu;
+ }
+ writestream.CommitL();
+ CleanupStack::PopAndDestroy();
+
+ LOGSMSPROT2("CClass0PermanentFileStore::ExternalizeEntryL End [count=%d]", count);
+ }
+
+/*
+It internalizes(reads) the entry from permanent store file.
+
+@param aIndex index number of the message to be internalized.
+@param aSmsMessage (output) reference to sms message.
+@param aIndexArray (output) refence to array of index.
+@param aSmsArray (output) refence to array of sms.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::InternalizeEntryL(const TInt aIndex, CSmsMessage& aSmsMessage, CArrayFix<TInt>& aIndexArray, CArrayFix<TGsmSms>& aSmsArray)
+ {
+ TSmsReassemblyEntry& entry = iEntryArray[aIndex];
+ LOGSMSPROT2("CSmsPermanentFileStore::InternalizeEntryL Start [sid=%d]", entry.DataStreamId().Value());
+ RStoreReadStream readstream;
+ readstream.OpenLC(*iFileStore, entry.DataStreamId());
+ readstream >> aSmsMessage;
+ TInt count=readstream.ReadInt32L();
+ TInt i;
+ for (i=0; i<count; i++)
+ {
+ TInt index=readstream.ReadInt32L();
+ aIndexArray.AppendL(index);
+ }
+ count=readstream.ReadInt32L();
+ if(count!=aIndexArray.Count())
+ {
+ User::Leave(KErrCorrupt);
+ }
+ for (i=0; i<count; i++)
+ {
+ RMobileSmsMessaging::TMobileSmsGsmTpdu pdu;
+ readstream >> pdu;
+ TGsmSms sms;
+ sms.SetPdu(pdu);
+ aSmsArray.AppendL(sms);
+ }
+ CleanupStack::PopAndDestroy();
+ //Set other properties of CSmsMessage
+ aSmsMessage.SetStorage(entry.Storage());
+ aSmsMessage.SetLogServerId(entry.LogServerId());
+ aSmsMessage.SetTime(entry.Time());
+ LOGSMSPROT2("CSmsPermanentFileStore::InternalizeEntryL End [count=%d]", count);
+ }
+
+/*
+It removes the PDUs from permanent store file.
+This function is needed because after forwarding the incomplete message
+to client, the corresponding PDUs needs to be be removed from permanent
+store file.
+This functionality is specific to class 0 re-assembly store.
+
+@param aIndex index number of the message to be removed.
+@param aStartPos starting pos of pdu to be removed.
+@param aEndPos end pos of pdu to be removed.
+
+@internalComponent
+*/
+void CSmsPermanentFileStore::RemovePDUsL(TInt aIndex, TInt aStartPos, TInt aEndPos)
+ {
+ LOGSMSPROT1("CSmsPermanentFileStore::RemovePDUsL");
+
+ CSmsBuffer* buffer = CSmsBuffer::NewL();
+ CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer);
+ CleanupStack::PushL(smsMessage);
+
+ CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
+ CleanupStack::PushL(indexArray);
+ CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
+ CleanupStack::PushL(smsArray);
+
+ InternalizeEntryL(aIndex, *smsMessage, *indexArray, *smsArray);
+
+ TInt count = indexArray->Count();
+ for (TInt i=count; i>0; i--)
+ {
+ if ((indexArray->At(i-1) >= aStartPos) && (indexArray->At(i-1) <= aEndPos))
+ {
+ indexArray->Delete(i-1);
+ smsArray->Delete(i-1);
+ }
+ }
+
+ /*
+ There are 3 scenarios in this case:
+ 1. If all the entries are removed,
+ then there is no need to store the entry in this permanent file.
+ 2. If few entries are removed,
+ then externalize the remaining entries. Update count field also.
+ 3. If no entries are removed, then do nothing.
+ */
+ if (indexArray->Count()==0)
+ {
+ DeleteEntryL(aIndex);
+ }
+ else if (count!=indexArray->Count())
+ {
+ TStreamId streamid = iEntryArray[aIndex].DataStreamId();
+ ExternalizeEntryL(streamid, *smsMessage, *indexArray, *smsArray);
+
+ TSmsReassemblyEntry entry;
+ entry = iEntryArray[aIndex];
+ entry.SetCount(indexArray->Count());
+ ChangeEntryL(aIndex, entry);
+ }
+ CleanupStack::PopAndDestroy(3, smsMessage); // smsMessage, indexArray, smsArray
+ }
+
+/**
+ * Sets the permanent store as in-transaction.
+ *
+ * The function checks the validity of the call and leaves KErrAccessDenied if
+ * invalid.
+ * @capability None
+ */
+void CSmsPermanentFileStore::BeginTransactionL()
+ {
+ LOGSMSPROT4("CSmsPermanentFileStore::BeginTransactionL [this=0x%08X iInTransaction=%d iFileStore=0x%08X]", this, iInTransaction, iFileStore);
+
+ if (iFileStore == NULL || iInTransaction)
+ {
+ LOGSMSPROT1("WARNING CSmsPermanentFileStore::BeginTransactionL leaving with KErrAccessDenied");
+ User::Leave(KErrAccessDenied);
+ }
+
+ iInTransaction = ETrue;
+ } // CSmsPermanentFileStore::BeginTransactionL
+
+/**
+ * It reverts the transaction.
+ */
+void CSmsPermanentFileStore::Revert()
+ {
+ LOGSMSPROT3("CSmsPermanentFileStore::Revert(): this=0x%08X, iInTransaction=%d",
+ this, iInTransaction);
+
+ iFileStore->Revert();
+ iInTransaction = EFalse;
+ ReinstateDeletedEntries();
+ } // CSmsPermanentFileStore::Revert
+
+/**
+ * It commits the transaction. Then it compact the permanent store file.
+ */
+void CSmsPermanentFileStore::DoCommitAndCompactL()
+ {
+ LOGSMSPROT1("CSmsPermanentFileStore::DoCommitAndCompactL()");
+
+ LOGSMSPROTTIMESTAMP();
+ iFileStore->CommitL();
+ LOGSMSPROTTIMESTAMP();
+
+ iCommitCount--;
+ if ((iCommitCount < 0) || (iCompact))
+ {
+ iCommitCount = KNumStoreCommitsBeforeCompaction;
+ iFileStore->CompactL();
+ iFileStore->CommitL();
+ iCompact = EFalse;
+ }
+ } // CSmsPermanentFileStore::DoCommitAndCompactL
+
+/**
+ * It commits the transaction.
+ */
+void CSmsPermanentFileStore::CommitTransactionL()
+ {
+ LOGSMSPROT4("CSmsPermanentFileStore::CommitTransactionL(): this=0x%08X iInTransaction=%d iFileStore=0x%08X",
+ this, iInTransaction, iFileStore);
+
+ ExternalizeEntryArrayL();
+
+#ifdef _SMS_LOGGING_ENABLED
+ TRAPD(err, DoCommitAndCompactL());
+ if (err != KErrNone)
+ {
+ LOGGSMU2("WARNING! could not CommitL/CompactL due to %d", err);
+ User::Leave(err);
+ }
+#else
+ DoCommitAndCompactL();
+#endif
+
+ iInTransaction = EFalse;
+ RemoveDeletedEntries();
+ }
+
+/**
+ * It removes the deleted entries from entry arry.
+ * This function is called after commit.
+ */
+void CSmsPermanentFileStore::RemoveDeletedEntries()
+ {
+ LOGSMSPROT1("CSmsPermanentFileStore::RemoveDeletedEntries()");
+
+ TInt count=iEntryArray.Count();
+ while (count--)
+ {
+ TSmsReassemblyEntry& entry = iEntryArray[count];
+
+ if (entry.IsDeleted())
+ {
+ iEntryArray.Delete(count);
+ }
+ else
+ {
+ entry.SetIsAdded(EFalse);
+ }
+ }
+ } // CSmsPermanentFileStore::RemoveDeletedEntries
+
+/**
+ * It reinstate the deleted/added entries from entry arry.
+ * This function is called after revert operation.
+ */
+void CSmsPermanentFileStore::ReinstateDeletedEntries()
+ {
+ LOGSMSPROT1("CSmsPermanentFileStore::ReinstateDeletedEntries()");
+
+ TInt count=iEntryArray.Count();
+ while (count--)
+ {
+ TSmsReassemblyEntry& entry = iEntryArray[count];
+
+ if (entry.IsAdded())
+ {
+ iEntryArray.Delete(count);
+ }
+ else
+ {
+ entry.SetIsDeleted(EFalse);
+ }
+ }
+ } // CSmsPermanentFileStore::ReinstateDeletedEntries
+
+/**
+ * Constructor
+ *
+ * @capability None
+ */
+TSmsPreAllocatedFileStoreReassemblyEntry::TSmsPreAllocatedFileStoreReassemblyEntry():
+ TSmsReassemblyEntry(),
+ iPreAllocatedStorageId(0),
+ iStatus(RMobileSmsStore::EStoredMessageUnknownStatus),
+ iTimeOffset(0),
+ iDecodedOnSim(EFalse),
+ iForwardToClient(EFalse),
+ iForwardedCount(0),
+ iBitMap(NULL)
+ {
+ //Have to externalize so initialize to 0.
+ for (TInt i=0; i<KBitMapLen; i++)
+ {
+ iBitMap.Append(0x00);
+ }
+ }
+
+/*
+It returns the reference of a particular bit-map index.
+
+@param aIndex index number of the bit-map.
+@param aBitMap bit-map value.
+
+@internalComponent
+*/
+void TSmsPreAllocatedFileStoreReassemblyEntry::GetBitMap(TUint8 aIndex, TUint8& aBitMap)
+ {
+ aBitMap = iBitMap[aIndex];
+ }
+
+/*
+It sets the value of a bit-map.
+
+@param aIndex index number of the bit-map.
+@param aBitMap bit-map value
+
+@internalComponent
+*/
+void TSmsPreAllocatedFileStoreReassemblyEntry::SetBitMap(TUint8 aIndex, TUint8 aBitMap)
+ {
+ iBitMap[aIndex] = aBitMap;
+ }
+
+/**
+Static factory constructor. Uses two phase
+construction and leaves nothing on the CleanupStack.
+
+@param aFs File Server handle.
+@param aFileName Permanent file store name.
+@param aMaxClass0Msg max class 0 message that can be stored.
+@param aMaxPDUSeg max number of pdus that can be stored.
+@param aVersion version number of pre-allocated file.
+
+@return A pointer to the newly created CPreallocatedFile object.
+
+@pre A connected file server session must be passed as parameter.
+@post CPreallocatedFile object is now fully initialised
+
+@internalComponent
+*/
+CPreallocatedFile* CPreallocatedFile::NewL(RFs& aFs, const TDesC& aFileName, TInt aMaxClass0Msg, TInt aMaxPDUSeg, TPreAllocatedFileVersion aVersion)
+ {
+ LOGSMSPROT1("CPreallocatedFile::NewL()");
+ CPreallocatedFile* self = new (ELeave) CPreallocatedFile(aFs, aMaxClass0Msg, aMaxPDUSeg, aVersion);
+ CleanupStack::PushL(self);
+ self->ConstructL(aFileName);
+ CleanupStack::Pop(self);
+
+ return self;
+ }
+
+void CPreallocatedFile::ConstructL(const TDesC& aFileName)
+ {
+ LOGSMSPROT1("CPreallocatedFile::ConstructL()");
+ iFileName = aFileName.AllocL();
+ }
+
+/**
+ * Constructor.
+*/
+CPreallocatedFile::CPreallocatedFile(RFs& aFs, TInt aMaxClass0Msg, TInt aMaxPDUSeg, TPreAllocatedFileVersion aVersion)
+ :iFs(aFs), iEntryArray(KFlatArrayGranularity), iReinstateEntryInfo(KFlatArrayGranularity), iMaxClass0Msg(aMaxClass0Msg), iMaxPDUSeg(aMaxPDUSeg), iVersion(aVersion)
+ {
+ /*
+ Format of File:
+ Version Number, Header Section & Data Section
+ Version Number - Interger Value.
+ Header Section: Number of entries, Array of Entries, Array of PDU identifier section, Checksum.
+ Data Section: Array of Container. Each container contains Sms slot informatiuon, index number & PDU.
+ */
+
+ // Calculate the size of each section.
+
+ // Entry section will always contain one more entry than configured one by the user.
+ // Because it will provide one extra slot to store the new message for time being
+ // before forwarding the oldest message.
+ iSizeOfEntrySection = (KSizeOfPreAllocatedStoreEntry * (iMaxClass0Msg + 1));
+
+ iSizeOfStorageIdentifierSection = ((sizeof(TInt))*(iMaxPDUSeg+1));
+
+ TInt sizeOfHeaderSection = KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection + KSizeOfChecksum;
+
+ TInt sizeOfDataSection = KSizeOfAContainer * (iMaxPDUSeg+1);
+
+ // Calculate the size of File.
+ iSizeOfFile = KSizeOfPreallocatedFileVersion + 2 * sizeOfHeaderSection + sizeOfDataSection;
+
+ iBeginOfDuplicateHeaderSection = KSizeOfPreallocatedFileVersion + sizeOfHeaderSection;
+ iBeginOfDataSection = KSizeOfPreallocatedFileVersion + 2 * sizeOfHeaderSection;
+ }
+
+/**
+ * Destructor. It destroys all the member variables.
+*/
+CPreallocatedFile::~CPreallocatedFile()
+ {
+ delete iFileName;
+ }
+
+/**
+It checks & returns whether the file exist or not. If file is there whether
+it is corrupted or not.
+
+@internalComponent
+*/
+TBool CPreallocatedFile::IsFileOK()
+ {
+ LOGSMSPROT1("CPreallocatedFile::IsFileOK()");
+
+ TEntry entry;
+ // Check file exists
+ TInt ret=iFs.Entry(iFileName->Des(), entry);
+ // Check the size of file, if size does not match then assume that file
+ // is corrupted, then return KErrNotFound.
+ if ((ret == KErrNone) && (entry.iSize != iSizeOfFile))
+ {
+ ret = KErrNotFound;
+ }
+
+ if (ret == KErrNone)
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+/**
+It creates a pre-allocated file.
+
+@internalComponent
+*/
+void CPreallocatedFile::CreateL()
+ {
+ LOGSMSPROT1("CPreallocatedFile::CreateL");
+
+ User::LeaveIfError(iFile.Replace(iFs, iFileName->Des(), EFileWrite));
+ User::LeaveIfError(iFile.SetSize(iSizeOfFile));
+ iFile.Flush();
+
+ // Externalize Version Number
+ //TInt version = iVersion;
+ TPtr8 memPtr((TUint8*) &iVersion, KSizeOfPreallocatedFileVersion, KSizeOfPreallocatedFileVersion);
+ iFile.Write(0, memPtr);
+
+ //Externalize Header Information
+ ExternalizeEntryArray();
+
+ // Initialize Storage Identifier Section.
+ TInt storageIdentifier=0;
+ memPtr.Set((TUint8*) &storageIdentifier, sizeof(storageIdentifier), sizeof(storageIdentifier));
+ TInt pos = KSizeOfNumberOfEntrySection + iSizeOfEntrySection;
+ TInt pos2 = 0;
+ for (TInt count=0; count<iMaxPDUSeg+1; count++)
+ {
+ pos2 = pos + count * sizeof(storageIdentifier);
+ iFile.Write(KBeginOfMasterHeaderSection + pos2, memPtr);
+ //iFile.Write(iBeginOfDuplicateHeaderSection + pos2, memPtr);
+ }
+
+ // Initialize Checksum
+ PutChecksumValueL();
+
+ // Close it to make sure that file is created correctly (defensive approach).
+ iFile.Close();
+ //Again Open the file
+ OpenL();
+ }
+
+/**
+It opens the pre-allocated file. Then it internalizes all the entry information.
+
+@internalComponent
+*/
+void CPreallocatedFile::OpenL()
+ {
+ User::LeaveIfError(iFile.Open(iFs, iFileName->Des(), EFileShareExclusive|EFileRead|EFileWrite));
+ // Check the validity of the data.
+ CheckDataL();
+ // Internalize data
+ InternalizeEntryArrayL();
+ }
+
+/**
+It closes the pre-allocated file.
+
+@internalComponent
+*/
+void CPreallocatedFile::Close()
+ {
+ iFile.Close();
+ iEntryArray.Reset();
+ iReinstateEntryInfo.Reset();
+ }
+
+/**
+It internalizes the entry info from pre-allocated file.
+
+@internalComponent
+*/
+void CPreallocatedFile::InternalizeEntryArrayL()
+ {
+ iEntryArray.Reset();
+ TInt numberOfMessage;
+ TPtr8 memPtr((TUint8*) &numberOfMessage, sizeof(numberOfMessage), sizeof(numberOfMessage));
+ iFile.Read(KBeginOfMasterHeaderSection, memPtr);
+
+ TSmsPreAllocatedFileStoreReassemblyEntry tmpClass0ReassemblyStore;
+ memPtr.Set((TUint8*) &tmpClass0ReassemblyStore, KSizeOfPreAllocatedStoreEntry, KSizeOfPreAllocatedStoreEntry);
+
+ TInt pos = 0;
+ for (TInt count=0; count < numberOfMessage; count++)
+ {
+ pos = sizeof(TInt) + (count * KSizeOfPreAllocatedStoreEntry);
+ iFile.Read(KBeginOfMasterHeaderSection + pos, memPtr);
+ iEntryArray.AppendL(tmpClass0ReassemblyStore);
+ }
+ }
+
+/**
+It externalizes the entry info to pre-allocated file.
+
+@internalComponent
+*/
+void CPreallocatedFile::ExternalizeEntryArray()
+ {
+ TInt count=iEntryArray.Count();
+ TInt numberOfMessage=0;
+ TInt i=0;
+
+ for (; i<count; i++)
+ {
+ if (!iEntryArray[i].IsDeleted())
+ {
+ numberOfMessage++;
+ }
+ }
+
+ //Externalize number of mesages.
+ TPtr8 memPtr((TUint8*) &numberOfMessage, sizeof(numberOfMessage), sizeof(numberOfMessage));
+ iFile.Write(KBeginOfMasterHeaderSection, memPtr);
+
+ TInt entryNumber = 0;
+ //Externalize all the entries.
+ for (i=0; i<count; i++)
+ {
+ if (!iEntryArray[i].IsDeleted())
+ {
+ //At the time of externalizing don't externalize IsAdded(), IsDeleted() value
+ TBool isAdded = iEntryArray[i].IsAdded();
+ TBool isDeleted = iEntryArray[i].IsDeleted();
+ iEntryArray[i].SetIsAdded(EFalse);
+ iEntryArray[i].SetIsDeleted(EFalse);
+ memPtr.Set((TUint8*) &iEntryArray[i], KSizeOfPreAllocatedStoreEntry, KSizeOfPreAllocatedStoreEntry);
+ iFile.Write(KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + (entryNumber * KSizeOfPreAllocatedStoreEntry), memPtr);
+ //Again update IsAdded(), IsDeleted() with previous value
+ iEntryArray[i].SetIsAdded(isAdded);
+ iEntryArray[i].SetIsDeleted(isDeleted);
+ entryNumber++;
+ }
+ }
+
+ count = numberOfMessage;
+ /*
+ Externalize extra entry information with default information.
+ This initialization is required because of checksum.
+ */
+ TSmsPreAllocatedFileStoreReassemblyEntry tmpClass0ReassemblyStore;
+ memPtr.Set((TUint8*) &tmpClass0ReassemblyStore, KSizeOfPreAllocatedStoreEntry, KSizeOfPreAllocatedStoreEntry);
+ TInt pos = 0;
+ for (; count<iMaxClass0Msg + 1; count++)
+ {
+ pos = KSizeOfNumberOfEntrySection + (count * KSizeOfPreAllocatedStoreEntry);
+ iFile.Write(KBeginOfMasterHeaderSection + pos, memPtr);
+ }
+ iFile.Flush();
+ }
+
+/*
+It adds the new message in pre-allocated file.
+
+@param aIndex (output) index number on which message is added.
+@param aSmsMessage reference to sms message to be added.
+@param aGsmSms reference to GsmSms object to be added.
+
+@internalComponent
+*/
+void CPreallocatedFile::AddNewMessageL(TInt& aIndex, CSmsMessage& aSmsMessage,const TGsmSms& aGsmSms)
+ {
+ LOGSMSPROT1("CPreallocatedFile::AddNewMessageL");
+ //Gets the next free slot where the message will be stored.
+ TInt nextFreeSlot = GetFreeContainer();
+ TInt pduIndex=aSmsMessage.IsDecoded()? 0: aSmsMessage.SmsPDU().ConcatenatedMessagePDUIndex();
+ if (aSmsMessage.Storage() == CSmsMessage::ESmsSIMStorage ||
+ aSmsMessage.Storage() == CSmsMessage::ESmsCombinedStorage)
+ {
+ const TGsmSmsSlotEntry& newSlot = aSmsMessage.iSlotArray[0];
+ ExternalizeEntry(nextFreeSlot, newSlot, pduIndex, aGsmSms);
+ }
+ else
+ {
+ ExternalizeEntry(nextFreeSlot, pduIndex, aGsmSms);
+ }
+
+ /*
+ Gets the unique id which will identify the containers where the
+ PDU related to this messsage are stored.
+ */
+ TInt freeStorageId = GetFreeStorageId();
+ AddStorageIdL(nextFreeSlot, freeStorageId);
+
+ TSmsPreAllocatedFileStoreReassemblyEntry tmpEntry;
+ //Fill-up entry information...
+ CReassemblyStoreUtility::PopulateEntry(tmpEntry, aSmsMessage, 1);
+ tmpEntry.SetPreAllocatedStorageId(freeStorageId);
+ //The properties below need to be set only once when a PDU of a new message arrives.
+ tmpEntry.SetStatus((RMobileSmsStore::TMobileSmsStoreStatus)aSmsMessage.Status());
+ tmpEntry.SetUTCOffset(aSmsMessage.UTCOffset());
+ tmpEntry.SetDecodedOnSIM(aSmsMessage.DecodedOnSim());
+ tmpEntry.SetForwardToClient(aSmsMessage.ForwardToClient());
+
+ // Add & extrenalize entry array.
+ aIndex = iEntryArray.Count();
+ AddEntryL(tmpEntry);
+ }
+
+/*
+It updates the existing message in permanent store file.
+
+@param aIndex index number on which message is to be updated.
+@param aSmsMessage reference to sms message to be updated.
+@param aPduIndex index of the PDU to be updated.
+@param aSms sms of the PDU to be updated.
+
+@internalComponent
+*/
+void CPreallocatedFile::UpdateExistingMessageL(TInt aIndex, const CSmsMessage& aSmsMessage, TInt aPduIndex, const TGsmSms& aSms)
+ {
+ LOGSMSPROT1("CPreallocatedFile::UpdateExistingMessageL()");
+ TInt preAllocatedStorageId = iEntryArray[aIndex].PreAllocatedStorageId();
+ if (preAllocatedStorageId == KErrNotFound)
+ {
+ /*
+ This condition arises when part of message is stored in permanent store file &
+ other parts arrive when system is out of disk.
+ */
+ preAllocatedStorageId = GetFreeStorageId();
+ iEntryArray[aIndex].SetPreAllocatedStorageId(preAllocatedStorageId);
+ }
+ // Externalize Entry in one of free containers.
+ TInt freeSlot = GetFreeContainer();
+ if (aSmsMessage.Storage() == CSmsMessage::ESmsSIMStorage ||
+ aSmsMessage.Storage() == CSmsMessage::ESmsCombinedStorage)
+ {
+ const TGsmSmsSlotEntry& newSlot = aSmsMessage.iSlotArray[0];
+ ExternalizeEntry(freeSlot, newSlot, aPduIndex, aSms);
+ }
+ else
+ {
+ ExternalizeEntry(freeSlot, aPduIndex, aSms);
+ }
+
+ AddStorageIdL(freeSlot, preAllocatedStorageId);
+ TSmsPreAllocatedFileStoreReassemblyEntry entry;
+ entry = iEntryArray[aIndex];
+ /*
+ This value must be set because this may the first PDU of an
+ existing message which is stored in pre-allocated store file.
+ */
+ entry.SetPreAllocatedStorageId(preAllocatedStorageId);
+ entry.SetCount(entry.Count()+1);
+ ChangeEntryL(aIndex, entry);
+ }
+
+/*
+It matches the entry with entry in pre-allocated file & returns
+the index. If not found it returns KErrNotFound.
+
+@param aEntry reference to entry information.
+@param aIndex (output) returns the index number.
+
+@internalComponent
+*/
+void CPreallocatedFile::MatchEntryToExistingMessage(const TReassemblyEntry& aEntry,
+ TInt& aIndex)
+ {
+ LOGSMSPROT1("CPreallocatedFile::MatchEntryToExistingMessage()");
+
+ aIndex = KErrNotFound;
+
+ //
+ // Search the reassembly store for a matching entry...
+ //
+ TInt reassemblyCount = iEntryArray.Count();
+
+ for (TInt index = 0; index < reassemblyCount; index++)
+ {
+ TSmsPreAllocatedFileStoreReassemblyEntry& entry = iEntryArray[index];
+
+ if (entry.Reference() == aEntry.Reference() &&
+ entry.Total() == aEntry.Total() &&
+ entry.PduType() == aEntry.PduType() &&
+ entry.Storage() == aEntry.Storage() &&
+ entry.Description2() == aEntry.Description2())
+ {
+ //
+ // Found it!
+ //
+ aIndex = index;
+ break;
+ }
+ }
+
+ LOGSMSPROT2("CPreallocatedFile::MatchEntryToExistingMessage(): aIndex=%d", aIndex);
+ }
+
+/*
+It updates the log server id of the message.
+
+@param aIndex index number of the message to be updated.
+@param aLogServerId log server id.
+
+@internalComponent
+*/
+void CPreallocatedFile::UpdateLogServerIdL(TInt& aIndex, TLogId aLogServerId)
+ {
+ LOGSMSPROT1("CPreallocatedFile::UpdateLogServerId");
+
+ TSmsPreAllocatedFileStoreReassemblyEntry entry;
+ entry = iEntryArray[aIndex];
+
+ if (entry.LogServerId() != aLogServerId)
+ {
+ entry.SetLogServerId(aLogServerId);
+ ChangeEntryL(aIndex, entry);
+ }
+ }
+
+/*
+It sets the message passed to client or not.
+
+@param aIndex index number of the message to be updated.
+@param aBool boolean value indicating whether message is passes or not.
+
+@internalComponent
+*/
+void CPreallocatedFile::SetPassedToClientL(TInt aIndex, TBool aBool)
+ {
+ LOGSMSPROT2("CPreallocatedFile::SetPassedToClientL(): aIndex=%d", aIndex);
+
+ TSmsPreAllocatedFileStoreReassemblyEntry entry;
+ entry = iEntryArray[aIndex];
+
+ if (entry.PassedToClient() != aBool)
+ {
+ entry.SetPassedToClient(aBool);
+ ChangeEntryL(aIndex, entry);
+ }
+ }
+
+/*
+It adds the new entry in the existing entry array.
+
+@param aEntry entry to be added.
+
+@internalComponent
+*/
+void CPreallocatedFile::AddEntryL(TSmsPreAllocatedFileStoreReassemblyEntry& aEntry)
+ {
+ LOGSMSPROT1("CPreallocatedFile::AddEntryL");
+ iEntryArray.AppendL(aEntry);
+ iEntryArray[iEntryArray.Count()-1].SetIsAdded(ETrue);
+ }
+
+/*
+It changes the existing entry with new entry.
+
+@param aIndex index number of the entry which will be changed.
+@param aNewEntry entry to be updated.
+
+@internalComponent
+*/
+void CPreallocatedFile::ChangeEntryL(TInt aIndex, const TSmsPreAllocatedFileStoreReassemblyEntry& aNewEntry)
+ {
+ LOGSMSPROT2("CPreallocatedFile::ChangeEntryL(): aIndex=%d", aIndex);
+ iEntryArray[aIndex].SetIsDeleted(ETrue);
+ iEntryArray.InsertL(aIndex,aNewEntry);
+ iEntryArray[aIndex].SetIsAdded(ETrue);
+ }
+
+/*
+It deletes the entry.
+
+@param aIndex index number of the entry which will be deleted.
+
+@internalComponent
+*/
+void CPreallocatedFile::DeleteEntryL(TInt aIndex)
+ {
+ LOGSMSPROT2("CPreallocatedFile::DeleteEntryL(): aIndex=%d", aIndex);
+ if (iEntryArray[aIndex].PreAllocatedStorageId() != KErrNotFound)
+ {
+ ClearEntryL(iEntryArray[aIndex].PreAllocatedStorageId(), iEntryArray[aIndex].Count());
+ }
+ iEntryArray[aIndex].SetIsDeleted(ETrue);
+ }
+
+/*
+It searches all the container & clears all the entries which
+contain the PDUs of the message (uniquely identified by aStorageId).
+
+NOTE:
+ It keeps the record of removed entries (container id, pre-allocated storage id
+ & operation performed (add/delete)) in iReinstateEntryInfo variable.
+ It will be required in case of revert operation. As the container which
+ refers to the container which contains actual PDU is freed,
+ so it will not be a problem to restore the removed PDUs.
+ In case of revert operation, the removed information can be found in
+ iReinstateEntryInfo variable which can be restored easily.
+ The container can be replaced with previous pre-allocated storage id.
+ After commiting the transaction, this varaible will be re-initialized.
+
+@param aStorageId unique id of message to be cleared.
+@param aNumberOfPDUs number of PDUs to be cleared.
+
+@internalComponent
+*/
+void CPreallocatedFile::ClearEntryL(TInt aStorageId, TInt aNumberOfPDUs)
+ {
+ LOGSMSPROT1("CPreallocatedFile::ClearEntryL");
+
+ //Read storage id.
+ TInt storageId;
+ TPtr8 memPtr((TUint8*) &storageId, sizeof(storageId), sizeof(storageId));
+ TInt beginOfStorageIdSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection;
+ TInt beginOfStorageId = 0;
+ TInt count;
+ TInt count2(0);
+
+ TInt cleanStorageId=0;
+ TPtr8 memPtr2((TUint8*) &cleanStorageId, sizeof(cleanStorageId), sizeof(cleanStorageId));
+
+ for (count=0; count<iMaxPDUSeg+1; count++)
+ {
+ TReinstateEntryInfo entry;
+ entry.iPreAllocatedStorageId=aStorageId;
+ entry.iFlag=EEntryIsDeleted;
+
+ beginOfStorageId = beginOfStorageIdSection + (count * sizeof(storageId));
+ iFile.Read(beginOfStorageId, memPtr);
+ if (storageId == aStorageId)
+ {
+ count2++;
+ iFile.Write(beginOfStorageId, memPtr2);
+ entry.iContainerId=count+1;
+ iReinstateEntryInfo.AppendL(entry);
+ }
+ if (count2 >= aNumberOfPDUs)
+ {
+ break;
+ }
+ }
+ iFile.Flush();
+ }
+
+/*
+It updates the storage identifier section. It updates the corresponding container
+in the storage identifier section specifying the PDU where it is stored.
+
+NOTE:
+ It keeps the record of added entries in iReinstateEntryInfo variable.
+ It will be required in case of revert operation.
+ After commiting the transaction, this varaible should be re-initialized.
+
+@param aIndex index number of the container where PDU has been stored..
+@param aStorageId unique id of added message.
+
+@internalComponent
+*/
+void CPreallocatedFile::AddStorageIdL(TInt aIndex, TInt aStorageId)
+ {
+ //Put storage id in master header section
+ TPtr8 memPtr((TUint8*) &aStorageId, sizeof(aStorageId), sizeof(aStorageId));
+ TInt beginOfStorageIdentifierSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection;
+ iFile.Write( beginOfStorageIdentifierSection + ((aIndex - 1) * sizeof(TInt)), memPtr);
+
+ TReinstateEntryInfo entry;
+ entry.iContainerId=aIndex;
+ entry.iPreAllocatedStorageId=aStorageId;
+ entry.iFlag=EEntryIsAdded;
+ iReinstateEntryInfo.AppendL(entry);
+ }
+
+/*
+It returns the next free available free container where next PDU can be stored.
+
+It goes through storage identifier section, it reads the conents of all storage
+identfier & return that container which is free.
+All the free container is identifiable by value 0. If the value is not 0 then it
+contains the storage id of a particular message.
+
+@internalComponent
+*/
+TInt CPreallocatedFile::GetFreeContainer()
+ {
+ // Get the next free slot.
+ TInt storageId;
+ TPtr8 memPtr((TUint8*) &storageId, sizeof(storageId), sizeof(storageId));
+ TInt beginOfStorageIdSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection;
+ TInt beginOfStorageId = 0;
+ TInt count;
+
+ for (count=0; count<iMaxPDUSeg+1; count++)
+ {
+ beginOfStorageId = beginOfStorageIdSection + (count * sizeof(storageId));
+ iFile.Read(beginOfStorageId, memPtr);
+ if (storageId == 0)
+ {
+ break;
+ }
+ }
+
+ // Count should never equal to iMaxPDUSeg+1
+ __ASSERT_DEBUG(count < iMaxPDUSeg+1, SmspPanic(KSmspPanicPreallocatedFileNoFreeContainer));
+
+ return (count + 1);
+ }
+
+/*
+It returns the next free storage id.
+
+Storage id is used to identify the messages stored in pre-allocated file.
+A message might contain multiple PDUs and all those PDUs will be stored in
+different container. This storage id will be used to identify on which
+container the PDUs of a message are stored.
+
+This logic is based on the max number of messages that can be stored in
+pre-allocated file at one time. So free storage id is always used from
+this pool of numbers (from 1 till (max calls 0 message+2)).
+
+@internalComponent
+*/
+TInt CPreallocatedFile::GetFreeStorageId()
+ {
+ TInt count;
+
+ for (count=1; count < iMaxClass0Msg + 2; count++)
+ {
+ TInt numberOfEntries = iEntryArray.Count();
+ TInt count2;
+ for (count2 = 0; count2 < numberOfEntries; count2++)
+ {
+ if (count == iEntryArray[count2].PreAllocatedStorageId())
+ {
+ break;
+ }
+ }
+ if (count2 == numberOfEntries)
+ {
+ break;
+ }
+ }
+ return count;
+ }
+
+/*
+It externalizes(writes) the entry in permanent store file.
+
+@param aContainerId container id where the sms pdu needs to externalized.
+@param aSmsSlot reference to slot information.
+@param aIndex index number of PDU.
+@param aGsmSms refence to sms pdu.
+
+@internalComponent
+*/
+void CPreallocatedFile::ExternalizeEntry(TInt aContainerId, const TGsmSmsSlotEntry& aSmsSlot, TInt aIndex, const TGsmSms& aGsmSms)
+ {
+ LOGSMSPROT3("CPreallocatedFile::ExternalizeEntry() 1: aContainerId=%d, aIndex=%d", aContainerId, aIndex);
+
+ // Container id must not be greater than max pdu segment.
+ TInt pos = iBeginOfDataSection + ((aContainerId - 1) * (KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU));
+ // Store slot info
+ TPtr8 memPtr((TUint8*) &aSmsSlot, sizeof(aSmsSlot), sizeof(aSmsSlot));
+ iFile.Write(pos, memPtr);
+ // Store the PDU index value
+ memPtr.Set((TUint8*) &aIndex, sizeof(aIndex), sizeof(aIndex));
+ iFile.Write(pos + KSizeOfGsmSmsSlotEntry, memPtr);
+ // Store the TGsmSms value
+ RMobileSmsMessaging::TMobileSmsGsmTpdu pdu;
+ pdu = aGsmSms.Pdu();
+ memPtr.Set((TUint8*) &pdu, KSizeOfSmsGsmPDU, KSizeOfSmsGsmPDU);
+ iFile.Write(pos + KSizeOfGsmSmsSlotEntry + sizeof(TInt), memPtr);
+
+ __ASSERT_DEBUG(pos + KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU <= iSizeOfFile,
+ SmspPanic(KSmspPanicPreallocatedFileCorrupt));
+ }
+
+/*
+It externalizes(writes) the entry in permanent store file.
+
+@param aContainerId container id where the sms pdu needs to externalized.
+@param aIndex index number of PDU.
+@param aGsmSms refence to sms pdu.
+
+@internalComponent
+*/
+void CPreallocatedFile::ExternalizeEntry(TInt aContainerId, TInt aIndex, const TGsmSms& aGsmSms)
+ {
+ LOGSMSPROT3("CPreallocatedFile::ExternalizeEntry() 2: aContainerId=%d, aIndex=%d", aContainerId, aIndex);
+
+ // Container id must not be greater than max pdu segment.
+ TInt pos = iBeginOfDataSection + ((aContainerId - 1) * (KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU));
+ // Store the PDU index value
+ TPtr8 memPtr((TUint8*) &aIndex, sizeof(aIndex), sizeof(aIndex));
+ iFile.Write(pos + KSizeOfGsmSmsSlotEntry, memPtr);
+ // Store the TGsmSms value
+ RMobileSmsMessaging::TMobileSmsGsmTpdu pdu;
+ pdu = aGsmSms.Pdu();
+ memPtr.Set((TUint8*) &pdu, KSizeOfSmsGsmPDU, KSizeOfSmsGsmPDU);
+ iFile.Write(pos + KSizeOfGsmSmsSlotEntry + sizeof(TInt), memPtr);
+
+ __ASSERT_DEBUG(pos + KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU <= iSizeOfFile,
+ SmspPanic(KSmspPanicPreallocatedFileCorrupt));
+ }
+
+/*
+It internalizes(reads) the entry from permanent store file.
+
+@param aIndex index number of the message to be internalized.
+@param aSmsMessage (output) reference to sms message.
+@param aIndexArray (output) refence to array of index.
+@param aSmsArray (output) refence to array of sms.
+
+@internalComponent
+*/
+void CPreallocatedFile::InternalizeEntryL(const TInt aIndex, CSmsMessage& aSmsMessage, CArrayFix<TInt>& aIndexArray, CArrayFix<TGsmSms>& aSmsArray)
+ {
+ LOGSMSPROT1("CPreallocatedFile::InternalizeEntryL");
+ TSmsPreAllocatedFileStoreReassemblyEntry& entry = iEntryArray[aIndex];
+ //Set other properties of CSmsMessage
+ aSmsMessage.SetStorage(entry.Storage());
+ aSmsMessage.SetStatus((NMobileSmsStore::TMobileSmsStoreStatus)entry.Status());
+ aSmsMessage.SetLogServerId(entry.LogServerId());
+ aSmsMessage.SetTime(entry.Time());
+ aSmsMessage.SetUTCOffset(entry.UTCOffset());
+ aSmsMessage.SetDecodedOnSIM(entry.DecodedOnSIM());
+ aSmsMessage.SetForwardToClient(entry.ForwardToClient());
+ aSmsMessage.SetToFromAddressL(entry.Description2());
+
+ LOGSMSPROT2("CPreallocatedFile::InternalizeEntryL Start [sid=%d]", entry.PreAllocatedStorageId());
+ if (entry.PreAllocatedStorageId()==KErrNotFound)
+ {
+ return;
+ }
+
+ TInt beginOfStorageIdSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection;
+ //This will be used to read the storgae id which will indicate
+ //that corresponding container contains actual PDU
+ TInt storageId=0;
+ TPtr8 memPtr1((TUint8*) &storageId, sizeof(storageId), sizeof(storageId));
+
+ TInt storageIdPos = 0;
+ TInt dataPos = 0;
+ //This will be used to read the slot information
+ TGsmSmsSlotEntry smsSlotEntry;
+ TPtr8 memPtr2((TUint8*) &smsSlotEntry, KSizeOfGsmSmsSlotEntry, KSizeOfGsmSmsSlotEntry);
+ //This will be used to read the concatenated PDU index.
+ TInt index=0;
+ TPtr8 memPtr3((TUint8*) &index, sizeof(index), sizeof(index));
+ //This will be used to read PDU.
+ RMobileSmsMessaging::TMobileSmsGsmTpdu pdu;
+ TPtr8 memPtr4((TUint8*) &pdu, KSizeOfSmsGsmPDU, KSizeOfSmsGsmPDU);
+ TGsmSms sms;
+
+ //Number of PDUs stored in this pre-allocated file
+ TInt noOfPDUs = iEntryArray[aIndex].Count();
+ //Will indicate how many number of PDUs already read from pre-allocated file.
+ TInt noOfPDUsRead = 0;
+ // Can also get the number of pdu stored in pre-allocated file from count's variable.
+ for (TInt count=0; count<iMaxPDUSeg+1; count++)
+ {
+ storageIdPos = beginOfStorageIdSection + count * sizeof(TInt);
+ iFile.Read(storageIdPos, memPtr1);
+ if (storageId == entry.PreAllocatedStorageId())
+ {//This means corresponding container contains the actual PDU
+ noOfPDUsRead++;
+ //Find the position of container where actaul PDU is stored.
+ dataPos = iBeginOfDataSection + ((count) * (KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU));
+ //Read slot information
+ if (entry.Storage() == CSmsMessage::ESmsSIMStorage ||
+ entry.Storage() == CSmsMessage::ESmsCombinedStorage)
+ {
+ iFile.Read(dataPos + KSizeOfGsmSmsSlotEntry, memPtr2);
+ aSmsMessage.AddSlotL(smsSlotEntry);
+ }
+ //Read index information
+ iFile.Read(dataPos + KSizeOfGsmSmsSlotEntry, memPtr3);
+ aIndexArray.AppendL(index);
+ //Read PDU
+ iFile.Read(dataPos + KSizeOfGsmSmsSlotEntry + sizeof(index), memPtr4);
+ sms.SetPdu(pdu);
+ aSmsArray.AppendL(sms);
+ if (noOfPDUsRead == noOfPDUs)
+ {
+ break;
+ }
+ }
+ }
+
+ LOGSMSPROT2("CPreallocatedFile::InternalizeEntryL End [noOfPDUsRead=%d]", noOfPDUsRead);
+ }
+
+/*
+It removes the PDUs from pre-allocated store file.
+This function is needed because after forwarding the incomplete message
+to client, the corresponding PDUs needs to be be removed from permanent
+store file.
+This functionality is specific to class 0 re-assembly store.
+
+@param aIndex index number of the message to be removed.
+@param aStartPos starting pos of pdu to be removed.
+@param aEndPos end pos of pdu to be removed.
+
+@internalComponent
+*/
+void CPreallocatedFile::RemovePDUsL(TInt aIndex, TInt aStartPos, TInt aEndPos)
+ {
+ LOGSMSPROT1("CPreallocatedFile::RemovePDUsL");
+
+ if ((aStartPos < 1) || (aEndPos > 256) || (aStartPos > aEndPos))
+ {
+ User::Leave(KErrArgument);
+ }
+
+ LOGSMSPROT2("CPreallocatedFile::RemovePDUsL Start [sid=%d]", iEntryArray[aIndex].PreAllocatedStorageId());
+ if (iEntryArray[aIndex].PreAllocatedStorageId()==KErrNotFound)
+ {
+ return;
+ }
+
+ TInt beginOfStorageIdSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection;
+ //This will be used to read the storgae id which will indicate
+ //that corresponding container contains actual PDU
+ TInt storageId=0;
+ TPtr8 memPtr1((TUint8*) &storageId, sizeof(storageId), sizeof(storageId));
+
+ //This will be used to cleanup the storage id.
+ TInt cleanStorageId=0;
+ TPtr8 memPtr2((TUint8*) &cleanStorageId, sizeof(cleanStorageId), sizeof(cleanStorageId));
+
+ //This will be used to read the concatenated PDU index.
+ TInt index=0;
+ TPtr8 memPtr3((TUint8*) &index, sizeof(index), sizeof(index));
+
+ //Number of PDUs stored in this pre-allocated file
+ TInt noOfPDUs = iEntryArray[aIndex].Count();
+ //Will indicate how many number of PDUs already read from pre-allocated file.
+ TInt noOfPDUsRead = 0;
+ // Can also get the number of pdu stored in pre-allocated file from count's variable.
+ TInt noOfEntriesRemoved=0;
+ for (TInt count=0; count<iMaxPDUSeg+1; count++)
+ {
+ TInt storageIdPos = beginOfStorageIdSection + count * sizeof(TInt);
+ iFile.Read(storageIdPos, memPtr1);
+ if (storageId == iEntryArray[aIndex].PreAllocatedStorageId())
+ {//This means corresponding container contains the actual PDU
+ noOfPDUsRead++;
+ //Find the position of container where actaul PDU is stored.
+ TInt dataPos = iBeginOfDataSection + ((count) * (KSizeOfGsmSmsSlotEntry + sizeof(TInt) + KSizeOfSmsGsmPDU));
+ //Read index information
+ iFile.Read(dataPos + KSizeOfGsmSmsSlotEntry, memPtr3);
+
+ if ((index >= aStartPos) && (index <= aEndPos))
+ {
+ noOfEntriesRemoved++;
+ //Remove the PDU entry.
+ iFile.Write(storageIdPos, memPtr2);
+ }
+
+ if (noOfPDUsRead == noOfPDUs)
+ {
+ break;
+ }
+ }
+ }
+
+ /*
+ There are 3 scenarios in this case:
+ 1. If all the entries need to be removed,
+ then there is no need to store the entry in this permanent file.
+ 2. If few entries need to be removed,
+ then externalize the remaining entries. Update count field also.
+ 3. If no entries need to be removed, then do nothing.
+ */
+ TSmsPreAllocatedFileStoreReassemblyEntry entry;
+ entry = iEntryArray[aIndex];
+
+ if (entry.Count() == noOfEntriesRemoved)
+ {
+ entry.SetPreAllocatedStorageId(KErrNotFound);
+ entry.SetCount(0);
+ ChangeEntryL(aIndex, entry);
+ }
+ else if (noOfEntriesRemoved > 0)
+ {
+ entry.SetCount(entry.Count() - noOfEntriesRemoved);
+ ChangeEntryL(aIndex, entry);
+ }
+ }
+
+/*
+It stores the forwarded message info in forwarded pdu bit-map.
+
+@param aIndex index number of the forwarded message.
+@param aStartPos starting pos of forwarded pdu.
+@param aEndPos end pos of forwarded pdu.
+
+@internalComponent
+*/
+void CPreallocatedFile::StoreForwardedPDUsInfoL(TInt aIndex, TInt aStartPos, TInt aEndPos)
+ {
+ TSmsPreAllocatedFileStoreReassemblyEntry entry;
+ entry = iEntryArray[aIndex];
+
+ TUint8 startBitMapIndex = (aStartPos-1)/8;
+ TUint8 endBitMapIndex = (aEndPos-1)/8;
+ TUint8 startBitPos = (aStartPos-1)%8;
+ TUint8 endBitPos = (aEndPos-1)%8;
+
+ if (startBitMapIndex == endBitMapIndex)
+ {
+ TUint8 bitMap;
+ entry.GetBitMap(startBitMapIndex, bitMap);
+ TUint8 tmpBitMap = (0 | 0xFF);
+ tmpBitMap <<= ((8 - endBitPos) - 1);
+ tmpBitMap >>= (8 - ((endBitPos - startBitPos)+1));
+ tmpBitMap <<= startBitPos;
+ bitMap |= tmpBitMap;
+ entry.SetBitMap(startBitMapIndex, bitMap);
+ }
+ else
+ {
+ TUint8 bitMap;
+ entry.GetBitMap(startBitMapIndex, bitMap);
+ TUint8 tmpBitMap = (0 | 0xFF);
+ tmpBitMap >>= (8 - ((7 - startBitPos)+1));
+ tmpBitMap <<= startBitPos;
+ bitMap |= tmpBitMap;
+ entry.SetBitMap(startBitMapIndex, bitMap);
+
+ entry.GetBitMap(endBitMapIndex, bitMap);
+ tmpBitMap = (0 | 0xFF);
+ tmpBitMap <<= ((8 - endBitPos) - 1);
+ tmpBitMap >>= (8 - ((endBitPos - 0)+1));
+ tmpBitMap <<= 0;
+ bitMap |= tmpBitMap;
+ entry.SetBitMap(endBitMapIndex, bitMap);
+ }
+
+ TInt noOfForwardedPDUs = (aEndPos - aStartPos) + 1;
+ entry.SetNumberOfPDUsForwardToClient(entry.NumberOfPDUsForwardToClient()+noOfForwardedPDUs);
+
+ ChangeEntryL(aIndex, entry);
+ }
+
+/*
+It checks the validity of master header section by comparing checksum value.
+If the checksum value does not match, then it copies data from duplicate header section to
+master header section.
+*/
+void CPreallocatedFile::CheckDataL()
+ {
+ TUint32 checksum;
+ TInt checksumPos = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection;
+
+ TPtr8 memPtr((TUint8*) &checksum, sizeof(checksum), sizeof(checksum));
+ iFile.Read(checksumPos, memPtr);
+
+ if (ChecksumValue() != checksum)
+ {
+ CopyDuplicateToMasterL();
+ }
+ }
+
+/*
+It writes the checksum value & then copies header information from master section to duplicate section.
+*/
+void CPreallocatedFile::PutChecksumValueL()
+ {
+ TUint32 checksum = ChecksumValue();
+ TInt checksumPos = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection;
+
+ TPtr8 memPtr((TUint8*) &checksum, sizeof(checksum), sizeof(checksum));
+ iFile.Write(checksumPos, memPtr);
+ iFile.Flush();
+ CopyMasterToDuplicateL();
+ }
+
+/*
+It calculates & returns the checksum value of master header section.
+*/
+TUint32 CPreallocatedFile::ChecksumValue()
+ {
+ TInt sizeOfDataToBeChecksum = KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection;
+
+ TUint32 checksum(0);
+
+ TUint32 tmpValue;
+ TPtr8 memPtr((TUint8*) &tmpValue, sizeof(tmpValue), sizeof(tmpValue));
+
+ for (TInt i = 0; i < sizeOfDataToBeChecksum/4 ; i++)
+ {
+ iFile.Read(KBeginOfMasterHeaderSection + (i*4), memPtr);
+ checksum += tmpValue;
+ }
+ return checksum;
+ }
+
+/*
+It copies header information from master copy to duplicate copy.
+*/
+void CPreallocatedFile::CopyMasterToDuplicateL()
+ {
+ TInt sizeOfDataToBeCopied = KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection + 4;
+
+ HBufC8* heapBuffer = HBufC8::NewL(sizeOfDataToBeCopied);
+ CleanupStack::PushL(heapBuffer);
+ TPtr8 memPtr(heapBuffer->Des());
+ iFile.Read(KBeginOfMasterHeaderSection, memPtr);
+ iFile.Write(iBeginOfDuplicateHeaderSection, memPtr);
+ iFile.Flush();
+ CleanupStack::PopAndDestroy(heapBuffer);
+ }
+
+/*
+It copies header information from duplicate copy to master copy.
+*/
+void CPreallocatedFile::CopyDuplicateToMasterL()
+ {
+ TInt sizeOfDataToBeCopied = KSizeOfNumberOfEntrySection + iSizeOfEntrySection + iSizeOfStorageIdentifierSection + 4;
+
+ HBufC8* heapBuffer = HBufC8::NewL(sizeOfDataToBeCopied);
+ CleanupStack::PushL(heapBuffer);
+ TPtr8 memPtr(heapBuffer->Des());
+ iFile.Read(iBeginOfDuplicateHeaderSection, memPtr);
+ iFile.Write(KBeginOfMasterHeaderSection, memPtr);
+ iFile.Flush();
+ CleanupStack::PopAndDestroy(heapBuffer);
+ }
+
+/*
+It returns the total number of PDUs stored in pre-allocated file.
+*/
+TInt CPreallocatedFile::NumberOfPDUStored()
+ {
+ TInt noOfPDUs = 0;
+ for (TInt i = 0; i < iEntryArray.Count(); i++)
+ {
+ noOfPDUs += iEntryArray[i].Count();
+ }
+ return noOfPDUs;
+ }
+
+/**
+ * Sets the pre-allocated file store as in-transaction.
+ *
+ * The function checks the validity of the call and leaves KErrAccessDenied if
+ * invalid.
+ * @capability None
+ */
+void CPreallocatedFile::BeginTransactionL()
+ {
+ LOGSMSPROT3("CPreallocatedFile::BeginTransactionL [this=0x%08X iInTransaction=%d]", this, iInTransaction);
+
+ if (iInTransaction)
+ {
+ LOGGSMU1("WARNING CPreallocatedFile::BeginTransactionL leaving with KErrAccessDenied");
+ User::Leave(KErrAccessDenied);
+ }
+
+ iInTransaction = ETrue;
+ }
+
+/**
+ * It commits the transaction.
+ */
+void CPreallocatedFile::CommitTransactionL()
+ {
+ LOGSMSPROT3("CPreallocatedFile::CommitTransactionL(): this=0x%08X iInTransaction=%d",
+ this, iInTransaction);
+
+ ExternalizeEntryArray();
+ //Commit
+ PutChecksumValueL();
+ iInTransaction = EFalse;
+ iReinstateEntryInfo.Reset();
+ RemoveDeletedEntries();
+ }
+
+/*
+It reverts the transaction.
+*/
+void CPreallocatedFile::Revert()
+ {
+ LOGSMSPROT3("CPreallocatedFile::Revert(): this=0x%08X, iInTransaction=%d",
+ this, iInTransaction);
+
+ ReinstateEntries();
+ ExternalizeEntryArray();
+ iInTransaction = EFalse;
+ ReinstateDeletedEntries();
+ }
+
+/**
+ * It removes the deleted entries from entry arry.
+ * This function is called after commit.
+ */
+void CPreallocatedFile::RemoveDeletedEntries()
+ {
+ LOGSMSPROT1("CPreallocatedFile::RemoveDeletedEntries()");
+
+ TInt count=iEntryArray.Count();
+ while (count--)
+ {
+ TSmsPreAllocatedFileStoreReassemblyEntry& entry = iEntryArray[count];
+
+ if (entry.IsDeleted())
+ {
+ iEntryArray.Delete(count);
+ }
+ else
+ {
+ entry.SetIsAdded(EFalse);
+ }
+ }
+ } // CPreallocatedFile::RemoveDeletedEntries
+
+/**
+ * It reinstate the deleted/added entries from entry arry.
+ * This function is called after revert operation.
+ */
+void CPreallocatedFile::ReinstateDeletedEntries()
+ {
+ LOGSMSPROT1("CPreallocatedFile::ReinstateDeletedEntries()");
+
+ TInt count=iEntryArray.Count();
+ while (count--)
+ {
+ TSmsPreAllocatedFileStoreReassemblyEntry& entry = iEntryArray[count];
+
+ if (entry.IsAdded())
+ {
+ iEntryArray.Delete(count);
+ }
+ else
+ {
+ entry.SetIsDeleted(EFalse);
+ }
+ }
+ } // CPreallocatedFile::ReinstateDeletedEntries
+
+/**
+ * It reinstate the deleted/added entries from the container.
+ * This function is called at the time of revert operation.
+ * Unlike permanent store file which supports revert. pre-allocated
+ * file (raw data file) supports the revert mecahnism using this function.
+ */
+void CPreallocatedFile::ReinstateEntries()
+ {
+ LOGSMSPROT1("CPreallocatedFile::ReinstateEntries()");
+
+ TInt containerId;
+ TInt storageId;
+ TPtr8 memPtr((TUint8*) &storageId, sizeof(storageId), sizeof(storageId));
+
+ TInt count = iReinstateEntryInfo.Count();
+
+ for (TInt i=0; i<count; i++)
+ {
+ if (iReinstateEntryInfo[i].iFlag == EEntryIsDeleted)
+ {
+ //Add the Pre-allocated storage info in the container.
+ storageId = iReinstateEntryInfo[i].iPreAllocatedStorageId;
+ containerId = iReinstateEntryInfo[i].iContainerId;
+ TInt beginOfStorageIdentifierSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection;
+ iFile.Write( beginOfStorageIdentifierSection + ((containerId - 1) * sizeof(TInt)), memPtr);
+ }
+ else //EEntryIsAdded
+ {
+ //Delete the Pre-allocated storage info from the container.
+ storageId = 0;
+ containerId = iReinstateEntryInfo[i].iContainerId;
+ TInt beginOfStorageIdentifierSection = KBeginOfMasterHeaderSection + KSizeOfNumberOfEntrySection + iSizeOfEntrySection;
+ iFile.Write( beginOfStorageIdentifierSection + ((containerId - 1) * sizeof(TInt)), memPtr);
+ }
+ }
+ iFile.Flush();
+ iReinstateEntryInfo.Reset();
+ }
+
+/*
+It returns the index of oldest message in pre-allocated file.
+*/
+TInt CPreallocatedFile::GetOldestMessageEntryIndex()
+ {
+ LOGSMSPROT1("CPreallocatedFile::GetOldestMessageEntryIndex()");
+
+ TInt index = KErrNotFound;
+ TTime time;
+ time.UniversalTime();
+
+ for (TInt index2=0; index2 < iEntryArray.Count(); index2++)
+ {
+ if ((iEntryArray[index2].Time() < time) && (iEntryArray[index2].Count()>0))
+ {
+ time = iEntryArray[index2].Time();
+ index = index2;
+ }
+ }
+ return index;
+ }
+
+/**
+Static factory constructor. Uses two phase
+construction and leaves nothing on the CleanupStack.
+
+@param aClass0ReassemblyStore reference to class 0 reasembly store.
+@param aGuardTimeout guard time out in hours.
+
+@return A pointer to the newly created CGuardTimer object.
+
+@internalComponent
+*/
+CGuardTimer* CGuardTimer::NewL(CClass0SmsReassemblyStore& aClass0ReassemblyStore, TInt aGuardTimeout)
+ {
+ LOGSMSPROT1("CGuardTimer::NewL()");
+
+ CGuardTimer* timer = new(ELeave) CGuardTimer(aClass0ReassemblyStore, aGuardTimeout);
+ CleanupStack::PushL(timer);
+ timer->ConstructL();
+ CleanupStack::Pop();
+ return timer;
+ } // CGuardTimer::NewL
+
+/**
+ * Constructor
+ */
+CGuardTimer::CGuardTimer(CClass0SmsReassemblyStore& aClass0ReassemblyStore, TInt aGuardTimeout)
+ :CTimer(KSmsSessionPriority),
+ iClass0ReassemblyStore(aClass0ReassemblyStore),
+ iTimeoutInSecs(aGuardTimeout*3600)
+ {
+ CActiveScheduler::Add(this);
+ } //CGuardTimer::CGuardTimer
+
+/**
+ * Destructor
+ */
+CGuardTimer::~CGuardTimer()
+ {
+ Cancel();
+ } // CGuardTimer::~CGuardTimer
+
+/**
+ * Enable the Gurad Timer
+ */
+void CGuardTimer::EnableGuardTimer()
+ {
+ LOGSMSPROT1("CGuardTimer::EnableGuardTimer()");
+ if (!IsActive())
+ {
+ TTime nextTimeOut;
+ iClass0ReassemblyStore.GetNextGuardTimeout(nextTimeOut);
+ At(nextTimeOut);
+ }
+ } //CGuardTimer::EnableGuardTimer
+
+/**
+ * Disable the Gurad Timer
+ */
+void CGuardTimer::DisableGuardTimer()
+ {
+ Cancel();
+ }
+
+/**
+ * Timer completed
+ */
+void CGuardTimer::RunL()
+ {
+ LOGSMSPROT2("CGuardTimer::RunL [iStatus=%d]", iStatus.Int());
+ iClass0ReassemblyStore.ProcessTimeoutMessageL();
+ EnableGuardTimer();
+ } // CGuardTimer::RunL
+
+/**
+Static factory constructor. Uses two phase
+construction and leaves nothing on the CleanupStack.
+
+@param aFs File Server handle.
+@param aSmsComm reference to MSmsComm event handler.
+
+@return A pointer to the newly created CClass0SmsReassemblyStore object.
+
+@pre A connected file server session must be passed as parameter.
+@post CClass0SmsReassemblyStore object is now fully initialised
+
+@internalComponent
+*/
+CClass0SmsReassemblyStore* CClass0SmsReassemblyStore::NewL(RFs& aFs, MSmsComm& aSmsComm)
+ {
+ LOGSMSPROT1("CClass0SmsReassemblyStore::NewL()");
+
+ CClass0SmsReassemblyStore* self = new (ELeave) CClass0SmsReassemblyStore(aFs, aSmsComm);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+
+ return self;
+ }
+
+/**
+ * C'tor
+ */
+CClass0SmsReassemblyStore::CClass0SmsReassemblyStore(RFs& aFs, MSmsComm& aSmsComm)
+ :CReassemblyStore(aFs), iSmsComm(aSmsComm), iPermanentFileStore(NULL), iPreallocatedFile(NULL),
+ iGuardTimer(NULL), iInTransaction(EFalse), iDiskSpaceStatus(ESmsDiskSpaceAvailable)
+ {
+ }
+
+/**
+ * D'tor
+ */
+CClass0SmsReassemblyStore::~CClass0SmsReassemblyStore()
+ {
+ delete iPermanentFileStore;
+ delete iPreallocatedFile;
+ delete iGuardTimer;
+ }
+
+/*
+It constructs permanent and pre-allocated file to store the class 0 messages.
+It creates a guard timer so that messages can be deleted if all the constituent
+PDU of a message is not received within configured time-frame.
+It also reserves 4KB disk space so that reserved space can be used to
+delete a stream from permanent file store in out-of-disk condition.
+
+@internalComponent
+*/
+void CClass0SmsReassemblyStore::ConstructL()
+ {
+ //Reserve Drive Space
+ User::LeaveIfError(iFs.ReserveDriveSpace(KStoreDrive, 4*1024));
+
+ //Read Configuration file
+ ReadConfigurableClass0SmsSettingsL(iMaxClass0Msg, iMaxPDUSeg, iGuardTimeOut);
+ //Create Permanent store file
+ TFileName permanentStoreFileName;
+ CReassemblyStoreUtility::PrivatePath(iFs, permanentStoreFileName);
+ permanentStoreFileName.Append(KClass0ReassemblyStoreName);
+ iPermanentFileStore = CSmsPermanentFileStore::NewL(iFs, permanentStoreFileName, KClass0ReassemblyStoreUid);
+ //Create Pre-allocated file
+ TFileName preAllocatedFileName;
+ CReassemblyStoreUtility::PrivatePath(iFs, preAllocatedFileName);
+ preAllocatedFileName.Append(KPreAllocatedFileName);
+ iPreallocatedFile = CPreallocatedFile::NewL(iFs, preAllocatedFileName, iMaxClass0Msg, iMaxPDUSeg);
+ //Create Gurad Timer
+ iGuardTimer = CGuardTimer::NewL(*this, iGuardTimeOut);
+ }
+
+/*
+It reads class 0 re-assembly store configuration information from smswap.sms.esk file.
+It reads the following information: MaxClass0Messages, NumberOfPDUSegements, GuardTimeOut.
+If any of the above element is missing it takes the default value.
+
+@internalComponent
+*/
+void CClass0SmsReassemblyStore::ReadConfigurableClass0SmsSettingsL(TInt& aMaxClass0Msg, TInt& aMaxPDUSeg, TInt& aGuardTimeOut)
+ {
+ LOGSMSPROT1("CClass0SmsReassemblyStore::ReadConfigurableClass0SmsSettingsL()");
+
+ aMaxClass0Msg = KMaxNumberOfClass0MessagesInReassemblyStore;
+ aMaxPDUSeg = KNumberOfPDUSegmentsStoredInOODCondition;
+ aGuardTimeOut = KGuardTimeOut;
+
+ CESockIniData* ini = NULL;
+ TRAPD(ret, ini=CESockIniData::NewL(_L("smswap.sms.esk")));
+ if(ret!=KErrNone)
+ {
+ LOGSMSPROT2("CESockIniData::NewL() returned=%d", ret);
+ }
+ else
+ {
+ CleanupStack::PushL(ini);
+
+ TInt var(0);
+ if(ini->FindVar(_L("ReassemblyStore"),_L("MaxClass0Messages"),var))
+ {
+ if (var > 0)
+ {
+ LOGSMSPROT2("MaxClass0Messages [%d]", var);
+ aMaxClass0Msg = var;
+ }
+ }
+
+ if(ini->FindVar(_L("ReassemblyStore"),_L("NumberOfPDUSegements"),var))
+ {
+ if (var > 0)
+ {
+ LOGSMSPROT2("MaxClass0Messages [%d]", var);
+ aMaxPDUSeg = var;
+ }
+ }
+
+ if(ini->FindVar(_L("ReassemblyStore"),_L("GuardTimeOut"),var))
+ {
+ if (var > 0)
+ {
+ LOGSMSPROT2("MaxClass0Messages [%d]", var);
+ aGuardTimeOut = var;
+ }
+ }
+
+ CleanupStack::PopAndDestroy(ini);
+ }
+
+ LOGSMSPROT4("CClass0SmsReassemblyStore::ReadConfigurableClass0SmsSettingsL(): aMaxClass0Msg=%d, aMaxPDUSeg=%d, aGuardTimeOut=%d",
+ aMaxClass0Msg, aMaxPDUSeg, aGuardTimeOut);
+ }
+
+/**
+It opens the class 0 re-assembly store.
+Then it populates the entry information (all the messages stored in re-assembly store).
+
+@internalComponent
+*/
+void CClass0SmsReassemblyStore::OpenStoreL()
+ {
+ LOGSMSPROT1("CClass0SmsReassemblyStore::OpenStoreL()");
+ TFileName pathName;
+ CReassemblyStoreUtility::PrivatePath(iFs, pathName);
+ //Create the directory if it is not created.
+ iFs.MkDirAll(pathName);
+ // If any one file becomes corrupt or does not exist then we have to create both files.
+ if (iPreallocatedFile->IsFileOK() && iPermanentFileStore->IsFileOK())
+ {
+ iPreallocatedFile->OpenL();
+ iPermanentFileStore->OpenL();
+ }
+ else
+ {
+ iPreallocatedFile->CreateL();
+ iPermanentFileStore->CreateL();
+ }
+ PopulateEntryArrayL(iEntryArray);
+ iGuardTimer->EnableGuardTimer();
+ }
+
+/**
+It closes the class 0 re-assembly store.
+
+@internalComponent
+*/
+void CClass0SmsReassemblyStore::Close()
+ {
+ LOGSMSPROT1("CClass0SmsReassemblyStore::CloseStore()");
+ iGuardTimer->DisableGuardTimer();
+ iEntryArray.Reset();
+ iPreallocatedFile->Close();
+ iPermanentFileStore->Close();
+ }
+
+/**
+It populates the entry information stored in class 0 reassembly store.
+
+@param aEntryArray reference to entry array.
+
+@internalComponent
+*/
+void CClass0SmsReassemblyStore::PopulateEntryArrayL(CArrayFix<TReassemblyEntry>& aEntryArray)
+ {
+ LOGSMSPROT1("CClass0SmsReassemblyStore::PopulateEntryArrayL()");
+ aEntryArray.Reset();
+ //Populate Entries from Pre-allocated file.
+ for (TInt count = 0; count < iPreallocatedFile->Entries().Count(); count++)
+ {
+ TReassemblyEntry entry;
+ entry.SetReference(iPreallocatedFile->Entries()[count].Reference());
+ entry.SetTotal(iPreallocatedFile->Entries()[count].Total());
+ entry.SetCount(iPreallocatedFile->Entries()[count].Count()+iPreallocatedFile->Entries()[count].NumberOfPDUsForwardToClient());
+ entry.SetLogServerId(iPreallocatedFile->Entries()[count].LogServerId());
+
+ // Check that descriptor2 (sms address )is not corrupted
+ TPtrC ptr = iPreallocatedFile->Entries()[count].Description2();
+
+ if (ptr.Length() <= CSmsAddress::KSmsAddressMaxAddressLength)
+ {
+ entry.SetDescription2(iPreallocatedFile->Entries()[count].Description2());
+ }
+
+ entry.SetPduType(iPreallocatedFile->Entries()[count].PduType());
+ entry.SetStorage(iPreallocatedFile->Entries()[count].Storage());
+ entry.SetTime(iPreallocatedFile->Entries()[count].Time());
+ entry.SetPassedToClient(iPreallocatedFile->Entries()[count].PassedToClient());
+ aEntryArray.AppendL(entry);
+ }
+
+ /*
+ Then populate the entries from permanent store file. It is needed
+ because permanent store file might contain few mesages.
+ But before populating the entry information it is needed to cleanup
+ the entries in permanent store file. It is needed to ensure that permanent file
+ clean itself with pre-allocated file. There migth be a scenario where
+ user has deleted a message but the corresponding message has not been
+ deleted from permanent store file due to out-of-disk condition.
+ And also at the time of forwarding an incomplete message a forwarded
+ message has not been deleted due to above reason. But the entry/PDU is
+ invalid because it is no more in the pre-allocated file which
+ contains master header info.
+ */
+ TInt ret = CleanReassemblyEntries();
+
+ if (ret == KErrNone)
+ {
+ /*
+ In this case permanent store file contains correct information.
+ So populate Entry information from Permanent store file.
+ In this case only count information needs to be updated.
+ */
+ TInt permanentFileStoreIndex;
+ for (TInt i=0; i<aEntryArray.Count(); i++)
+ {
+ permanentFileStoreIndex=KErrNotFound;
+ iPermanentFileStore->MatchEntryToExistingMessage(aEntryArray[i], permanentFileStoreIndex);
+ if (permanentFileStoreIndex!=KErrNotFound)
+ {
+ aEntryArray[i].SetCount(aEntryArray[i].Count() + iPermanentFileStore->Entries()[permanentFileStoreIndex].Count());
+ if (aEntryArray[i].Count() > aEntryArray[i].Total())
+ {
+ aEntryArray[i].SetCount(aEntryArray[i].Total());
+ }
+ }
+ }
+ }
+ else if (ret == KErrDiskFull)
+ {
+ LOGSMSPROT1("CleanReassemblyEntries() returns KErrDiskFull");
+ /*
+ In this case permanent store file contains incorrect information.
+ For example forwarded message might be still stored in this store.
+ Because it has not been deleted due to out-of-disk condition.
+ So be careful at the time of updating the count information
+ about the message.
+ */
+ TInt permanentFileStoreIndex;
+ for (TInt i=0; i<aEntryArray.Count(); i++)
+ {
+ permanentFileStoreIndex=KErrNotFound;
+ iPermanentFileStore->MatchEntryToExistingMessage(aEntryArray[i], permanentFileStoreIndex);
+ if (permanentFileStoreIndex!=KErrNotFound)
+ {
+ TSmsPreAllocatedFileStoreReassemblyEntry entry = iPreallocatedFile->Entries()[i];
+ if (entry.NumberOfPDUsForwardToClient() > 0)
+ {
+ //Internalize the entries.
+ CSmsBuffer* buffer = CSmsBuffer::NewL();
+ CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer);
+ CleanupStack::PushL(smsMessage);
+
+ CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
+ CleanupStack::PushL(indexArray);
+ CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
+ CleanupStack::PushL(smsArray);
+ //Internalize to check whether removed PDUs still stored in Permanent store file.
+ iPermanentFileStore->InternalizeEntryL(permanentFileStoreIndex, *smsMessage, *indexArray, *smsArray);
+ TInt noOfForwardedEntries=0;
+ for (TInt j=0; j<indexArray->Count() ;j++)
+ {
+ TUint8 bitMapIndex = (indexArray->At(j)-1)/8;
+ TUint8 bitPos = (indexArray->At(j)-1)%8;
+ TUint8 bitMap;
+ entry.GetBitMap(bitMapIndex, bitMap);
+ TUint8 tmpBitMap = 1;
+ tmpBitMap <<= bitPos;
+ if (tmpBitMap == (bitMap & tmpBitMap))
+ {
+ noOfForwardedEntries++;
+ }
+ }
+ TInt count = iPermanentFileStore->Entries()[permanentFileStoreIndex].Count() - noOfForwardedEntries;
+ aEntryArray[i].SetCount(aEntryArray[i].Count() + count);
+
+ CleanupStack::PopAndDestroy(3, smsMessage); // smsMessage, indexArray, smsArray
+ }
+ else
+ {
+ aEntryArray[i].SetCount(aEntryArray[i].Count() + iPermanentFileStore->Entries()[permanentFileStoreIndex].Count());
+ }
+ }
+ }
+ }
+ else
+ {
+ User::Leave(ret);
+ }
+ }
+
+/**
+It sets the disk space status.
+If disk space is full, then class 0 re-assembly store stores the incoming message in
+pre-allocated file. Otherwise it stores the message in permanent store file.
+*/
+void CClass0SmsReassemblyStore::SetDiskSpaceState(TSmsDiskSpaceMonitorStatus aDiskSpaceStatus)
+ {
+ LOGSMSPROT1("CClass0SmsReassemblyStore::SetDiskSpaceState()");
+ iDiskSpaceStatus = aDiskSpaceStatus;
+ }
+
+/*
+It adds the new message in class 0 reassembly store.
+It first tries to add the message in permanent store file. If it is
+successful, then it adds the entry information in pre-allocated file.
+Because pre-allocated file contains master header entry information.
+Otherwise (if disk space is full), it adds the message in pre-allocated file.
+
+@param aSmsMessage reference to sms message to be added.
+@param aGsmSms reference to GsmSms object to be added.
+
+@internalComponent
+*/
+void CClass0SmsReassemblyStore::AddNewMessageL(CSmsMessage& aSmsMessage,const TGsmSms& aGsmSms)
+ {
+ LOGSMSPROT1("CClass0SmsReassemblyStore::AddNewMessageL");
+
+ // Add entry in permanent store file
+ TInt index;
+ TInt ret = KErrNone;
+
+ if (iDiskSpaceStatus == ESmsDiskSpaceFull)
+ {
+ ret = KErrDiskFull;
+ }
+ else
+ {
+ TRAP(ret, iPermanentFileStore->AddNewMessageL(index, aSmsMessage, aGsmSms));
+ }
+
+ if (ret == KErrNone)
+ {
+ // Add a new entry in pre-allocated file
+ TSmsPreAllocatedFileStoreReassemblyEntry tmpEntry;
+ //Fill-up entry information...
+ CReassemblyStoreUtility::PopulateEntry(tmpEntry, aSmsMessage, 1);
+
+ //The properties below need to be set only once when a PDU of a new message arrives.
+ tmpEntry.SetStatus((RMobileSmsStore::TMobileSmsStoreStatus)aSmsMessage.Status());
+ tmpEntry.SetUTCOffset(aSmsMessage.UTCOffset());
+ tmpEntry.SetDecodedOnSIM(aSmsMessage.DecodedOnSim());
+ tmpEntry.SetForwardToClient(aSmsMessage.ForwardToClient());
+ //Set KErrNotFound because message corresponding to
+ //this entry is not in this pr-allocated file.
+ tmpEntry.SetPreAllocatedStorageId(KErrNotFound);
+ //Has to set 0 because PDU is stored in Permanent store file instead of pre-allocated file.
+ tmpEntry.SetCount(0);
+
+ iPreallocatedFile->AddEntryL(tmpEntry);
+ }
+ else if (ret == KErrDiskFull)
+ {
+ // Add the new message in pre-allocated file
+ iPreallocatedFile->AddNewMessageL(index, aSmsMessage, aGsmSms);
+ }
+ else
+ {
+ User::Leave(ret);
+ }
+ }
+
+/*
+It updates the existing message in class 0 re-assembly store.
+
+@param aSmsMessage reference to sms message to be updated.
+@param aGsmSms reference to GsmSms object to be added.
+@param aDuplicateMsgRef boolean value (output) indicates whether the added PDU is a duplicate or not.
+@param aDuplicateSlot boolean value (output) indicates whether the added PDU is a duplicate enumerated PDU.
+
+@internalComponent
+*/
+void CClass0SmsReassemblyStore::UpdateExistingMessageL(CSmsMessage& aSmsMessage, const TGsmSms& aGsmSms, TBool& aDuplicateMsgRef, TBool& aDuplicateSlot)
+ {
+ LOGSMSPROT1("CClass0SmsReassemblyStore::UpdateExistingMessageL()");
+
+ aDuplicateMsgRef = EFalse;
+ aDuplicateSlot = EFalse;
+
+ CSmsBuffer* buffer = CSmsBuffer::NewL();
+ CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer);
+ CleanupStack::PushL(smsMessage);
+
+ CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
+ CleanupStack::PushL(indexArray);
+ CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
+ CleanupStack::PushL(smsArray);
+
+ //Internalize stored message in permanent store file
+ TReassemblyEntry entry;
+ CReassemblyStoreUtility::PopulateEntry(entry, aSmsMessage, 1);
+ TInt permanentStoreIndex;
+ iPermanentFileStore->MatchEntryToExistingMessage(entry, permanentStoreIndex);
+ if (permanentStoreIndex!=KErrNotFound)
+ {
+ iPermanentFileStore->InternalizeEntryL(permanentStoreIndex, *smsMessage, *indexArray, *smsArray);
+ }
+
+ //Internalize stored message in pre-allocated file
+ TInt preAllocatedFileIndex;
+ iPreallocatedFile->MatchEntryToExistingMessage(entry, preAllocatedFileIndex);
+ if (preAllocatedFileIndex!=KErrNotFound)
+ {
+ iPreallocatedFile->InternalizeEntryL(preAllocatedFileIndex, *smsMessage, *indexArray, *smsArray);
+ }
+ else
+ {
+ //This condition should never arise
+ User::Leave(KErrNotFound);
+ }
+
+ //
+ // Check if this is a duplicated enumerated PDU (e.g. on the SIM or phone memory)
+ // or a duplicated PDU (e.g. in the Reassembly Store)...
+ //
+ TInt concatPDUIndex = aSmsMessage.SmsPDU().ConcatenatedMessagePDUIndex();
+
+ if (smsMessage->Storage() == CSmsMessage::ESmsSIMStorage ||
+ smsMessage->Storage() == CSmsMessage::ESmsCombinedStorage)
+ {
+ //
+ // In most cases this PDU is being enumerated, but not always. It is
+ // possible for the PDU to be stored on the SIM first before it is
+ // received.
+ //
+ const TGsmSmsSlotEntry& newSlot = aSmsMessage.iSlotArray[0];
+ TInt slotArrayCount = smsMessage->iSlotArray.Count();
+
+ for (TInt slotNum = 0; slotNum < slotArrayCount; slotNum++ )
+ {
+ const TGsmSmsSlotEntry& slot = smsMessage->iSlotArray[slotNum];
+
+ if (slot.iIndex == newSlot.iIndex && slot.iStore == newSlot.iStore)
+ {
+ LOGSMSPROT1("CSmsReassemblyStore::UpdateExistingMessageL(): Duplicate enumerated PDU.");
+
+ // It is a duplicate that was already stored on the SIM...
+ aDuplicateSlot = ETrue;
+ break;
+ }
+ }
+ }
+
+ TInt indexArrayCount = indexArray->Count();
+
+ for (TInt index = 0; index < indexArrayCount; index++ )
+ {
+ if (indexArray->At(index) == concatPDUIndex)
+ {
+ LOGSMSPROT1("CSmsReassemblyStore::UpdateExistingMessageL(): Duplicate concatenated PDU.");
+
+ // The PDU is already stored in the reassembly store.
+ aDuplicateMsgRef = ETrue;
+ break;
+ }
+ }
+
+ //Check whether this PDU is part of forwarded PDU.
+ TSmsPreAllocatedFileStoreReassemblyEntry preAllocatedFileEntry = iPreallocatedFile->Entries()[preAllocatedFileIndex];
+ if (preAllocatedFileEntry.NumberOfPDUsForwardToClient() > 0)
+ {
+ TUint8 bitMapIndex = (concatPDUIndex-1)/8;
+ TUint8 bitPos = (concatPDUIndex-1)%8;
+ TUint8 bitMap;
+ preAllocatedFileEntry.GetBitMap(bitMapIndex, bitMap);
+ TUint8 tmpBitMap = 1;
+ tmpBitMap <<= bitPos;
+ if (tmpBitMap == (bitMap & tmpBitMap))
+ {
+ aDuplicateMsgRef = ETrue;
+ }
+ }
+
+ if (aDuplicateMsgRef || aDuplicateSlot)
+ {
+ CleanupStack::PopAndDestroy(3, smsMessage); // smsMessage, smsArray, indexArray
+ return;
+ }
+
+ //
+ // If the PDU is stored then add the slot information...
+ //
+ if (aSmsMessage.Storage() == CSmsMessage::ESmsSIMStorage ||
+ aSmsMessage.Storage() == CSmsMessage::ESmsCombinedStorage)
+ {
+ smsMessage->AddSlotL(aSmsMessage.iSlotArray[0]);
+ }
+
+ //
+ // If the PDU is Unsent or Unread, then store that information...
+ //
+ NMobileSmsStore::TMobileSmsStoreStatus status = aSmsMessage.Status();
+
+ if (status == NMobileSmsStore::EStoredMessageUnsent ||
+ status == NMobileSmsStore::EStoredMessageUnread)
+ {
+ smsMessage->SetStatus(status);
+ }
+
+ /*
+ Below logic is written in keeping view of different scenarios that might occur here:
+ (1) Previous PDUs are in Permanent store file, this PDU arrives in out-of-disk condition (so will be stored in Pre-allocated file).
+ (2) Previous PDUs are in Pre-allocated file (means PDU arrives in out-of-disk condition), this PDU arrives in normal condition.
+ (3) Previous PDUs are in Permanent store file, this PDU also arrives in normal condition.
+ (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.
+ */
+
+ //Always first try to store the message in permanent store file.
+ //In case of out-of-disk condition store the message in pre-allocated file
+ TInt ret = KErrNone;
+ if (iDiskSpaceStatus == ESmsDiskSpaceFull)
+ {
+ ret = KErrDiskFull;
+ }
+ else
+ {
+ if (permanentStoreIndex==KErrNotFound)
+ {
+ // See condition (2)
+ TInt tmpIndex;
+ TRAP(ret, iPermanentFileStore->AddNewMessageL(tmpIndex, aSmsMessage, aGsmSms));
+ }
+ else
+ {
+ CSmsBuffer* tmpBuffer = CSmsBuffer::NewL();
+ CSmsMessage* tmpSmsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, tmpBuffer);
+ CleanupStack::PushL(tmpSmsMessage);
+
+ indexArray->Reset();
+ smsArray->Reset();
+ iPermanentFileStore->InternalizeEntryL(permanentStoreIndex, *tmpSmsMessage, *indexArray, *smsArray);
+ /*
+ Check & remove those PDU from permanent store file which has already been
+ forwarded to client. Forwarded PDU might still remain in permanent store
+ file if it is deleted at the time of out-of-disk condition.
+ */
+ if (preAllocatedFileEntry.NumberOfPDUsForwardToClient()>0)
+ {
+ for (TInt j=indexArray->Count(); j>0 ;j--)
+ {
+ TUint8 bitMapIndex = (indexArray->At(j-1)-1)/8;
+ TUint8 bitPos = (indexArray->At(j-1)-1)%8;
+ TUint8 bitMap;
+ preAllocatedFileEntry.GetBitMap(bitMapIndex, bitMap);
+ TUint8 tmpBitMap = 1;
+ tmpBitMap <<= bitPos;
+ if (tmpBitMap == (bitMap & tmpBitMap))
+ {
+ indexArray->Delete(j-1);
+ smsArray->Delete(j-1);
+ }
+ }
+ }
+
+ indexArray->AppendL(concatPDUIndex);
+ smsArray->AppendL(aGsmSms);
+
+ TRAP(ret, iPermanentFileStore->UpdateExistingMessageL(permanentStoreIndex, *smsMessage, *indexArray, *smsArray));
+
+ CleanupStack::PopAndDestroy(1); //tmpSmsMessage
+ }
+ }
+
+ if (ret == KErrDiskFull)
+ {
+ iPreallocatedFile->UpdateExistingMessageL(preAllocatedFileIndex, aSmsMessage, concatPDUIndex, aGsmSms);
+ }
+ else if (ret!=KErrNone)
+ {
+ User::Leave(ret);
+ }
+
+ CleanupStack::PopAndDestroy(3, smsMessage); // smsMessage, indexArray, smsArray
+ }
+
+/*
+It retrieves class 0 message from re-assembly store.
+The message which match the passed entry information is returned from this function.
+
+@param aEntry reference to entry information.
+@param aSmsMessage reference to returned sms message.
+
+@internalComponent
+*/
+void CClass0SmsReassemblyStore::RetrieveMessageL(const TReassemblyEntry& aEntry, CSmsMessage& aSmsMessage)
+ {
+ CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
+ CleanupStack::PushL(indexArray);
+ CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
+ CleanupStack::PushL(smsArray);
+
+ GetSmsEntriesL(aEntry, aSmsMessage, *indexArray, *smsArray);
+
+ //There is no need to decode a single segment message
+ if (aEntry.Total()>1)
+ {
+ if (smsArray->Count() == aEntry.Total())
+ {
+ aSmsMessage.DecodeMessagePDUsL(*smsArray);
+ }
+ }
+ CleanupStack::PopAndDestroy(2, indexArray); //smsArray, indexArray
+ }
+
+/*
+It deletes the entry from re-assembly store.
+
+@param aEntry reference to entry information.
+
+@internalComponent
+*/
+void CClass0SmsReassemblyStore::DeleteEntryL(const TReassemblyEntry& aEntry)
+ {
+ TInt index;
+ iPreallocatedFile->MatchEntryToExistingMessage(aEntry, index);
+ if (index == KErrNotFound)
+ {
+ //This condition should never arise
+ User::Leave(KErrNotFound);
+ }
+ iPreallocatedFile->DeleteEntryL(index);
+ iPermanentFileStore->MatchEntryToExistingMessage(aEntry, index);
+ if (index != KErrNotFound)
+ {
+ TRAP_IGNORE(iPermanentFileStore->DeleteEntryL(index));
+ }
+ }
+
+/*
+It updates the log server id of the passed entry (message).
+
+@param aEntry reference to entry information.
+@param aLogId log id of the message to be updated.
+
+@internalComponent
+*/
+void CClass0SmsReassemblyStore::UpdateLogServerIdL(const TReassemblyEntry& aEntry, TLogId aLogServerId)
+ {
+ TInt index;
+ iPreallocatedFile->MatchEntryToExistingMessage(aEntry, index);
+ if (index == KErrNotFound)
+ {
+ //This condition should never arise
+ User::Leave(KErrNotFound);
+ }
+ iPreallocatedFile->UpdateLogServerIdL(index, aLogServerId);
+ }
+
+/*
+It sets the message passed to client or not. The message, which match the
+passed entry information, its passed to client value is set.
+
+@param aEntry reference to entry information.
+@param aBool boolean value indicating whether message is passed or not.
+
+@internalComponent
+*/
+void CClass0SmsReassemblyStore::SetPassedToClientL(const TReassemblyEntry& aEntry, TBool aBool)
+ {
+ TInt index;
+ iPreallocatedFile->MatchEntryToExistingMessage(aEntry, index);
+ if (index == KErrNotFound)
+ {
+ //This condition should never arise
+ User::Leave(KErrNotFound);
+ }
+ iPreallocatedFile->SetPassedToClientL(index, aBool);
+ }
+
+/**
+It forwards the complete class 0 messages to client.
+It checks whether the received object is complete or not.
+If it is complete, then it forwards the complete message to client.
+Otherwise it forms the message & forward the message to client.
+In this it might be possible to forward multiple incomplete message.
+
+@param aSmsComm a reference to aSmsComm object which implemented the events.
+
+@param aSmsMessage a reference to sms message object. This sms message must be class 0 messages.
+
+@param aOriginalSmsAddr pointer to the address of the sender of a previously sent
+
+@param aOriginalSmsMessage pointer to a message previously sent matched to the received
+ one (e.g. status report). Null if not matched.
+
+@param aDes user data for the deliver report acknowledging this message to the SC.
+ Filled in by the observer.
+
+@internalComponent
+*/
+void CClass0SmsReassemblyStore::ForwardCompleteClass0SmsMessagesL(MSmsComm& aSmsComm, const CSmsMessage& aSmsMessage,const TSmsAddr* aOriginalSmsAddr,const CSmsMessage* aOriginalSmsMessage,TDes& aDes)
+ {
+ TBool passedToClient=ETrue;
+
+ if (aSmsMessage.IsComplete())
+ {
+ //Message is complete so forward it.
+ TInt ret = aSmsComm.ProcessMessageL(aSmsMessage, aOriginalSmsAddr, aOriginalSmsMessage, aDes);
+ if (ret!=KErrNone)
+ {
+ passedToClient = EFalse;
+ }
+ }
+ else
+ {
+ /*
+ Message is not complete, but re-assembly store contains other constituent PDU
+ of the message which makes the message complete.
+
+ In case of class 0 messages, it is possible to forward the incomplete messages. So after forwarding
+ the incomplete message, if we receive other constituent PDU of that message then in that case we
+ might receive all the constituent PDU of that message but aSmsMesssage will contain partial complete message.
+ */
+ TReassemblyEntry entry;
+ CReassemblyStoreUtility::PopulateEntry(entry, aSmsMessage, 1);
+
+ CSmsBuffer* buffer = CSmsBuffer::NewL();
+ CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer );
+ CleanupStack::PushL( smsMessage );
+
+ CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
+ CleanupStack::PushL(indexArray);
+ CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
+ CleanupStack::PushL(smsArray);
+
+ GetSmsEntriesL(entry, *smsMessage, *indexArray, *smsArray);
+ SortPDUsL(*indexArray, *smsArray);
+
+ CArrayFixFlat<TGsmSms>* tmpSmsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
+ CleanupStack::PushL(tmpSmsArray);
+
+ //Form the sequence of incomplete message & forward it to client.
+ TInt startSeqIndex(0), endSeqIndex(0);
+ TInt i;
+ do
+ {
+ i = startSeqIndex;
+ for (; i < indexArray->Count() - 1; i++)
+ {
+ if (indexArray->At(i) + 1 != indexArray->At(i+1))
+ {
+ endSeqIndex = i;
+ break;
+ }
+ }
+
+ if (i == (indexArray->Count() - 1))
+ {
+ endSeqIndex = i;
+ }
+
+ tmpSmsArray->Reset();
+ for (TInt j = startSeqIndex; j <= endSeqIndex; j++)
+ {
+ tmpSmsArray->AppendL(smsArray->At(j));
+ }
+
+ if (tmpSmsArray->Count() == entry.Total())
+ {
+ smsMessage->DecodeMessagePDUsL(*tmpSmsArray);
+ }
+ else
+ {
+ //Build the partial complete message.
+ if (endSeqIndex == (indexArray->Count() - 1))
+ {
+ smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, ETrue);
+ }
+ else
+ {
+ smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, EFalse);
+ }
+ }
+
+ //Forward the partial complete message to client.
+ TInt ret=KErrNone;
+ TRAP(ret, aSmsComm.ProcessMessageL(*smsMessage, aOriginalSmsAddr, aOriginalSmsMessage, aDes));
+ if (ret != KErrNone)
+ {
+ passedToClient = EFalse;
+ }
+ startSeqIndex = endSeqIndex + 1;
+ endSeqIndex = startSeqIndex;
+ }
+ while (startSeqIndex < indexArray->Count());
+
+ CleanupStack::PopAndDestroy(4); //tmpSmsArray, indexArray, smsArray, smsMessage
+ }
+
+ if(passedToClient)
+ {
+ SetMessagePassedToClientL(aSmsMessage);
+ }
+
+ //If the latest segement exceeds the limitation, then we can't wait till ack.
+ //So call ProcessMessageIfExceedLimitationL() function & delete the oldest message.
+ if (IsExceedLimitation())
+ {
+ ProcessMessageIfExceedLimitationL(aSmsComm);
+ }
+ }
+
+/**
+It frees the space by forwarding the class 0 message if class 0 re-assembly store
+exceeds limitation (max class 0 message, max reserved pdu segment).
+
+@param aSmsComm a reference to aSmsComm object which implemented the events.
+
+@internalComponent
+*/
+void CClass0SmsReassemblyStore::ProcessMessageIfExceedLimitationL(MSmsComm& aSmsComm)
+ {
+ //Add Comment
+ TInt class0MsgCount = iEntryArray.Count();
+ TInt noOfMsgStoredInPreAllocatedFile = iPreallocatedFile->NumberOfPDUStored();
+ if ((class0MsgCount > iMaxClass0Msg)
+ || (noOfMsgStoredInPreAllocatedFile >= iMaxPDUSeg))
+ {
+ CSmsBuffer* buffer = CSmsBuffer::NewL();
+ CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer );
+ CleanupStack::PushL( smsMessage );
+
+ CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
+ CleanupStack::PushL(indexArray);
+ CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
+ CleanupStack::PushL(smsArray);
+
+ //Add Comment
+ TInt index;
+ if (class0MsgCount > iMaxClass0Msg)
+ {
+ index = GetIndexOfOldestMessage();
+ }
+ else
+ {
+ index = GetIndexOfOldestMessageFromReservedFileL();
+ }
+
+ TReassemblyEntry entry = iEntryArray[index];
+
+ GetSmsEntriesL(entry, *smsMessage, *indexArray, *smsArray);
+
+ SortPDUsL(*indexArray, *smsArray);
+
+ CArrayFixFlat<TGsmSms>* tmpSmsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
+ CleanupStack::PushL(tmpSmsArray);
+
+ //Form the message & forward it to client.
+ TInt startSeqIndex(0), endSeqIndex(0);
+ TInt i;
+ do
+ {
+ i = startSeqIndex;
+ for (; i < indexArray->Count() - 1; i++)
+ {
+ if (indexArray->At(i) + 1 != indexArray->At(i+1))
+ {
+ endSeqIndex = i;
+ break;
+ }
+ }
+ if (i == (indexArray->Count() - 1))
+ {
+ endSeqIndex = i;
+ }
+ tmpSmsArray->Reset();
+
+ for (TInt j = startSeqIndex; j <= endSeqIndex; j++)
+ {
+ tmpSmsArray->AppendL(smsArray->At(j));
+ }
+
+ if (entry.IsComplete())
+ {
+ if (tmpSmsArray->Count() == entry.Total())
+ {
+ smsMessage->DecodeMessagePDUsL(*tmpSmsArray);
+ }
+ else
+ {
+ //Build the partial complete message.
+ if (endSeqIndex == (indexArray->Count() - 1))
+ {
+ smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, ETrue);
+ }
+ else
+ {
+ smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, EFalse);
+ }
+ }
+ }
+ else
+ {
+ //Build the partial complete message.
+ smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, EFalse);
+ }
+ //Forward the partial complete message to client.
+ TBuf16<CSmsPDUProcessor::ESmsMaxDeliverReportBufferSize> buffer;
+ TRAP_IGNORE(aSmsComm.ProcessMessageL(*smsMessage, NULL, NULL, buffer));
+
+ /*
+ Can't do much. So free the reserved space & also stored the information
+ related to forwarded message. If the message is complete then delete
+ the complete message (see the condition after the while loop)rather
+ than freeing the memory. No need to store the complete messages forwaded
+ info.
+ */
+ if ((noOfMsgStoredInPreAllocatedFile > iMaxPDUSeg) && (!entry.IsComplete()))
+ {
+ SetIncompleteMessageForwardedToClientL(*smsMessage);
+ }
+ startSeqIndex = endSeqIndex + 1;
+ endSeqIndex = startSeqIndex;
+ }
+ while (startSeqIndex < indexArray->Count());
+ //Can't do much. So removed the oldest message.
+ if ((class0MsgCount > iMaxClass0Msg) ||
+ ((noOfMsgStoredInPreAllocatedFile > iMaxPDUSeg) && (entry.IsComplete())))
+ {
+ DeleteMessageL(*smsMessage, EFalse);
+ }
+ CleanupStack::PopAndDestroy(4); //tmpSmsArray, indexArray, smsArray, smsMessage
+ }
+ }
+
+/**
+Guard timer calls this function when timer expires.
+It goes through all the messages stored in re-assembly store & forwards those message
+whose time has expired.
+It is also called when a new observer is added or a PDU has been received and successfully
+processed. It is also called from ProcessCompleteClass0SmsMessagesL.
+
+@internalComponent
+*/
+void CClass0SmsReassemblyStore::ProcessTimeoutMessageL()
+ {
+ LOGSMSPROT1("CClass0SmsReassemblyStore::ProcessTimeoutMessageL()");
+ TBool passedToClient=ETrue;
+ TInt count=iEntryArray.Count();
+
+ CSmsBuffer* buffer = CSmsBuffer::NewL();
+ CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer );
+ CleanupStack::PushL( smsMessage );
+
+ CArrayFix<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(KFlatArrayGranularity);
+ CleanupStack::PushL(indexArray);
+ CArrayFixFlat<TGsmSms>* smsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
+ CleanupStack::PushL(smsArray);
+
+ CArrayFixFlat<TGsmSms>* tmpSmsArray = new(ELeave) CArrayFixFlat<TGsmSms>(KFlatArrayGranularity);
+ CleanupStack::PushL(tmpSmsArray);
+
+ TTime time;
+ time.UniversalTime();
+
+ TTimeIntervalSeconds timeOutInSecs = iGuardTimeOut*3600;
+
+ for (TInt k=count-1; k>=0; k--)
+ {
+ if (!iEntryArray[k].PassedToClient())
+ {
+ TTimeIntervalSeconds diffInSecs;
+ time.SecondsFrom(iEntryArray[k].Time(), diffInSecs);
+ indexArray->Reset();
+ smsArray->Reset();
+ if (diffInSecs >= timeOutInSecs)
+ {
+ GetSmsEntriesL(iEntryArray[k], *smsMessage, *indexArray, *smsArray);
+ SortPDUsL(*indexArray, *smsArray);
+
+ //Form the message & forward it to client.
+ TInt startSeqIndex(0), endSeqIndex(0);
+ TInt i;
+ do
+ {
+ i = startSeqIndex;
+ for (; i < indexArray->Count() - 1; i++)
+ {
+ if (indexArray->At(i) + 1 != indexArray->At(i+1))
+ {
+ endSeqIndex = i;
+ break;
+ }
+ }
+ if (i == (indexArray->Count() - 1))
+ {
+ endSeqIndex = i;
+ }
+ tmpSmsArray->Reset();
+ for (TInt j = startSeqIndex; j <= endSeqIndex; j++)
+ {
+ tmpSmsArray->AppendL(smsArray->At(j));
+ }
+
+ if (iEntryArray[k].IsComplete())
+ {
+ if (tmpSmsArray->Count() == iEntryArray[k].Total())
+ {
+ smsMessage->DecodeMessagePDUsL(*tmpSmsArray);
+ }
+ else
+ {
+ //Build the partial complete message.
+ if (endSeqIndex == (indexArray->Count() - 1))
+ {
+ smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, ETrue);
+ }
+ else
+ {
+ smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, EFalse);
+ }
+ }
+ }
+ else
+ {
+ //Build the partial complete message.
+ if (endSeqIndex == (indexArray->Count() - 1))
+ {
+ smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, ETrue);
+ }
+ else
+ {
+ smsMessage->DecodePartialCompleteMessagePDUsL(*tmpSmsArray, EFalse);
+ }
+ }
+
+ //Forward the partial complete message to client.
+ TInt ret=KErrNone;
+ TBuf16<CSmsPDUProcessor::ESmsMaxDeliverReportBufferSize> buffer;
+ ret = iSmsComm.ProcessMessageL(*smsMessage, NULL, NULL, buffer);
+ if (ret != KErrNone)
+ {
+ passedToClient = EFalse;
+ }
+
+ startSeqIndex = endSeqIndex + 1;
+ endSeqIndex = startSeqIndex;
+ }
+ while (startSeqIndex < indexArray->Count());
+
+ if(passedToClient)
+ {
+ SetMessagePassedToClientL(*smsMessage);
+ }
+ } //diffInSecs >= timeOutInSecs
+ } //!iEntryArray[k].PassedToClient()
+ } //For k loop
+ CleanupStack::PopAndDestroy(4); //tmpSmsArray, indexArray, smsArray, smsMessage
+ }
+
+/**
+It sets the bit-map of forwarded incomplete message to client.
+It frees up the memory by removing the forwarded PDUs.
+
+@param aSmsMessage a reference to forwaded incomplete class 0 sms message object.
+
+@internalComponent
+*/
+void CClass0SmsReassemblyStore::SetIncompleteMessageForwardedToClientL(const CSmsMessage& aSmsMessage)
+ {
+ LOGSMSPROT1("CClass0SmsReassemblyStore::SetIncompleteMessageForwardedToClientL()");
+ TInt index = KErrNotFound;
+
+ if (aSmsMessage.IsComplete())
+ {
+ LOGSMSPROT1("This function must be called when message is incomplete");
+ User::Leave(KErrArgument);
+ }
+
+ if (FindMessageL(aSmsMessage, EFalse, index))
+ {
+ CIncompleteClass0MessageInfo& incompleteClass0MsgInfo = (CIncompleteClass0MessageInfo &) aSmsMessage.GetOperationsForNonIEL(ESmsIncompleteClass0MessageParameter);
+ // Retrieve incomplete class 0 message information & process
+ TInt startPos, endPos;
+ TBool isLastMessage;
+ incompleteClass0MsgInfo.GetIncompleteMessageInfoL(startPos, endPos, isLastMessage);
+
+ const TReassemblyEntry& entry = iEntryArray[index];
+
+ //Remove the forwarded PDU entries from pre-allocated file
+ TInt preAllocatedFileIndex=KErrNotFound;
+ iPreallocatedFile->MatchEntryToExistingMessage(entry, preAllocatedFileIndex);
+ if (preAllocatedFileIndex!=KErrNotFound)
+ {
+ BeginTransactionLC();
+ iPreallocatedFile->RemovePDUsL(preAllocatedFileIndex, startPos, endPos);
+ iPreallocatedFile->StoreForwardedPDUsInfoL(preAllocatedFileIndex, startPos, endPos);
+ CommitTransactionL();
+ }
+ else
+ {
+ //This situation should never arise
+ User::Leave(KErrNotFound);
+ }
+
+ //Remove the forwarded PDU entries from permanent store file
+ TInt permanentStoreIndex=KErrNotFound;
+ iPermanentFileStore->MatchEntryToExistingMessage(entry, permanentStoreIndex);
+ if (permanentStoreIndex!=KErrNotFound)
+ {
+ TRAP_IGNORE(BeginTransactionLC();
+ iPermanentFileStore->RemovePDUsL(permanentStoreIndex, startPos, endPos);
+ CommitTransactionL(););
+ }
+ }
+ }
+
+/**
+This function is needed to ensure that permanent file
+clean itself with pre-allocated file.
+There migth be a scenario where user has deleted a message
+but the corresponding message has not been deleted from permanent store file
+due to out-of-disk condition. But the entry is invalid because
+it is no more in the pre-allocated file which contains master header info.
+
+@return the error code.
+
+@internalComponent
+*/
+TInt CClass0SmsReassemblyStore::CleanReassemblyEntries()
+ {
+ LOGSMSPROT1("CleanReassemblyEntries");
+ const CArrayFix<TSmsPreAllocatedFileStoreReassemblyEntry>& preAllocatedFileEntryArray = iPreallocatedFile->Entries();
+ TInt ret=KErrNone;
+ TRAP(ret, BeginTransactionLC();
+ iPermanentFileStore->CleanupEntriesL(preAllocatedFileEntryArray);
+ CommitTransactionL(););
+
+ if (ret == KErrDiskFull)
+ {
+ LOGSMSPROT1("CleanupEntriesL returns KErrDiskFull");
+ /*
+ Get access to reserve memory, call again to clean the entries with compact.
+ Compact needs to be called at this instance because permanent store
+ will use reserve disk space to delete, but after deletion reserve
+ disk space will be freed. So compact will make sure that reserve disk
+ space is not used after compaction.
+ */
+ iFs.GetReserveAccess(KStoreDrive);
+ TRAP(ret, BeginTransactionLC();
+ iPermanentFileStore->CleanupEntriesWithCompactL(preAllocatedFileEntryArray);
+ CommitTransactionL(););
+ LOGSMSPROT2("CleanupEntriesWithCompactL returns %d", ret);
+ iFs.ReleaseReserveAccess(KStoreDrive);
+ }
+ return ret;
+ }
+
+/**
+It returns the SMS entries (sms messages, sms pdu arrays & the corresponding index array)
+from its permanent store & pre-allocated file.
+
+@param aEntry reference to entry information. The message which match this entry information
+ is returned to caller of the function.
+@param aSmsMessage a reference to class 0 sms message object.
+@param aIndexArray a reference to the array of pdu index.
+@param aSmsArray a reference to the array of pdu.
+
+@internalComponent
+*/
+void CClass0SmsReassemblyStore::GetSmsEntriesL(const TReassemblyEntry& aEntry, CSmsMessage& aSmsMessage, CArrayFix<TInt>& aIndexArray, CArrayFix<TGsmSms>& aSmsArray)
+ {
+ LOGSMSPROT1("CClass0SmsReassemblyStore::GetSmsEntriesL()");
+ TInt permanentStoreIndex=KErrNotFound;
+ iPermanentFileStore->MatchEntryToExistingMessage(aEntry, permanentStoreIndex);
+ if (permanentStoreIndex!=KErrNotFound)
+ {
+ iPermanentFileStore->InternalizeEntryL(permanentStoreIndex, aSmsMessage, aIndexArray, aSmsArray);
+ }
+ else
+ {
+ LOGSMSPROT1("No PDUs in Permanent store file");
+ }
+
+ TInt preAllocatedFileIndex=KErrNotFound;
+ iPreallocatedFile->MatchEntryToExistingMessage(aEntry, preAllocatedFileIndex);
+ if (preAllocatedFileIndex!=KErrNotFound)
+ {
+ iPreallocatedFile->InternalizeEntryL(preAllocatedFileIndex, aSmsMessage, aIndexArray, aSmsArray);
+
+ //Filter forwarde PDU here..this condition might arise if the PDU
+ //could not be deleted at the time of OOD condition from permanent store file.
+ TSmsPreAllocatedFileStoreReassemblyEntry preAllocatedFileEntry = iPreallocatedFile->Entries()[preAllocatedFileIndex];
+ if (preAllocatedFileEntry.NumberOfPDUsForwardToClient() > 0)
+ {
+ for (TInt j=aIndexArray.Count(); j>0 ;j--)
+ {
+ TUint8 bitMapIndex = (aIndexArray.At(j-1)-1)/8;
+ TUint8 bitPos = (aIndexArray.At(j-1)-1)%8;
+ TUint8 bitMap;
+ preAllocatedFileEntry.GetBitMap(bitMapIndex, bitMap);
+ TUint8 tmpBitMap = 1;
+ tmpBitMap <<= bitPos;
+ if (tmpBitMap == (bitMap & tmpBitMap))
+ {
+ aIndexArray.Delete(j-1);
+ aSmsArray.Delete(j-1);
+ }
+ }
+ }
+
+ if (permanentStoreIndex==KErrNotFound)
+ {
+ //In this scenario a CSmsMessage object has to be created from the existing PDU in
+ //pre-allocated file & then serialized into aSmsMessage.
+ LOGSMSPROT2("Number of PDUs in Pre-allocated file %d", aIndexArray.Count());
+ if (aIndexArray.Count() > 0)
+ {
+ CSmsBuffer* smsBuffer = CSmsBuffer::NewL();
+ CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, aSmsArray.At(0), smsBuffer, EFalse, ETrue);
+ CleanupStack::PushL(smsMessage);
+
+ //Update sms messages's properties.
+ smsMessage->SetStorage(aSmsMessage.Storage());
+ smsMessage->SetStatus((NMobileSmsStore::TMobileSmsStoreStatus)aSmsMessage.Status());
+ smsMessage->SetLogServerId(aSmsMessage.LogServerId());
+ smsMessage->SetTime(aSmsMessage.Time());
+ smsMessage->SetUTCOffset(aSmsMessage.UTCOffset());
+ smsMessage->SetDecodedOnSIM(aSmsMessage.DecodedOnSim());
+ smsMessage->SetForwardToClient(aSmsMessage.ForwardToClient());
+ smsMessage->SetToFromAddressL(aSmsMessage.ToFromAddress());
+
+ CBufSeg* recvbufseg = CBufSeg::NewL(KSmsMaxSegmentLength);
+ CleanupStack::PushL(recvbufseg);
+ // Attempt to serialize this message into the buffer
+ RBufWriteStream writestream(*recvbufseg);
+ writestream.Open(*recvbufseg);
+ CleanupClosePushL(writestream);
+ writestream << *smsMessage;
+
+ // Initialize the read stream with the buffer
+ RBufReadStream readstream(*recvbufseg);
+ readstream.Open(*recvbufseg,0);
+ CleanupClosePushL(readstream);
+ // De-serialize the message from using the read stream
+ readstream >> aSmsMessage;
+ CleanupStack::PopAndDestroy(4); //readstream, writestream, recvbufseg, smsMessage
+ }
+ }
+ }
+ }
+
+/*
+It returns when the next timeout should occur.
+*/
+void CClass0SmsReassemblyStore::GetNextGuardTimeout(TTime& aNextTimeout)
+ {
+ TTime curTime;
+ curTime.UniversalTime();
+ TTimeIntervalSeconds timeOutInSecs = iGuardTimeOut*3600;
+ aNextTimeout = curTime + timeOutInSecs;
+
+ TInt class0ReassemblyStoreCount = iEntryArray.Count();
+
+ if (class0ReassemblyStoreCount > 0)
+ {
+ for (TInt i=0; i<class0ReassemblyStoreCount;i++)
+ {
+ TTime guradTimeout = iEntryArray[i].Time() + timeOutInSecs;
+ if ((guradTimeout > curTime) &&
+ (guradTimeout < aNextTimeout))
+ {
+ aNextTimeout = guradTimeout;
+ }
+ }
+ }
+ }
+
+/*
+It returns the index of oldest message in class 0 re-assembly store.
+*/
+TInt CClass0SmsReassemblyStore::GetIndexOfOldestMessage()
+ {
+ TInt index = 0;
+ TTime time = iEntryArray[index].Time();
+ for (TInt index2=1; index2 < iEntryArray.Count(); index2++)
+ {
+ if (iEntryArray[index2].Time() < time)
+ {
+ index = index2;
+ }
+ }
+ return index;
+ }
+
+/*
+It returns the index of oldest message in class 0 re-assembly store.
+*/
+TInt CClass0SmsReassemblyStore::GetIndexOfOldestMessageFromReservedFileL()
+ {
+ TInt index = KErrNotFound;
+ //Find the index of oldest message in pre-allocated file.
+ index = iPreallocatedFile->GetOldestMessageEntryIndex();
+ if (index == KErrNotFound)
+ {
+ //This condition should never arise
+ User::Leave(KErrNotFound);
+ }
+
+ //Compare the oldest pre-allocated message entry against class 0 reassembly store entry
+ //and return the index of class 0 reassembly store entry.
+ const TSmsPreAllocatedFileStoreReassemblyEntry& preAllocatedFileEntry = iPreallocatedFile->Entries()[index];
+
+ TInt reassemblyCount = iEntryArray.Count();
+ TInt count;
+ for (count = 0; count < reassemblyCount; count++)
+ {
+ TReassemblyEntry& entry = iEntryArray[count];
+
+ if (entry.Reference() == preAllocatedFileEntry.Reference() &&
+ entry.Total() == preAllocatedFileEntry.Total() &&
+ entry.PduType() == preAllocatedFileEntry.PduType() &&
+ entry.Storage() == preAllocatedFileEntry.Storage() &&
+ entry.Description2() == preAllocatedFileEntry.Description2())
+ {
+ //
+ // Found it!
+ //
+ index = count;
+ break;
+ }
+ }
+ if (count == reassemblyCount)
+ {
+ //This condition should never arise
+ User::Leave(KErrNotFound);
+ }
+ return index;
+ }
+
+/*
+It returns a boolean value indicating whether the limitation (max class 0 message,
+max pdu stored in pre-allocated file) imposed on class 0 reassembly store exceeds or not.
+*/
+TBool CClass0SmsReassemblyStore::IsExceedLimitation()
+ {
+ TInt class0MsgCount = iEntryArray.Count();
+ TInt noOfMsgStoredInPreAllocatedFile = iPreallocatedFile->NumberOfPDUStored();
+ if ((class0MsgCount > iMaxClass0Msg)
+ || (noOfMsgStoredInPreAllocatedFile > iMaxPDUSeg))
+ {
+ return ETrue;
+ }
+
+ return EFalse;
+ }
+
+/*
+This sorting algorithm is based on bubble sort
+*/
+void CClass0SmsReassemblyStore::SortPDUsL(CArrayFix<TInt>& aIndexArray, CArrayFix<TGsmSms>& aSmsArray)
+ {
+ //Test---Index array count must be equal to sms array count
+ TBool swapped;
+
+ do
+ {
+ swapped = EFalse;
+ for (TInt i=0; i<aIndexArray.Count()-1 ;i++)
+ {
+ if (aIndexArray[i] > aIndexArray[i+1])
+ {
+ aSmsArray.InsertL(i, aSmsArray[i+1]);
+ aSmsArray.Delete(i+2);
+ aIndexArray.InsertL(i, aIndexArray[i+1]);
+ aIndexArray.Delete(i+2);
+ swapped = ETrue;
+ }
+ }
+ }
+ while (swapped);
+ }
+
+/**
+ * Utility func for cleanup stack
+ */
+void CClass0StoreCloseObject(TAny* aObj)
+ {
+ LOGGSMU2("WARNING! Hey, CClass0StoreCloseObject called by Untrapper! [0x%08x]", aObj);
+ ((CClass0SmsReassemblyStore*)aObj)->Revert();
+ }
+
+/**
+ * Sets the class 0 re-assembly store as in-transaction.
+ *
+ * The function checks the validity of the call and leaves KErrAccessDenied if
+ * invalid.
+ * @capability None
+ */
+void CClass0SmsReassemblyStore::BeginTransactionLC()
+ {
+ LOGSMSPROT3("CClass0SmsReassemblyStore::BeginTransactionLC [this=0x%08X iInTransaction=%d]", this, iInTransaction);
+
+ if (iInTransaction)
+ {
+ LOGGSMU1("WARNING CClass0SmsReassemblyStore::BeginTransactionLC leaving with KErrAccessDenied");
+ User::Leave(KErrAccessDenied);
+ }
+
+ TCleanupItem class0StoreClose(CClass0StoreCloseObject, this);
+ CleanupStack::PushL(class0StoreClose);
+ iPreallocatedFile->BeginTransactionL();
+ iPermanentFileStore->BeginTransactionL();
+ iInTransaction = ETrue;
+ }
+
+/**
+ * It commits the transaction.
+ */
+void CClass0SmsReassemblyStore::CommitTransactionL()
+ {
+ LOGSMSPROT3("CClass0SmsReassemblyStore::CommitTransactionL(): this=0x%08X iInTransaction=%d",
+ this, iInTransaction);
+
+ //Commit permanent store file
+ iPermanentFileStore->CommitTransactionL();
+ //Commit pre-allocated file
+ iPreallocatedFile->CommitTransactionL();
+ CleanupStack::Pop(this); //CClass0StoreCloseObject
+ iInTransaction = EFalse;
+ }
+
+/**
+ * It reverts the transaction.
+ */
+void CClass0SmsReassemblyStore::Revert()
+ {
+ LOGSMSPROT3("CClass0SmsReassemblyStore::Revert(): this=0x%08X, iInTransaction=%d",
+ this, iInTransaction);
+
+ iPreallocatedFile->Revert();
+ iPermanentFileStore->Revert();
+ iInTransaction = EFalse;
+ }