devicediagnosticsfw/diagresultsdb/server/src/diagresultsdbstore.cpp
branchRCL_3
changeset 61 b183ec05bd8c
parent 59 13d7c31c74e0
child 62 19bba8228ff0
equal deleted inserted replaced
59:13d7c31c74e0 61:b183ec05bd8c
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Class definition of 
       
    15 *
       
    16 */
       
    17 
       
    18 #include <s32std.h>
       
    19 #include <sysutil.h> 
       
    20 #include <f32file.h> 
       
    21 #include <centralrepository.h>
       
    22 
       
    23 #include "diagresultsdbtestrecord.h"
       
    24 #include "diagresultsdbstore.h"
       
    25 #include "diagresultsdatabasecommon.h"
       
    26 #include "diagresultsdbcrdc.h"
       
    27 #include "diagresultsdatabase.h"
       
    28 #include "diagresultsdbtestrecordhandle.h"
       
    29 #include "diagresultsdbrecordengineparam.h"
       
    30 #include "diagresultsdbprivatecrkeys.h"
       
    31 
       
    32 _LIT( KFileType, ".dat" );
       
    33 _LIT( KDriveC, "C:" );
       
    34 
       
    35 const TInt KMininumDiskSpace = 500;
       
    36 
       
    37 const TInt KFirstStreamId = 2;
       
    38 
       
    39 // ---------------------------------------------------------------------------
       
    40 // Constructor.
       
    41 // ---------------------------------------------------------------------------
       
    42 // 
       
    43 CDiagResultsDbStore::CDiagResultsDbStore( TUid aDbUid ): 
       
    44         CActive( CActive::EPriorityStandard ), iStore( NULL ), 
       
    45         iDbUid( aDbUid ), iLoadingObserver( NULL ), iCompletionObserver( NULL ),
       
    46         iRecordArray( NULL ), iRecordIds(NULL), iRecordNumber(0), 
       
    47         iTestRecord( NULL ), iState( ENotRunning )
       
    48 	{
       
    49 	CActiveScheduler::Add(this);
       
    50 	}
       
    51 
       
    52 // ---------------------------------------------------------------------------
       
    53 // NewL. Creates a DB file based on aDbUid if it does not exist.
       
    54 // ---------------------------------------------------------------------------
       
    55 // 
       
    56 CDiagResultsDbStore* CDiagResultsDbStore::NewL( TUid aDbUid )
       
    57 	{
       
    58 	LOGME("CDiagResultsDbStore* CDiagResultsDbStore::NewL");
       
    59 	CDiagResultsDbStore* store = new (ELeave) CDiagResultsDbStore( aDbUid );
       
    60 	CleanupStack::PushL( store );
       
    61 	store->ConstructL();
       
    62 	CleanupStack::Pop();
       
    63 	return store;
       
    64 	}
       
    65 
       
    66 // ---------------------------------------------------------------------------
       
    67 // NewLC.
       
    68 // ---------------------------------------------------------------------------
       
    69 // 
       
    70 CDiagResultsDbStore* CDiagResultsDbStore::NewLC( TUid aDbUid )
       
    71 	{
       
    72 	LOGME("CDiagResultsDbStore::NewLC");
       
    73 	CDiagResultsDbStore* store = new (ELeave) CDiagResultsDbStore( aDbUid );
       
    74 	CleanupStack::PushL( store );
       
    75 	store->ConstructL();
       
    76 	return store;
       
    77 	}	
       
    78 
       
    79 // ---------------------------------------------------------------------------
       
    80 // Starts asynchronous loading of all test records from the DB.
       
    81 // Observer is notified when test records have been loaded.
       
    82 // ---------------------------------------------------------------------------
       
    83 // 
       
    84 void CDiagResultsDbStore::ExistingRecordsAsyncL( MRecordLoadingObserver& aObserver )
       
    85     {
       
    86     if ( IsActive() )
       
    87         {
       
    88         User::Leave( KErrInUse );
       
    89         }
       
    90     
       
    91     iLoadingObserver = &aObserver;
       
    92     
       
    93     iState = EGetRootStream;
       
    94     iRecordNumber = 0;
       
    95     
       
    96     CompleteOwnRequest();
       
    97     
       
    98     SetActive();
       
    99     }
       
   100 
       
   101 // ---------------------------------------------------------------------------
       
   102 // Cancel asynchronous functionality. Do not call this directly (use Cancel())
       
   103 // ---------------------------------------------------------------------------
       
   104 // 
       
   105 void CDiagResultsDbStore::DoCancel()
       
   106     {
       
   107     if ( iRecordArray )
       
   108         {
       
   109         iRecordArray->ResetAndDestroy(); 
       
   110            
       
   111         delete iRecordArray;
       
   112         iRecordArray = NULL;   
       
   113         }
       
   114               
       
   115     //Note that Store is not responsible for deleting the iTestRecord.
       
   116     //iTestRecord is deleted by subsession.
       
   117             
       
   118     delete iRecordIds;
       
   119     iRecordIds = NULL;
       
   120     
       
   121     iState = ENotRunning;
       
   122     iRecordNumber = 0;
       
   123     }
       
   124 
       
   125 // ---------------------------------------------------------------------------
       
   126 // This is called if there are leaves or errors in RunL.
       
   127 // ---------------------------------------------------------------------------
       
   128 // 
       
   129 TInt CDiagResultsDbStore::RunError(TInt aError)
       
   130     {
       
   131     TInt err = KErrNone;
       
   132 
       
   133     switch ( iState )
       
   134     	{
       
   135         case EGetRootStream:
       
   136         case EGetRecord:            
       
   137         case ERecordsReady:
       
   138             {
       
   139             TRAP( err, iLoadingObserver->ExistingRecordsL( aError, NULL ) );
       
   140             }
       
   141         break;
       
   142         default:
       
   143         	{
       
   144         	///@@@KSR: changes for Codescanner error val = High 
       
   145         	//User::Leave( aError );
       
   146         	}
       
   147     	}
       
   148 
       
   149     return KErrNone;
       
   150     }
       
   151 
       
   152 
       
   153 // ---------------------------------------------------------------------------
       
   154 // Keeps the database file small as possible. Compacting must be done often as
       
   155 // possible keeping in mind that compacting could take a long time.
       
   156 // ---------------------------------------------------------------------------
       
   157 // 
       
   158 void CDiagResultsDbStore::CompactDatabase()
       
   159     {    
       
   160     TRAPD( error, iStore->CompactL());
       
   161     
       
   162     if ( error != KErrNone )
       
   163         {
       
   164         User::Panic(_L("compact error"), 
       
   165             DiagResultsDbCommon::EDatabaseCompact );
       
   166         }    
       
   167     else 
       
   168         {
       
   169         //Commit must be called in order to really reduce the size of DB file.
       
   170         TRAP( error, iStore->CommitL() ); 
       
   171         if ( error != KErrNone )
       
   172            {
       
   173            User::Panic(_L("compact/commit error"), 
       
   174            DiagResultsDbCommon::EDatabaseCompactCommit );
       
   175            }
       
   176         }
       
   177     }
       
   178 
       
   179 // ---------------------------------------------------------------------------
       
   180 // Completes own request. This changes the value of TRequestStatus and causes
       
   181 // RunL to be called afterwards (if CActive is active).
       
   182 // ---------------------------------------------------------------------------
       
   183 // 
       
   184 void CDiagResultsDbStore::CompleteOwnRequest()
       
   185     {
       
   186     TRequestStatus* status = &iStatus;
       
   187     User::RequestComplete( status, KErrNone );
       
   188     }
       
   189 
       
   190 // ---------------------------------------------------------------------------
       
   191 // Asynchronous handling function. States are needed to separate two different
       
   192 // tasks. The first one is loading test records from the db file. The second
       
   193 // is writing a test record into the DB file.
       
   194 // ---------------------------------------------------------------------------
       
   195 //     
       
   196 void CDiagResultsDbStore::RunL()
       
   197     {
       
   198     
       
   199     switch ( iState )
       
   200         {
       
   201         case EGetRootStream:
       
   202             {
       
   203             iRecordArray = new (ELeave) RPointerArray<CDiagResultsDbTestRecord>;
       
   204             iRecordIds = new (ELeave) RArray<TStreamId>;
       
   205             // Find available stream ids
       
   206             ReadRootStreamL( *iRecordIds );
       
   207                                    
       
   208             if ( iRecordIds->Count() == 0 ) //no records, no need to continue
       
   209                 {
       
   210                  //Ownership is transferred
       
   211                 iLoadingObserver->ExistingRecordsL( KErrNone, iRecordArray );
       
   212                 iRecordArray = NULL; //do not delete
       
   213             
       
   214                 iRecordIds->Close();
       
   215                 delete iRecordIds;
       
   216                 iRecordIds = NULL;
       
   217     
       
   218                 iState = ENotRunning;
       
   219                 iRecordNumber = 0;   
       
   220             
       
   221                 iLoadingObserver = NULL;
       
   222                 return;
       
   223                 }
       
   224             
       
   225             iState = EGetRecord;
       
   226             
       
   227             CompleteOwnRequest();
       
   228             SetActive();
       
   229             }
       
   230             break;
       
   231             
       
   232         case EGetRecord:
       
   233             {            
       
   234             iRecordArray->Append ( OpenExistingRecordL( 
       
   235                             TUid::Uid( (*iRecordIds)[iRecordNumber].Value()), ETrue ) );
       
   236             iRecordNumber++;
       
   237             if ( iRecordNumber < iRecordIds->Count() )
       
   238                 {
       
   239                 iState = EGetRecord;
       
   240                 }
       
   241             else 
       
   242                 {
       
   243                 iState = ERecordsReady;
       
   244                 }
       
   245             
       
   246             CompleteOwnRequest();
       
   247             SetActive();
       
   248             }
       
   249             break;
       
   250             
       
   251         case ERecordsReady:
       
   252             {
       
   253              //Ownership is transferred
       
   254             iLoadingObserver->ExistingRecordsL( KErrNone, iRecordArray );
       
   255             iRecordArray = NULL; //do not delete
       
   256             
       
   257             iRecordIds->Close();
       
   258             delete iRecordIds;
       
   259             iRecordIds = NULL;
       
   260     
       
   261             iState = ENotRunning;
       
   262             iRecordNumber = 0;   
       
   263             
       
   264             iLoadingObserver = NULL;
       
   265             }
       
   266             break;
       
   267   
       
   268         
       
   269         default:
       
   270             User::Leave( KErrNotFound );
       
   271             break;
       
   272             
       
   273         }
       
   274         
       
   275     }
       
   276 
       
   277 // ---------------------------------------------------------------------------
       
   278 // Constructs the store. Creates the DB file if it does not exist or opens it. 
       
   279 // Also creates an empty root stream into the store if file was created.
       
   280 // There is some exception handling included for example if file exist but it
       
   281 // cannot be opened.
       
   282 // ---------------------------------------------------------------------------
       
   283 // 
       
   284 void CDiagResultsDbStore::ConstructL()
       
   285 	{	
       
   286 	LOGME("CDiagResultsDbStore::ConstructL");		
       
   287 	//Read from central repository.
       
   288 	TInt algorithm = GetDeletionAlgorithmL();
       
   289 	
       
   290 	if ( algorithm == 0 )
       
   291 		{
       
   292 		iDeletionAlgorithm = EMaxRecordCountAlgorithm;
       
   293 		}
       
   294 	else if ( algorithm == 1 )
       
   295 		{
       
   296 		iDeletionAlgorithm = ELastResultsAlgorithm;
       
   297 		}
       
   298 	else 
       
   299 		{
       
   300 		User::Panic( _L("Unknown Deletion Algorithm"), 
       
   301                 DiagResultsDbCommon::EUnknownDeletionAlgorithm);  
       
   302 		}
       
   303 	
       
   304 	LOGME("resultdbstore::Before irfs.connect");
       
   305     User::LeaveIfError(iRfs.Connect());
       
   306     LOGME("iRfs.connect");
       
   307     TBool tooLowSpace = SysUtil::DiskSpaceBelowCriticalLevelL( 
       
   308                                                     &iRfs, 
       
   309                                                     KMininumDiskSpace, 
       
   310                                                     EDriveC );
       
   311     LOGME1("tooLowSpace %d",tooLowSpace);
       
   312     if ( tooLowSpace )        
       
   313         {
       
   314         User::Leave( KErrDiskFull );
       
   315         }
       
   316     
       
   317     TInt err = iRfs.CreatePrivatePath( EDriveC );
       
   318     
       
   319     LOGME1("privatepathcreate %d",err);
       
   320     //Create private path if it does not exists
       
   321     if ( err != KErrAlreadyExists && err != KErrNone )
       
   322         {
       
   323         User::Leave ( err ); //Unexpected error
       
   324         }
       
   325     
       
   326     TBuf<256> filename;
       
   327     iRfs.PrivatePath( filename );
       
   328     filename.Insert( 0, KDriveC );
       
   329     filename.Append( iDbUid.Name() );
       
   330     filename.Append( KFileType );
       
   331 
       
   332     //Check is the File already there
       
   333     //open for reading and writing.
       
   334     err = iFile.Open( iRfs, filename, EFileShareAny|EFileWrite );  
       
   335 
       
   336     LOGME1("ifile.open %d",err);
       
   337     TInt fileError = KErrNotFound;
       
   338     TInt fileSize = 0;
       
   339 
       
   340     if ( err == KErrNone )
       
   341         {        
       
   342         fileError = iFile.Size( fileSize );    
       
   343         }
       
   344     
       
   345     
       
   346     //Checking is done when the file exists. 
       
   347     //File size reading error should never happen.
       
   348     //if the file is too large, the function will panic.
       
   349     if ( err == KErrNone && fileError == KErrNone )
       
   350     	{
       
   351     	CheckMaximumFileSizeLimitL( iRfs, filename, fileSize ); 
       
   352     	}
       
   353     
       
   354     iFile.Close();
       
   355     
       
   356     // File exist
       
   357     if ( err == KErrNone )
       
   358         {                           
       
   359         TRAPD( err, iStore = CPermanentFileStore::OpenL(iRfs, filename, 
       
   360                         EFileShareAny|EFileWrite|EFileRead|EFileStream ));
       
   361         
       
   362         if ( err != KErrNone )
       
   363             {           
       
   364             err = iRfs.Delete ( filename );
       
   365             
       
   366             if ( err != KErrNone )
       
   367                 {
       
   368                 User::Panic( _L("DiagServer corrupt file delete failed"), 
       
   369                         DiagResultsDbCommon::EServerCorruptFileDelete);
       
   370                 }
       
   371                 
       
   372             User::Leave( KErrCorrupt );
       
   373             }
       
   374             
       
   375         //This must be called, otherwise RStoreWriteStream write will fail.
       
   376         iStore->SetTypeL( iStore->Layout() );
       
   377         }
       
   378        
       
   379     else if ( err == KErrNotFound ) //Create new file  if the file is not found
       
   380         {
       
   381         LOGME("createnewfile");
       
   382         TRAPD( err, iStore = CPermanentFileStore::CreateL(iRfs, filename, 
       
   383                         EFileShareAny|EFileWrite|EFileRead|EFileStream ));
       
   384         
       
   385         LOGME1("createnewfile = %d",err);
       
   386         if ( err != KErrNone ) //File could not be created for some reason
       
   387             { 
       
   388              LOGME1("createnewfile panic = %d",err);
       
   389             User::Panic( _L("DiagServer unable to create DB file"), 
       
   390                             DiagResultsDbCommon::EServerFileCreationError);          
       
   391             }
       
   392             
       
   393         //This must be called, otherwise RStoreWriteStream write will fail.
       
   394         iStore->SetTypeL( iStore->Layout() );
       
   395         CreateEmptyRootStreamL( *iStore );
       
   396         
       
   397         if ( iDeletionAlgorithm == ELastResultsAlgorithm )
       
   398         	{
       
   399         	CreateLastResultsBufferStreamL();
       
   400         	}
       
   401         
       
   402         iStore->CommitL();
       
   403      
       
   404         }
       
   405     else 
       
   406         {
       
   407         LOGME1("else userleave = %d",err);
       
   408         User::Leave( err );
       
   409         }
       
   410 	}
       
   411 
       
   412 
       
   413 // ---------------------------------------------------------------------------
       
   414 // Get central repository key that controls maximum file size.
       
   415 // ---------------------------------------------------------------------------
       
   416 //
       
   417 TInt CDiagResultsDbStore::GetMaximumFileSizeL()
       
   418 	{
       
   419 	CRepository* cr = CRepository::NewLC( KCRUidDiagnosticsResults );
       
   420 
       
   421 	TInt result = 0;	
       
   422 	TInt error = cr->Get( KDiagDatabaseMaxFileSize, result );
       
   423 	
       
   424 	CleanupStack::PopAndDestroy();
       
   425 	
       
   426 	if ( error != KErrNone )
       
   427 		{
       
   428 		User::Leave(error);
       
   429 		}
       
   430 	return result;
       
   431 	}
       
   432 
       
   433 
       
   434 // ---------------------------------------------------------------------------
       
   435 // Get central repository key that controls usage of the deletion algorithm.
       
   436 // ---------------------------------------------------------------------------
       
   437 //
       
   438 TInt CDiagResultsDbStore::GetDeletionAlgorithmL()
       
   439 	{
       
   440 	CRepository* cr = CRepository::NewLC( KCRUidDiagnosticsResults );
       
   441 
       
   442 	TInt result = 0;	
       
   443 	TInt error = cr->Get( KDiagDatabaseDeletionAlgorithm, result );
       
   444 	
       
   445 	CleanupStack::PopAndDestroy();
       
   446 	
       
   447 	if ( error != KErrNone )
       
   448 		{
       
   449 		User::Leave(error);
       
   450 		}
       
   451 	return result;
       
   452 	}
       
   453 
       
   454 
       
   455 // ---------------------------------------------------------------------------
       
   456 // Check DB file size and delete the file if it is too big.
       
   457 // Checking is controlled by a central repository key.
       
   458 //
       
   459 // Note that this function deletes the file and after that panics, because
       
   460 // the error is very serious. 
       
   461 // ---------------------------------------------------------------------------
       
   462 //
       
   463 void CDiagResultsDbStore::CheckMaximumFileSizeLimitL( RFs& aRfs, 
       
   464 													  const TDesC& aFileName,
       
   465 													  TInt aFileSize )
       
   466 	{
       
   467 	//Read central repository value
       
   468 	TInt maxFileSize = GetMaximumFileSizeL();
       
   469 	
       
   470 	//If == 0, feature is disabled i.e. there is no limitation
       
   471 	//to the size of DB files.
       
   472 	if ( maxFileSize == 0 )
       
   473 		{
       
   474 		return;		
       
   475 		}
       
   476 	else
       
   477 		{
       
   478 		if ( aFileSize > maxFileSize )
       
   479 			{
       
   480 			//Delete the file. 
       
   481 			aRfs.Delete( aFileName );		
       
   482 			User::Panic(_L("Maxfile Size exceeded"), 
       
   483 			            DiagResultsDbCommon::EMaximumFileSizeExceeded );
       
   484 			}
       
   485 		}	
       
   486 	}
       
   487 
       
   488 // ---------------------------------------------------------------------------
       
   489 // Create a stream for last results.
       
   490 // The stream is created when DB file is created.
       
   491 // 
       
   492 // Because this is the first stream in the PermanentFileStore,
       
   493 // we do not need to store the stream ID anywhere. Consider it as a constant.
       
   494 // ---------------------------------------------------------------------------
       
   495 //
       
   496 void CDiagResultsDbStore::CreateLastResultsBufferStreamL()
       
   497     {        
       
   498     RArray<TUid>* uids = new (ELeave) RArray<TUid>;
       
   499     
       
   500     CDiagResultsDbRecordEngineParam* params = 
       
   501         CDiagResultsDbRecordEngineParam::NewL( uids, EFalse );
       
   502     CleanupStack::PushL( params );
       
   503                 
       
   504     TStreamId id = iStore->ExtendL();
       
   505     
       
   506     //We assume that the permanent file store uses this as the first stream ID.
       
   507     __ASSERT_ALWAYS( id == TStreamId( KFirstStreamId ), 
       
   508                         User::Panic( _L("DiagServer Incorrect Last Results Buffer"), 
       
   509                         DiagResultsDbCommon::EIncorrectExtendNumberForLastResults)  );
       
   510 
       
   511     CleanupStack::Pop();
       
   512       
       
   513     CDiagResultsDbTestRecordHandle* handle = CDiagResultsDbTestRecordHandle::NewL( 
       
   514                                                     id, 
       
   515                                                     iDbUid, 
       
   516                                                     params );
       
   517                                                     
       
   518     CleanupStack::PushL( handle );
       
   519     
       
   520     WriteHandleIntoDbL( *handle ); //writes a new stream
       
   521          
       
   522     //Do not append on to the root stream!!
       
   523     //this should be visible only for the server.                  
       
   524     
       
   525     CleanupStack::PopAndDestroy();                                
       
   526         
       
   527     }
       
   528 
       
   529 // ---------------------------------------------------------------------------
       
   530 // Destructor.
       
   531 // ---------------------------------------------------------------------------
       
   532 // 	
       
   533 CDiagResultsDbStore::~CDiagResultsDbStore()
       
   534 	{
       
   535 	if ( iRecordIds )
       
   536 	    {
       
   537 	    iRecordIds->Close();
       
   538 	    delete iRecordIds;
       
   539         iRecordIds = NULL;    
       
   540 	    }
       
   541 
       
   542     Cancel();
       
   543         
       
   544     delete iStore;
       
   545     iStore = NULL;
       
   546     
       
   547     iFile.Close();
       
   548     iRfs.Close();
       
   549 	}
       
   550 
       
   551 // ---------------------------------------------------------------------------
       
   552 // Create a new record. 
       
   553 // ---------------------------------------------------------------------------
       
   554 // 
       
   555 CDiagResultsDbTestRecordHandle* CDiagResultsDbStore::CreateNewRecordL( 
       
   556                                 CDiagResultsDbRecordEngineParam* aEngineParam )
       
   557     {
       
   558     
       
   559     TBool tooLowSpace = SysUtil::DiskSpaceBelowCriticalLevelL( 
       
   560                                                     &iRfs, 
       
   561                                                     KMininumDiskSpace, 
       
   562                                                     EDriveC );
       
   563     if ( tooLowSpace )        
       
   564         {
       
   565         User::Leave( KErrDiskFull );
       
   566         }
       
   567     
       
   568     
       
   569     
       
   570     TStreamId id = iStore->ExtendL();
       
   571   
       
   572     CDiagResultsDbTestRecordHandle* handle = CDiagResultsDbTestRecordHandle::NewL( 
       
   573                                                     id, 
       
   574                                                     iDbUid, 
       
   575                                                     aEngineParam );
       
   576     CleanupStack::PushL( handle );
       
   577     
       
   578     WriteHandleIntoDbL( *handle ); //writes a new stream
       
   579     
       
   580     AppendRootStreamL( id ); //update root stream
       
   581     
       
   582     iStore->CommitL(); 
       
   583     
       
   584     CleanupStack::Pop();                                
       
   585     return handle;
       
   586     
       
   587     }
       
   588 
       
   589 // ---------------------------------------------------------------------------
       
   590 // Write test record handle into the store.
       
   591 // ---------------------------------------------------------------------------
       
   592 // 
       
   593 void CDiagResultsDbStore::WriteHandleIntoDbL( CDiagResultsDbTestRecordHandle& aHandle )
       
   594     {
       
   595     RStoreWriteStream writestream;
       
   596     
       
   597     writestream.ReplaceLC( *iStore, aHandle.RecordId() );    
       
   598         
       
   599     aHandle.ExternalizeL( writestream );
       
   600     
       
   601     writestream.CommitL();
       
   602        
       
   603     CleanupStack::PopAndDestroy( &writestream );
       
   604     }
       
   605 
       
   606 // ---------------------------------------------------------------------------
       
   607 // Writes data into the DB file (.dat file). 
       
   608 // ---------------------------------------------------------------------------
       
   609 //     
       
   610 TInt CDiagResultsDbStore::CompleteTestResult( TBool aCommit, 
       
   611                                     CDiagResultsDbTestRecordHandle& aHandle,  
       
   612                                     CDiagResultsDatabaseItem& aTestItem )
       
   613     {        
       
   614     TRAPD( err, DoCompleteTestResultL( aCommit, aHandle, aTestItem ));
       
   615     
       
   616     return err;
       
   617     }
       
   618 
       
   619 // ---------------------------------------------------------------------------
       
   620 // Writes handle into the DB. Test results items have been written already.
       
   621 // see CompleteTestResult.
       
   622 // ---------------------------------------------------------------------------
       
   623 // 
       
   624 TInt CDiagResultsDbStore::CompleteRecord(  
       
   625                                 CDiagResultsDbTestRecordHandle& aHandle )
       
   626     {
       
   627     // ignore DRM error.
       
   628     TRAP_IGNORE( aHandle.RecordInfo().iDrmFinishTime = 
       
   629         TDiagResultsDatabaseTestRecordInfo::DRMTimeL() );
       
   630 
       
   631     aHandle.RecordInfo().iFinishTime.HomeTime();
       
   632     
       
   633     TRAPD( error, DoCompleteRecordL( aHandle ));
       
   634     
       
   635     return error;
       
   636     }
       
   637 
       
   638 // ---------------------------------------------------------------------------
       
   639 // Writes handle into the DB. Test results items have been written already.
       
   640 // see CompleteTestResult.
       
   641 // ---------------------------------------------------------------------------
       
   642 // 
       
   643 void CDiagResultsDbStore::DoCompleteRecordL(  
       
   644                                 CDiagResultsDbTestRecordHandle& aHandle )
       
   645     {
       
   646     
       
   647     TBool tooLowSpace = SysUtil::DiskSpaceBelowCriticalLevelL( 
       
   648                                                     &iRfs, 
       
   649                                                     KMininumDiskSpace, 
       
   650                                                     EDriveC );
       
   651     if ( tooLowSpace )        
       
   652         {
       
   653         User::Leave( KErrDiskFull );
       
   654         }
       
   655     
       
   656     WriteHandleIntoDbL( aHandle );
       
   657     
       
   658     iStore->CommitL();
       
   659     }
       
   660 
       
   661 
       
   662 // ---------------------------------------------------------------------------
       
   663 // Write aTestItem and aHandle into the DB. These must be in sync.
       
   664 // ---------------------------------------------------------------------------
       
   665 //     
       
   666 void CDiagResultsDbStore::DoCompleteTestResultL( TBool aCommit, 
       
   667                                         CDiagResultsDbTestRecordHandle& aHandle, 
       
   668                                         CDiagResultsDatabaseItem& aTestItem )
       
   669     {   
       
   670     
       
   671     TBool tooLowSpace = SysUtil::DiskSpaceBelowCriticalLevelL( 
       
   672                                                     &iRfs, 
       
   673                                                     aTestItem.Size() *2, 
       
   674                                                     EDriveC );
       
   675     if ( tooLowSpace )        
       
   676         {
       
   677         User::Leave( KErrDiskFull );
       
   678         }
       
   679     
       
   680     RStoreWriteStream writestream;
       
   681     
       
   682     CDiagResultsDbTestRecordHandle::TTestResultHandle testresulthandle;
       
   683     
       
   684     TBool found = aHandle.Find( aTestItem.TestUid() );
       
   685     
       
   686     
       
   687     if ( found ) //Replace old test result
       
   688         {
       
   689         TStreamId id;
       
   690         TInt error = aHandle.MatchingStreamId( aTestItem.TestUid(), id);
       
   691         User::LeaveIfError ( error );
       
   692         writestream.ReplaceLC( *iStore, id );
       
   693         }
       
   694     else //New test result
       
   695         {
       
   696         TStreamId newstreamid = writestream.CreateLC( *iStore );   
       
   697         testresulthandle.iStreamId = newstreamid;
       
   698         testresulthandle.iTestUid = aTestItem.TestUid();
       
   699         }
       
   700 
       
   701     aTestItem.ExternalizeL( writestream );
       
   702     writestream.CommitL();
       
   703     CleanupStack::PopAndDestroy( &writestream );
       
   704   
       
   705     if ( !found )
       
   706         {
       
   707         aHandle.AddL( testresulthandle );
       
   708         }
       
   709     
       
   710     WriteHandleIntoDbL( aHandle );
       
   711     
       
   712     if ( aCommit )
       
   713         {
       
   714         iStore->CommitL();       
       
   715         }      
       
   716     }
       
   717 
       
   718 // ---------------------------------------------------------------------------
       
   719 // Read a test record from the DB. The record should not be ever written into
       
   720 // the same DB again. First read the number of items there are in the record.
       
   721 // After that read the items and the record info. 
       
   722 // ---------------------------------------------------------------------------
       
   723 //     
       
   724 CDiagResultsDbTestRecord* CDiagResultsDbStore::OpenExistingRecordL( TUid aUid, 
       
   725                                                             TBool aReadOnly )
       
   726     {    
       
   727     TStreamId id = TStreamId ( aUid.iUid );
       
   728     
       
   729     RStoreReadStream handlereadstream;
       
   730     handlereadstream.OpenLC( *iStore, id );
       
   731     
       
   732     CDiagResultsDbTestRecord* testrecord = CDiagResultsDbTestRecord::NewL( aReadOnly, 
       
   733 	                                       aUid );
       
   734     CleanupStack::PushL ( testrecord );
       
   735     
       
   736     CDiagResultsDbTestRecordHandle* handle = 
       
   737                             CDiagResultsDbTestRecordHandle::NewL( handlereadstream );
       
   738                                                        
       
   739     CleanupStack::PushL ( handle );
       
   740     
       
   741     for ( TInt i = 0; i < handle->Count(); ++i )
       
   742         {
       
   743         RStoreReadStream readstream;
       
   744         readstream.OpenLC( *iStore, ((*handle)[i]) ); 
       
   745                 
       
   746         testrecord->AddL( CDiagResultsDatabaseItem::NewL ( readstream ) );
       
   747         
       
   748         CleanupStack::PopAndDestroy( &readstream );  
       
   749         }
       
   750 
       
   751     CleanupStack::PopAndDestroy(); //handle
       
   752     CleanupStack::Pop(); //testrecord
       
   753     
       
   754     CleanupStack::PopAndDestroy( &handlereadstream ); 
       
   755     
       
   756     return testrecord;
       
   757     }
       
   758 
       
   759 
       
   760 // ---------------------------------------------------------------------------
       
   761 // Open last results buffer. It contains the test results that would have
       
   762 // been otherwise deleted. 
       
   763 // ---------------------------------------------------------------------------
       
   764 //   
       
   765 CDiagResultsDbTestRecord* CDiagResultsDbStore::OpenExistingLastResultsBufferL()
       
   766     {      
       
   767     CDiagResultsDbTestRecord* testrecord = 
       
   768                             OpenExistingRecordL( TUid::Uid(KFirstStreamId),
       
   769                                                  ETrue );                                                                                                                                       
       
   770     return testrecord;
       
   771     }
       
   772 
       
   773 
       
   774 void CDiagResultsDbStore::OpenExistingRecordAndHandleL( TStreamId aId, 
       
   775                                                         CDiagResultsDbTestRecord*& aRecord,
       
   776                                                         CDiagResultsDbTestRecordHandle*& aHandle )
       
   777     {            
       
   778     RStoreReadStream handlereadstream;
       
   779     handlereadstream.OpenLC( *iStore, aId );
       
   780     
       
   781     CDiagResultsDbTestRecord* testrecord = CDiagResultsDbTestRecord::NewL( ETrue, 
       
   782 	                                       TUid::Uid( aId.Value() ));
       
   783     CleanupStack::PushL ( testrecord );
       
   784     
       
   785     CDiagResultsDbTestRecordHandle* handle = 
       
   786                             CDiagResultsDbTestRecordHandle::NewL( handlereadstream );
       
   787                                                        
       
   788     CleanupStack::PushL ( handle );
       
   789     
       
   790     for ( TInt i = 0; i < handle->Count(); ++i )
       
   791         {
       
   792         RStoreReadStream readstream;
       
   793         readstream.OpenLC( *iStore, ((*handle)[i]) ); 
       
   794                 
       
   795         testrecord->AddL( CDiagResultsDatabaseItem::NewL ( readstream ) );
       
   796         
       
   797         CleanupStack::PopAndDestroy( &readstream );  
       
   798         }
       
   799 
       
   800     CleanupStack::Pop(); //handle
       
   801     CleanupStack::Pop(); //testrecord
       
   802     
       
   803     aRecord = testrecord;
       
   804     aHandle = handle;
       
   805     
       
   806     CleanupStack::PopAndDestroy( &handlereadstream ); 
       
   807     
       
   808     
       
   809     }
       
   810 
       
   811 
       
   812 // ---------------------------------------------------------------------------
       
   813 // Retrieve all record infos from the store.
       
   814 // ---------------------------------------------------------------------------
       
   815 // 
       
   816 RArray<TDiagResultsDatabaseTestRecordInfo>* CDiagResultsDbStore::ExistingRecordInfosL()
       
   817     {
       
   818     RArray<TStreamId> ids;
       
   819     CleanupClosePushL( ids );
       
   820     // Find available stream ids
       
   821     ReadRootStreamL( ids );
       
   822     
       
   823     RArray<TDiagResultsDatabaseTestRecordInfo>* infos = new (ELeave) 
       
   824                                             RArray<TDiagResultsDatabaseTestRecordInfo>;
       
   825     CleanupClosePushL( *infos );                                            
       
   826     
       
   827     
       
   828     for ( TInt i = 0; i < ids.Count(); ++i )
       
   829         {
       
   830         CDiagResultsDbTestRecordHandle* handle = OpenExistingHandleL( TUid::Uid( ids[i].Value() ));
       
   831       
       
   832         TDiagResultsDatabaseTestRecordInfo info = handle->RecordInfo();
       
   833         
       
   834         infos->Append( info );
       
   835         }  
       
   836         
       
   837     CleanupStack::PopAndDestroy( &ids );
       
   838     CleanupStack::Pop();
       
   839     
       
   840     return infos;
       
   841     }
       
   842 
       
   843 
       
   844 // ---------------------------------------------------------------------------
       
   845 // Open a test result from the DB.
       
   846 // ---------------------------------------------------------------------------
       
   847 // 
       
   848 CDiagResultsDatabaseItem* CDiagResultsDbStore::OpenExistingTestResultL( TStreamId aId )
       
   849     {
       
   850     RStoreReadStream readstream;
       
   851     readstream.OpenLC( *iStore, aId ); 
       
   852     
       
   853     CDiagResultsDatabaseItem* item = CDiagResultsDatabaseItem::NewL ( readstream );
       
   854     
       
   855     CleanupStack::PopAndDestroy( &readstream );
       
   856     
       
   857     return item;
       
   858     }
       
   859     
       
   860 
       
   861 // ---------------------------------------------------------------------------
       
   862 // Open handle from the DB. Uid matches the handle's stream Id.
       
   863 // ---------------------------------------------------------------------------
       
   864 // 
       
   865 CDiagResultsDbTestRecordHandle* CDiagResultsDbStore::OpenExistingHandleL( 
       
   866                                                     TUid aUid )
       
   867     {
       
   868     TStreamId id = TStreamId ( aUid.iUid );
       
   869     
       
   870     RStoreReadStream handlereadstream;
       
   871     handlereadstream.OpenLC( *iStore, id );
       
   872     
       
   873     
       
   874     CDiagResultsDbTestRecordHandle* handle = 
       
   875                             CDiagResultsDbTestRecordHandle::NewL( handlereadstream );
       
   876                             
       
   877     CleanupStack::PopAndDestroy( &handlereadstream );                           
       
   878     
       
   879     return handle;   
       
   880     }
       
   881     
       
   882 // ---------------------------------------------------------------------------
       
   883 // Cleanup Database if there are two many test records.    
       
   884 // ---------------------------------------------------------------------------
       
   885 // 
       
   886 void CDiagResultsDbStore::CleanUpDatabaseL(TBool aCommit)
       
   887 	{
       
   888 	if ( iDeletionAlgorithm == EMaxRecordCountAlgorithm )
       
   889 		{
       
   890 		CleanUpDatabaseNoLastResultsL( aCommit );
       
   891 		}
       
   892 	else if ( iDeletionAlgorithm == ELastResultsAlgorithm )
       
   893 		{
       
   894 		CleanUpDatabaseUseLastResultsBufferL( aCommit );
       
   895 		}
       
   896 	else 
       
   897 		{
       
   898 		User::Panic( _L("Unknown Deletion Algorithm"), 
       
   899                 DiagResultsDbCommon::EUnknownDeletionAlgorithm);  
       
   900 		}
       
   901 	}
       
   902 
       
   903 // ---------------------------------------------------------------------------
       
   904 // Cleanup Database if there are two many test records.    
       
   905 // ---------------------------------------------------------------------------
       
   906 // 
       
   907 void CDiagResultsDbStore::CleanUpDatabaseNoLastResultsL(TBool aCommit)
       
   908     {    
       
   909     RArray<TStreamId> ids;
       
   910     CleanupClosePushL( ids );
       
   911     ReadRootStreamL( ids );
       
   912     
       
   913     //Fetch the maximum number of test records from Central Repository. Panic if
       
   914     //the value is not found. Also panic if value is less than zero.
       
   915     TInt maxsize = 0;
       
   916     TInt err = RDiagResultsDatabase::GetDatabaseMaximumSize( maxsize ) ;
       
   917     
       
   918     if ( err != KErrNone || maxsize < 0 )
       
   919         {
       
   920         User::Panic ( _L("Diag ResultsDB panic"), 
       
   921                     DiagResultsDbCommon::ECentralRepositoryFailure );
       
   922         }
       
   923             
       
   924     TBool cleanedUp = EFalse;   
       
   925         
       
   926     while ( ids.Count() > maxsize ) //Do cleanup
       
   927         {                
       
   928         DeleteOldestHandleL( ids );
       
   929                    
       
   930         cleanedUp = ETrue;
       
   931         }
       
   932       
       
   933     if ( cleanedUp && aCommit )
       
   934         {
       
   935         iStore->CommitL();       
       
   936         }      
       
   937       
       
   938     CleanupStack::PopAndDestroy( &ids );
       
   939     }
       
   940 
       
   941 
       
   942 // ---------------------------------------------------------------------------
       
   943 // Cleanup Database if there are two many test records.    
       
   944 // ---------------------------------------------------------------------------
       
   945 // 
       
   946 void CDiagResultsDbStore::CleanUpDatabaseUseLastResultsBufferL(TBool aCommit)
       
   947     {    
       
   948     RArray<TStreamId> ids;
       
   949     CleanupClosePushL( ids );
       
   950     ReadRootStreamL( ids );
       
   951 
       
   952     //Fetch the maximum number of test records from Central Repository. Panic if
       
   953     //the value is not found. Also panic if value is less than zero.
       
   954     TInt maxsize = 0;
       
   955     TInt err = RDiagResultsDatabase::GetDatabaseMaximumSize( maxsize ) ;
       
   956     
       
   957     if ( err != KErrNone || maxsize < 0 )
       
   958         {
       
   959         User::Panic ( _L("Diag ResultsDB panic"), 
       
   960                     DiagResultsDbCommon::ECentralRepositoryFailure );
       
   961         }
       
   962             
       
   963     TBool cleanedUp = EFalse;   
       
   964         
       
   965     while ( ids.Count() > maxsize ) //Do cleanup
       
   966         {                     
       
   967         TInt count = ids.Count();
       
   968                    
       
   969         ///@@@KSR: changes for Codescanner error val = High 
       
   970         //CheckOverflowingTestResults( ids );
       
   971         CheckOverflowingTestResultsL( ids );
       
   972                                   
       
   973         cleanedUp = ETrue;
       
   974         
       
   975         __ASSERT_ALWAYS( ids.Count() == count - 1, User::Panic( _L("Diag ResultsDB panic"), 
       
   976                     DiagResultsDbCommon::EUnableToDelete ) );
       
   977         }
       
   978     
       
   979     if ( cleanedUp && aCommit )
       
   980         {
       
   981         iStore->CommitL();       
       
   982         }      
       
   983       
       
   984     CleanupStack::PopAndDestroy( &ids );
       
   985     }
       
   986 
       
   987 
       
   988 // ---------------------------------------------------------------------------
       
   989 // Load last results buffer and add test results if needed.
       
   990 // 
       
   991 // Test results are only moved to the last results buffer.
       
   992 //
       
   993 // We want to preserve only test results that have Pass/fail result.
       
   994 //
       
   995 // The algorithm.
       
   996 //
       
   997 // 1. Open the test record that is going to be removed (handle + test results)
       
   998 // 2. Open last results buffer
       
   999 // 3. Go through the test record and search for test results that have pass/fail
       
  1000 // 4. If found, then check last results buffer is there a similar result.
       
  1001 // 5. If similar test results are found from the last results buffer, delete the old
       
  1002 //    result and add the new one.
       
  1003 // 6. If similar test result is not found, then append the test result into the
       
  1004 //    buffer.
       
  1005 // 7. Finally update the last result buffer 
       
  1006 // 8. delete the test record and any of the test results that did not go into
       
  1007 //    the last results buffer.
       
  1008 // ---------------------------------------------------------------------------
       
  1009 //
       
  1010 //void CDiagResultsDbStore::CheckOverflowingTestResults( RArray<TStreamId>& aIds )
       
  1011 ///@@@KSR: changes for Codescanner error val = High
       
  1012 void CDiagResultsDbStore::CheckOverflowingTestResultsL( RArray<TStreamId>& aIds )
       
  1013     {    
       
  1014     TStreamId id = aIds[0];
       
  1015     
       
  1016     CDiagResultsDbTestRecordHandle* handleToBeRemoved = NULL;
       
  1017     CDiagResultsDbTestRecord* recordToBeRemoved = NULL;
       
  1018     
       
  1019     
       
  1020     OpenExistingRecordAndHandleL( id, 
       
  1021                                   recordToBeRemoved,
       
  1022                                   handleToBeRemoved );
       
  1023     
       
  1024     CleanupStack::PushL( handleToBeRemoved );
       
  1025     CleanupStack::PushL( recordToBeRemoved );
       
  1026   
       
  1027     
       
  1028     CDiagResultsDbTestRecordHandle*  lastResultsBufferHandle = NULL;
       
  1029                                                                                                          
       
  1030     lastResultsBufferHandle = OpenExistingHandleL( TUid::Uid( KFirstStreamId ) );
       
  1031           
       
  1032     TInt testCount = recordToBeRemoved->Count();
       
  1033    
       
  1034     TInt movedCount = 0;
       
  1035    
       
  1036     CleanupStack::PushL( lastResultsBufferHandle );                                  
       
  1037                                              
       
  1038     for ( TInt x = 0; x < recordToBeRemoved->Count(); ++x )
       
  1039         {
       
  1040         
       
  1041         CDiagResultsDatabaseItem* item = recordToBeRemoved->GetItem(x);
       
  1042         
       
  1043         //We are looking for only results that are either ESuccess or
       
  1044         //EFailed.
       
  1045         if ( item->TestResult() == CDiagResultsDatabaseItem::ESuccess ||
       
  1046              item->TestResult() == CDiagResultsDatabaseItem::EFailed )
       
  1047             {            
       
  1048             TBool found = lastResultsBufferHandle->Find( item->TestUid() );
       
  1049             TInt  index = lastResultsBufferHandle->FindIndex( item->TestUid() );
       
  1050             
       
  1051             CDiagResultsDbTestRecordHandle::TTestResultHandle resulthandle = 
       
  1052                          handleToBeRemoved->Get( handleToBeRemoved->FindIndex( item->TestUid() ));
       
  1053                                                 
       
  1054             if ( resulthandle.iTestUid != item->TestUid() ) 
       
  1055                 {
       
  1056                 User::Panic( _L("Diag ResultsDB panic"), DiagResultsDbCommon::EIncorrectStreamId);
       
  1057                 }
       
  1058                                                         
       
  1059             if ( found )
       
  1060                 {                                
       
  1061                 //remove old result from last results buffer, because we add new one.
       
  1062                 iStore->DeleteL ( lastResultsBufferHandle->Get(index).iStreamId );
       
  1063                                 
       
  1064                 lastResultsBufferHandle->RemoveL( item->TestUid() );
       
  1065                 lastResultsBufferHandle->AddL( resulthandle );                               
       
  1066                 }
       
  1067             else 
       
  1068                 {
       
  1069                 lastResultsBufferHandle->AddL( resulthandle );                              
       
  1070                 }
       
  1071                 
       
  1072             movedCount++;
       
  1073             
       
  1074             handleToBeRemoved->RemoveL( item->TestUid() );    
       
  1075                 
       
  1076             }                                             
       
  1077         }
       
  1078             
       
  1079     WriteHandleIntoDbL( *lastResultsBufferHandle );
       
  1080                     
       
  1081     iStore->DeleteL( aIds[0] ); //delete oldest first
       
  1082     aIds.Remove( 0 );
       
  1083         
       
  1084     ReplaceRootStreamL( aIds );
       
  1085                 
       
  1086     //Delete test results streams as well.    
       
  1087     for (TInt i=0; i < handleToBeRemoved->Count(); ++i)
       
  1088         {
       
  1089         iStore->DeleteL ( handleToBeRemoved->Get(i).iStreamId );
       
  1090         movedCount++;
       
  1091         }        
       
  1092         
       
  1093     if ( movedCount != testCount )    
       
  1094         {
       
  1095         User::Panic( _L("EIncorrectStreamId"), DiagResultsDbCommon::EIncorrectStreamId);
       
  1096         }
       
  1097         
       
  1098     CleanupStack::PopAndDestroy( lastResultsBufferHandle );
       
  1099     CleanupStack::PopAndDestroy( recordToBeRemoved );
       
  1100     CleanupStack::PopAndDestroy( handleToBeRemoved );       
       
  1101     }
       
  1102 
       
  1103 
       
  1104 // ---------------------------------------------------------------------------
       
  1105 // Deletes the oldest handle from the store.
       
  1106 // ---------------------------------------------------------------------------
       
  1107 //  
       
  1108 void CDiagResultsDbStore::DeleteOldestHandleL( RArray<TStreamId>& aIds )
       
  1109     {        
       
  1110     CDiagResultsDbTestRecordHandle* handle = OpenExistingHandleL( 
       
  1111                                                 TUid::Uid( aIds[0].Value() ) );
       
  1112     CleanupStack::PushL( handle );
       
  1113         
       
  1114     iStore->DeleteL( aIds[0] ); //delete oldest first
       
  1115     aIds.Remove( 0 );
       
  1116         
       
  1117     ReplaceRootStreamL( aIds );
       
  1118                 
       
  1119     //Delete test results streams as well.    
       
  1120     for (TInt i=0; i < handle->Count(); ++i)
       
  1121         {
       
  1122         iStore->DeleteL ( handle->Get(i).iStreamId );
       
  1123         }
       
  1124                               
       
  1125     CleanupStack::PopAndDestroy( handle );
       
  1126     }
       
  1127 
       
  1128 
       
  1129 // ---------------------------------------------------------------------------
       
  1130 // Delete handle and its test results.
       
  1131 // ---------------------------------------------------------------------------
       
  1132 // 
       
  1133 void CDiagResultsDbStore::DeleteHandleL( TInt aIndex, RArray<TStreamId>& aIds )
       
  1134     {        
       
  1135     CDiagResultsDbTestRecordHandle* handle = OpenExistingHandleL( 
       
  1136                                                 TUid::Uid( aIds[aIndex].Value() ) );
       
  1137     CleanupStack::PushL( handle );
       
  1138         
       
  1139     iStore->DeleteL( aIds[aIndex] ); 
       
  1140     aIds.Remove( aIndex );
       
  1141         
       
  1142     ReplaceRootStreamL( aIds );
       
  1143                 
       
  1144     //Delete test results streams as well.    
       
  1145     for (TInt i=0; i < handle->Count(); ++i)
       
  1146         {
       
  1147         iStore->DeleteL ( handle->Get(i).iStreamId );
       
  1148         }
       
  1149                               
       
  1150     CleanupStack::PopAndDestroy( handle );
       
  1151     }
       
  1152 
       
  1153 
       
  1154 // ---------------------------------------------------------------------------
       
  1155 // Reads the root stream from the DB. Root stream contains uids of the 
       
  1156 // test records. TUid is convertible to TStreamId and opposite.
       
  1157 // ---------------------------------------------------------------------------
       
  1158 //             
       
  1159 void CDiagResultsDbStore::ReadRootStreamL( RArray<TStreamId>& aIds )
       
  1160     {    
       
  1161     
       
  1162     if (!iStore)
       
  1163         {
       
  1164         User::Panic( _L("Store is null"), 
       
  1165                         DiagResultsDbCommon::EStoreNullPointer );
       
  1166         }
       
  1167     
       
  1168     RStoreReadStream readstream;
       
  1169  
       
  1170     TStreamId rootId = iStore->Root();
       
  1171     readstream.OpenLC( *iStore, rootId );
       
  1172     
       
  1173     TInt count = readstream.ReadInt16L();
       
  1174         
       
  1175     for ( TInt i = 0; i < count; ++i )
       
  1176         {
       
  1177         TStreamId id;
       
  1178         id.InternalizeL( readstream );
       
  1179         aIds.AppendL ( id  );
       
  1180                
       
  1181         }
       
  1182     
       
  1183     CleanupStack::PopAndDestroy( &readstream );
       
  1184     }
       
  1185   
       
  1186 // ---------------------------------------------------------------------------
       
  1187 // Add one stream Id into the root stream.
       
  1188 // ---------------------------------------------------------------------------
       
  1189 //    
       
  1190 void CDiagResultsDbStore::AppendRootStreamL( TStreamId& aId )
       
  1191     {    
       
  1192     RArray<TStreamId> ids;
       
  1193     CleanupClosePushL( ids );
       
  1194     
       
  1195     ReadRootStreamL( ids );
       
  1196     
       
  1197     ids.Append( aId );
       
  1198     
       
  1199     ReplaceRootStreamL( ids );
       
  1200 
       
  1201     CleanupStack::PopAndDestroy( &ids);
       
  1202     }
       
  1203 
       
  1204 // ---------------------------------------------------------------------------
       
  1205 // Returns TUids from the root stream.
       
  1206 // ---------------------------------------------------------------------------
       
  1207 //     
       
  1208 void CDiagResultsDbStore::RecordUidsL(RArray<TUid>& aUids)
       
  1209     {
       
  1210     RArray<TStreamId> ids;
       
  1211     CleanupClosePushL ( ids );
       
  1212  
       
  1213     ReadRootStreamL( ids );
       
  1214     
       
  1215     for (TInt i = 0; i < ids.Count(); ++i)
       
  1216         {
       
  1217         aUids.Append( TUid::Uid( ids[i].Value() ));
       
  1218         }
       
  1219         
       
  1220     CleanupStack::PopAndDestroy( &ids );
       
  1221     }
       
  1222 
       
  1223         
       
  1224 // ---------------------------------------------------------------------------
       
  1225 // Replace the current root stream with a new array.
       
  1226 // ---------------------------------------------------------------------------
       
  1227 //     
       
  1228 void CDiagResultsDbStore::ReplaceRootStreamL( RArray<TStreamId>& aArray )
       
  1229     {
       
  1230     RStoreWriteStream writestream;
       
  1231     writestream.ReplaceLC( *iStore, iStore->Root() );    
       
  1232         
       
  1233     TInt count =  aArray.Count();    
       
  1234         
       
  1235     writestream.WriteInt16L(  count );
       
  1236     
       
  1237     for ( TInt i = 0; i < count; ++i )
       
  1238         {
       
  1239         writestream << aArray[i];
       
  1240         }
       
  1241         
       
  1242     writestream.CommitL();
       
  1243        
       
  1244     CleanupStack::PopAndDestroy( &writestream );
       
  1245     }     
       
  1246 
       
  1247 // ---------------------------------------------------------------------------
       
  1248 // Empty root stream is needed when DB file is created for the first time.
       
  1249 // ---------------------------------------------------------------------------
       
  1250 // 
       
  1251 void CDiagResultsDbStore::CreateEmptyRootStreamL(CPermanentFileStore& aStore)
       
  1252     {
       
  1253     RStoreWriteStream writestream;
       
  1254    
       
  1255     TStreamId id = writestream.CreateLC( *iStore );  
       
  1256     writestream.WriteInt16L( 0 ); // stream id count = 0
       
  1257     
       
  1258     writestream.CommitL();  
       
  1259     
       
  1260     aStore.SetRootL( id );
       
  1261     
       
  1262     aStore.CommitL();
       
  1263     
       
  1264     CleanupStack::PopAndDestroy( &writestream );
       
  1265     }
       
  1266         
       
  1267