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