devicediagnosticsfw/diagresultsdb/server/src/diagresultsdbsession.cpp
changeset 32 5d0ec111abfc
parent 27 2c8580950a26
child 35 0deca9b72b62
equal deleted inserted replaced
27:2c8580950a26 32:5d0ec111abfc
     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 CDiagResultsDbSession
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "diagresultsdatabasecommon.h"
       
    20 #include "diagresultsdbsession.h"
       
    21 #include "diagresultsdbserver.h"
       
    22 #include "diagresultsdbtestrecordsubsession.h"
       
    23 #include "diagresultsdatabasetestrecordinfo.h"
       
    24 #include "diagresultsdbtestrecordhandle.h"
       
    25 #include "diagresultsdbtestrecord.h"
       
    26 #include "diagresultsdatabaseitem.h"
       
    27 #include "diagresultsdbrecordinfoarraypacked.h"
       
    28 #include "diagresultsdbcrdc.h"
       
    29 #include "diagresultsdbrecordengineparam.h"
       
    30 
       
    31 //System includes
       
    32 #include <s32mem.h>
       
    33 
       
    34 const TInt KArrayGranuality = 50;
       
    35 const TInt KResultsDatabaseBufferLength=0x700;
       
    36 
       
    37 // ---------------------------------------------------------------------------
       
    38 // constructor - must pass client to CSession
       
    39 // ---------------------------------------------------------------------------
       
    40 // 
       
    41 CDiagResultsDbSession::CDiagResultsDbSession(CDiagResultsDbServer * aServer): 
       
    42        iServer(aServer), iSubsessionContainer( NULL ), iSubsessionIndex(NULL), 
       
    43        iLastResultCommand( 0 ),
       
    44        iStore(NULL), iBufferedLastResults(NULL), iBufferedSingleResult(NULL),
       
    45        iHasWrittenData(EFalse)
       
    46 	{
       
    47 	aServer->IncreaseSessionCount();
       
    48 	}
       
    49 
       
    50 // ---------------------------------------------------------------------------
       
    51 // NewL.
       
    52 // ---------------------------------------------------------------------------
       
    53 // 
       
    54 CDiagResultsDbSession* CDiagResultsDbSession::NewL(CDiagResultsDbServer * aServer)
       
    55 	{
       
    56 	CDiagResultsDbSession* pSession= new (ELeave) CDiagResultsDbSession( aServer );
       
    57 	CleanupStack::PushL( pSession );
       
    58 	pSession->ConstructL();
       
    59 	CleanupStack::Pop();
       
    60 	return pSession;
       
    61 	}
       
    62 
       
    63 // ---------------------------------------------------------------------------
       
    64 // ConstructL.
       
    65 // ---------------------------------------------------------------------------
       
    66 // 
       
    67 void CDiagResultsDbSession::ConstructL()
       
    68 	{
       
    69 	iSubsessionContainer = iServer->NewContainerL();
       
    70 	iSubsessionIndex = CObjectIx::NewL();
       
    71 	
       
    72 	// buffer for IPC. Objects are transmitted in this buffer.
       
    73 	// Size of the buffer has to be selected carefully.
       
    74 	// It should be 'large enough' but not too large.
       
    75 	// If you see too many overflows, increase the size.
       
    76 	iBuffer = CBufFlat::NewL(KArrayGranuality);
       
    77 	iBuffer->ResizeL(KResultsDatabaseBufferLength);
       
    78 	}
       
    79 
       
    80 // ---------------------------------------------------------------------------
       
    81 // Destructor.
       
    82 // ---------------------------------------------------------------------------
       
    83 // 	
       
    84 CDiagResultsDbSession::~CDiagResultsDbSession()
       
    85 	{
       
    86     if ( iBuffer )
       
    87         {
       
    88         iBuffer->Reset();
       
    89         delete iBuffer;
       
    90         iBuffer = NULL;
       
    91         }
       
    92     
       
    93 	// NOTE!
       
    94 	// The deletion order is important here. You must
       
    95 	// delete object indexes first, because this zeros the
       
    96 	// number of references to any CObject type objects. Trying 
       
    97 	// to delete object container first, you get panic
       
    98 	// E32USER-CBase 33: an attempt is made to delete the CObject 
       
    99 	// when the reference count is not zero.
       
   100 	delete iSubsessionIndex;
       
   101 
       
   102     if ( iSubsessionContainer )
       
   103         {
       
   104         iServer->RemoveContainer( iSubsessionContainer );
       
   105         }
       
   106 	
       
   107 	delete iStore;
       
   108 	
       
   109     if ( iServer )
       
   110         {
       
   111         iServer->DecreaseSessionCount();
       
   112         }
       
   113 	
       
   114 	if ( iBufferedLastResults )
       
   115 	    {
       
   116 	    iBufferedLastResults->ResetAndDestroy();
       
   117 	    iBufferedLastResults->Close();
       
   118 	    delete iBufferedLastResults;
       
   119 	    iBufferedLastResults = 0;
       
   120 	    }
       
   121 	    
       
   122     if ( iBufferedSingleResult )
       
   123         {
       
   124         delete iBufferedSingleResult;
       
   125         iBufferedSingleResult = NULL;
       
   126         }
       
   127 	}
       
   128 
       
   129 // ---------------------------------------------------------------------------
       
   130 // Service client requests.
       
   131 // ---------------------------------------------------------------------------
       
   132 // 
       
   133 void CDiagResultsDbSession::ServiceL(const RMessage2& aMessage)
       
   134 	{
       
   135 	LOGME("CDiagResultsDbSession::ServiceL");
       
   136 	TBool async = EFalse;
       
   137 	TRAPD( err, async = DispatchMessageL( aMessage ) );
       
   138 	LOGME1("CDiagResultsDbSession::ServiceL %d",err);
       
   139 	if ( !async ) 
       
   140 	    {
       
   141 	    aMessage.Complete( err );
       
   142 	    }
       
   143 	}
       
   144 
       
   145 // ---------------------------------------------------------------------------
       
   146 // service a client request; test the opcode and then do appropriate servicing
       
   147 // ---------------------------------------------------------------------------
       
   148 //     
       
   149 TBool CDiagResultsDbSession::DispatchMessageL(const RMessage2 &aMessage)
       
   150 	{
       
   151 	LOGME("CDiagResultsDbSession::DispatchMessageL");
       
   152 	iMsg = aMessage;
       
   153 	TInt function = aMessage.Function();
       
   154 	LOGME1("CDiagResultsDbSession::DispatchMessageL - %d",function);
       
   155 	TInt handle(0);
       
   156 	CObject* subsession = NULL;
       
   157 	switch( function )
       
   158         {
       
   159 	case DiagResultsDbCommon::EConnect:
       
   160 	    {
       
   161 	    LOGME("CDiagResultsDbSession::EConnect");
       
   162 	    TPckgBuf<TUid> uidpckg;
       
   163 	    aMessage.Read(0, uidpckg);
       
   164         iDbUid = uidpckg();
       
   165         
       
   166         iStore = CDiagResultsDbStore::NewL( iDbUid );
       
   167 		return EFalse;
       
   168 	    }
       
   169         
       
   170     case DiagResultsDbCommon::EClose:
       
   171         {        
       
   172         LOGME("CDiagResultsDbSession::EClose");
       
   173         aMessage.Complete (KErrNone);
       
   174                       
       
   175         return ETrue;
       
   176         }
       
   177         
       
   178     case DiagResultsDbCommon::EGetRecordCount:
       
   179         {        
       
   180         LOGME("CDiagResultsDbSession::EGetRecordCount");
       
   181         RArray<TUid> uids;
       
   182         CleanupClosePushL ( uids );
       
   183         iStore->RecordUidsL( uids );
       
   184         
       
   185         TPckgBuf<TUint> pckg( uids.Count() );
       
   186         aMessage.Write(0, pckg);
       
   187         
       
   188         CleanupStack::PopAndDestroy( &uids );
       
   189         return EFalse;
       
   190         }
       
   191         
       
   192 	case DiagResultsDbCommon::EConnectSubsession:
       
   193 			LOGME("CDiagResultsDbSession::EConnectSubsession");
       
   194 	    ConnectSubsessionL( aMessage );
       
   195 		return EFalse;			
       
   196 		
       
   197 	case DiagResultsDbCommon::ESubsessionCreateNewRecord:
       
   198 			LOGME("CDiagResultsDbSession::ESubsessionCreateNewRecord");
       
   199 	    CreateNewRecordL( aMessage );
       
   200 	    HasWritten();
       
   201 		return EFalse;
       
   202 		
       
   203 	case DiagResultsDbCommon::ECloseSubsession:
       
   204 		LOGME("CDiagResultsDbSession::ECloseSubsession");
       
   205 		CloseSubsessionL();
       
   206 		return EFalse;
       
   207 		
       
   208     case DiagResultsDbCommon::EGetLastRecord:  
       
   209     		LOGME("CDiagResultsDbSession::EGetLastRecord");
       
   210         GetLastRecordL( aMessage );
       
   211         return EFalse;
       
   212         
       
   213     case DiagResultsDbCommon::EGetLastNotCompletedRecord:
       
   214     		LOGME("CDiagResultsDbSession::EGetLastNotCompletedRecord");
       
   215         GetLastNotCompletedRecordL( aMessage );
       
   216         return EFalse;
       
   217     
       
   218     case DiagResultsDbCommon::EGetRecordList: //record uids 
       
   219     		LOGME("CDiagResultsDbSession::EGetRecordList");
       
   220         GetRecordListL( aMessage );
       
   221         return EFalse;
       
   222 
       
   223     case DiagResultsDbCommon::EGetRecordInfoList:
       
   224     		LOGME("CDiagResultsDbSession::EGetRecordInfoList");
       
   225         GetRecordInfoListL( aMessage );
       
   226         return EFalse;
       
   227 
       
   228     case DiagResultsDbCommon::EInitiateGetLastResults:  //Async
       
   229         {     
       
   230         LOGME("CDiagResultsDbSession::EInitiateGetLastResults");
       
   231         ReadBufferL( aMessage, 0, iBuffer );
       
   232                
       
   233         iLastResultsMsg = iMsg;
       
   234         	
       
   235         iLastResultCommand = DiagResultsDbCommon::EInitiateGetLastResults;	
       
   236         	
       
   237         if ( iBufferedLastResults )
       
   238 	        {
       
   239 	        iBufferedLastResults->ResetAndDestroy();
       
   240 	        iBufferedLastResults->Close();
       
   241 	        delete iBufferedLastResults;
       
   242 	        iBufferedLastResults = 0;
       
   243 	        }
       
   244 	        
       
   245         iStore->ExistingRecordsAsyncL( *this );
       
   246         return ETrue;
       
   247         }
       
   248     
       
   249     case DiagResultsDbCommon::EInitiateGetSingleLastResult: //Async
       
   250         {           
       
   251         LOGME("CDiagResultsDbSession::EInitiateGetSingleLastResult");     
       
   252         iLastSingleResultsMsg = iMsg;
       
   253         
       
   254         iLastResultCommand = DiagResultsDbCommon::EInitiateGetSingleLastResult;	
       
   255         
       
   256         if ( iBufferedSingleResult )
       
   257             {
       
   258             delete iBufferedSingleResult;
       
   259             iBufferedSingleResult = NULL;
       
   260             }
       
   261             
       
   262         iStore->ExistingRecordsAsyncL( *this );
       
   263         return ETrue;  
       
   264         }
       
   265     
       
   266     
       
   267     case DiagResultsDbCommon::EGetLastResults:    
       
   268     		LOGME("CDiagResultsDbSession::EGetLastResults");     
       
   269         GetLastResultsL( aMessage );
       
   270         return EFalse;
       
   271         
       
   272     case DiagResultsDbCommon::EGetSingleLastResult: 
       
   273     		LOGME("CDiagResultsDbSession::EGetSingleLastResult");        
       
   274         GetSingleLastResultL( aMessage );
       
   275         return EFalse;    
       
   276         
       
   277     case DiagResultsDbCommon::ECancelInitiateGetLastResults:
       
   278         {
       
   279         LOGME("CDiagResultsDbSession::ECancelInitiateGetLastResults");        
       
   280         CancelLastResultsL( aMessage );
       
   281         return EFalse;
       
   282         }
       
   283        
       
   284 	// Sub-session requests. See CDiagResultsDbTestRecordSubsession.
       
   285     case DiagResultsDbCommon::ESubsessionGetTestRecordId:
       
   286     case DiagResultsDbCommon::ESubsessionTestCompleted:
       
   287     case DiagResultsDbCommon::ESubsessionIsTestCompleted:
       
   288     case DiagResultsDbCommon::ESubsessionGetRecordInfo:
       
   289     case DiagResultsDbCommon::ESubsessionGetTestUids:
       
   290     case DiagResultsDbCommon::ESubsessionSuspend:
       
   291     case DiagResultsDbCommon::ESubsessionIsSuspended:
       
   292     case DiagResultsDbCommon::ESubsessionLogTestResult:
       
   293     case DiagResultsDbCommon::ESubsessionGetTestResult:
       
   294     case DiagResultsDbCommon::ESubsessionGetTestResults:
       
   295     case DiagResultsDbCommon::ESubsessionGetEngineParam:
       
   296     case DiagResultsDbCommon::ESubsessionGetStatus:
       
   297     case DiagResultsDbCommon::ESubsessionCancelLogTestResult:
       
   298     LOGME("CDiagResultsDbSession::ESubsessionCancelLogTestResult");        
       
   299 		handle = aMessage.Int3();
       
   300 		subsession = iSubsessionIndex->At( handle );
       
   301 		return static_cast<CDiagResultsDbTestRecordSubsession*>(subsession)
       
   302 		                                    ->DispatchMessageL( aMessage );
       
   303 	default:
       
   304 		aMessage.Panic( _L("DiagSrv panic: unknown command"), 
       
   305 		                    DiagResultsDbCommon::EBadRequest );
       
   306 		return EFalse;
       
   307 		}
       
   308 	}
       
   309 
       
   310 // ---------------------------------------------------------------------------
       
   311 // Get function.
       
   312 // ---------------------------------------------------------------------------
       
   313 // 
       
   314 TBool CDiagResultsDbSession::SessionHasWritten() const
       
   315     {
       
   316     return iHasWrittenData;
       
   317     }
       
   318             
       
   319 // ---------------------------------------------------------------------------
       
   320 // Connect to a subsession. Test record represents the connected subsession.
       
   321 // ---------------------------------------------------------------------------
       
   322 //     
       
   323 void CDiagResultsDbSession::ConnectSubsessionL( const RMessage2 &aMessage )    
       
   324     {
       
   325     TPckgBuf<TUid> uidpckg;
       
   326 	aMessage.Read(0, uidpckg);
       
   327     TUid recordUid = uidpckg(); 
       
   328     
       
   329     TPckgBuf<TBool> readOnlyPckg;
       
   330 	aMessage.Read(1, readOnlyPckg);
       
   331     TBool readonly = readOnlyPckg();
       
   332     
       
   333 	CDiagResultsDbTestRecordHandle* handle = iStore->OpenExistingHandleL( 
       
   334 	                                           recordUid );
       
   335 	                                           
       
   336     if ( readonly ) 
       
   337         {
       
   338         // keep the record as it is.
       
   339         }
       
   340     else
       
   341         {
       
   342         if ( handle->RecordInfo().iCompleted )
       
   343             {
       
   344             delete handle;
       
   345             handle = 0;
       
   346             User::Leave( KErrAlreadyExists );
       
   347             }
       
   348         
       
   349         handle->RecordInfo().iRecordStatus = 
       
   350                 TDiagResultsDatabaseTestRecordInfo::EOpen;
       
   351         }
       
   352 	                                           
       
   353     CreateSubsessionL( handle, readonly );
       
   354     }
       
   355 
       
   356 // ---------------------------------------------------------------------------
       
   357 // Create a new record. This does not write data into the db file.
       
   358 // ---------------------------------------------------------------------------
       
   359 //     
       
   360 void CDiagResultsDbSession::CreateNewRecordL ( const RMessage2 &aMessage )
       
   361     {
       
   362     
       
   363     ReadBufferL( aMessage, 1, iBuffer );
       
   364     
       
   365     RBufReadStream stream( *iBuffer );
       
   366     CleanupClosePushL ( stream );
       
   367     
       
   368     CDiagResultsDbRecordEngineParam* params = 
       
   369                             CDiagResultsDbRecordEngineParam::NewL ( stream );
       
   370     CleanupStack::PushL( params );                         
       
   371 
       
   372     CDiagResultsDbTestRecordHandle* handle = iStore->CreateNewRecordL( params );
       
   373 
       
   374     handle->RecordInfo().iRecordStatus = 
       
   375                                 TDiagResultsDatabaseTestRecordInfo::EOpen;
       
   376 
       
   377     CleanupStack::Pop(); //params    
       
   378     CleanupStack::PopAndDestroy( &stream );
       
   379 
       
   380 	CreateSubsessionL(handle, EFalse);
       
   381 		
       
   382 	TPckgBuf<TUid> recorduidpckg( handle->RecordInfo().iRecordId );
       
   383 		
       
   384 	aMessage.Write(0, recorduidpckg );
       
   385     }
       
   386     
       
   387 // ---------------------------------------------------------------------------
       
   388 // Return the database file uid.
       
   389 // ---------------------------------------------------------------------------
       
   390 //      
       
   391 TUid CDiagResultsDbSession::DbUid() const
       
   392     {
       
   393     return iDbUid;
       
   394     }
       
   395 
       
   396 // ---------------------------------------------------------------------------
       
   397 // Create a new subsession.
       
   398 // ---------------------------------------------------------------------------
       
   399 //     
       
   400 void CDiagResultsDbSession::CreateSubsessionL( 
       
   401                             CDiagResultsDbTestRecordHandle* aTestRecordHandle,
       
   402                             TBool aReadonly )
       
   403 	{
       
   404     TInt handle(0);
       
   405     CObject* subsession = NULL;
       
   406     
       
   407 	// Create sub-session object
       
   408 	subsession = CDiagResultsDbTestRecordSubsession::NewL( this, 
       
   409 	                                                    aTestRecordHandle,
       
   410 	                                                    aReadonly );
       
   411     CleanupStack::PushL( subsession );
       
   412     iSubsessionContainer->AddL( subsession );
       
   413     CleanupStack::Pop();
       
   414 
       
   415 	// Create sub-session handle
       
   416 	TRAPD( err, handle = iSubsessionIndex->AddL( subsession ) );
       
   417 
       
   418 	// Remember to remove session object from object container
       
   419 	if( err != KErrNone )
       
   420 		{
       
   421 		iSubsessionContainer->Remove( subsession ); 
       
   422 		User::Leave( DiagResultsDbCommon::ESvrCreateSubsession );
       
   423 		}
       
   424 
       
   425     // Package to pass information to the client
       
   426     TPckgC<TInt> handlePckg(handle);
       
   427     
       
   428     // Send handle to the client
       
   429     TRAP( err, iMsg.WriteL( 3, handlePckg ) );
       
   430 	if( err != KErrNone )
       
   431 		{
       
   432 		iSubsessionIndex->Remove(handle);
       
   433 		User::Leave( DiagResultsDbCommon::ESvrCreateSubsession );
       
   434 		}
       
   435 
       
   436 	return;
       
   437 	}
       
   438 
       
   439 // ---------------------------------------------------------------------------
       
   440 // Close existing subsession.
       
   441 // ---------------------------------------------------------------------------
       
   442 // 
       
   443 void CDiagResultsDbSession::CloseSubsessionL()
       
   444 	{
       
   445 	TInt handle = iMsg.Int3();
       
   446 	iSubsessionIndex->Remove(handle);
       
   447 	}
       
   448 
       
   449 // ---------------------------------------------------------------------------
       
   450 // Return store that is responsible for handling the database file.
       
   451 // ---------------------------------------------------------------------------
       
   452 // 	
       
   453 CDiagResultsDbStore& CDiagResultsDbSession::Store()
       
   454     {
       
   455     return *iStore;
       
   456     }
       
   457 
       
   458 // ---------------------------------------------------------------------------
       
   459 // Service function. Searches for newest test results. 
       
   460 //    Related functions: 
       
   461 //    ExistingRecordsAsyncL (initiates async fetch of test records)
       
   462 //    CancelLastResultsL (cancel async fetch)
       
   463 //    ExistingRecordsL (retrieves test records)
       
   464 // ---------------------------------------------------------------------------
       
   465 // 
       
   466 void CDiagResultsDbSession::GetLastResultsL( const RMessage2 &aMessage )
       
   467     {
       
   468     if ( iBufferedLastResults == NULL )
       
   469         {
       
   470         User::Leave ( KErrNotFound );
       
   471         }
       
   472        
       
   473     ReadBufferL( aMessage, 0, iBuffer );
       
   474       
       
   475     RBufWriteStream stream ( *iBuffer );
       
   476     CleanupClosePushL( stream );
       
   477     
       
   478     stream.WriteInt16L( iBufferedLastResults->Count() );
       
   479     
       
   480     for ( TInt i = 0; i < iBufferedLastResults->Count(); ++i )
       
   481         {    
       
   482         CDiagResultsDatabaseItem* item = (*iBufferedLastResults)[i];
       
   483         
       
   484         if ( item == NULL )
       
   485             {
       
   486             stream.WriteUint8L(0); 
       
   487             }
       
   488         else 
       
   489             {
       
   490             stream.WriteUint8L(1);
       
   491             (*iBufferedLastResults)[i]->ExternalizeL( stream );
       
   492             }
       
   493         }
       
   494 
       
   495     if ( iBuffer->Ptr(0).Length() > aMessage.GetDesMaxLength(0) )
       
   496         {
       
   497         User::Leave( KErrOverflow );
       
   498         }
       
   499    
       
   500     stream.CommitL();
       
   501      
       
   502     CleanupStack::PopAndDestroy( &stream );
       
   503     
       
   504     aMessage.Write( 0, iBuffer->Ptr(0) ); //write to client's address space 
       
   505          
       
   506     iBufferedLastResults->ResetAndDestroy();
       
   507     iBufferedLastResults->Close();
       
   508     delete iBufferedLastResults;
       
   509     iBufferedLastResults = NULL;   
       
   510     }
       
   511 
       
   512 
       
   513 // ---------------------------------------------------------------------------
       
   514 // Service function. Get single test result (the newest).
       
   515 // ---------------------------------------------------------------------------
       
   516 //   
       
   517 void CDiagResultsDbSession::GetSingleLastResultL( const RMessage2 &aMessage )
       
   518     {
       
   519     ReadBufferL( aMessage, 0, iBuffer );
       
   520           
       
   521     RBufWriteStream stream ( *iBuffer );
       
   522     CleanupClosePushL( stream );
       
   523     
       
   524     if ( iBufferedSingleResult )
       
   525         {
       
   526         stream.WriteInt8L( 1 );
       
   527         
       
   528         iBufferedSingleResult->ExternalizeL( stream );
       
   529         
       
   530         }
       
   531     else //NULL
       
   532         {
       
   533         stream.WriteInt8L( 0 );
       
   534         }
       
   535     
       
   536     stream.CommitL();
       
   537     CleanupStack::PopAndDestroy( &stream );
       
   538     
       
   539     aMessage.Write( 0, iBuffer->Ptr(0) );
       
   540             
       
   541     delete iBufferedSingleResult;
       
   542     iBufferedSingleResult = NULL;
       
   543     }
       
   544 
       
   545 
       
   546 // ---------------------------------------------------------------------------
       
   547 // Service function. Cancel InitiateGetLastResults method.
       
   548 // ---------------------------------------------------------------------------
       
   549 //     
       
   550 void CDiagResultsDbSession::CancelLastResultsL( const RMessage2 & /*aMessage*/ )
       
   551     {
       
   552       if ( !iLastResultsMsg.IsNull() )
       
   553         {
       
   554         iStore->Cancel();    
       
   555         iLastResultsMsg.Complete( KErrCancel );  
       
   556         
       
   557         if ( iBufferedLastResults )
       
   558             {
       
   559             iBufferedLastResults->ResetAndDestroy();
       
   560             delete iBufferedLastResults;
       
   561             iBufferedLastResults = NULL;
       
   562             }
       
   563         }
       
   564     }
       
   565 
       
   566 // ---------------------------------------------------------------------------
       
   567 // Service function. Retrieve uid of the newest test record.
       
   568 // ---------------------------------------------------------------------------
       
   569 // 
       
   570 void CDiagResultsDbSession::GetLastRecordL( const RMessage2 &aMessage )
       
   571     {
       
   572     RArray<TUid> uids;
       
   573     CleanupClosePushL ( uids );
       
   574     iStore->RecordUidsL( uids );
       
   575     
       
   576     if ( uids.Count() == 0 )
       
   577         {
       
   578         User::Leave( KErrNotFound );
       
   579         }
       
   580     
       
   581     TPckgBuf<TUid> pckg( uids[uids.Count() -1] ); //newest record is the last
       
   582     aMessage.Write( 0, pckg );
       
   583     
       
   584     CleanupStack::PopAndDestroy( &uids );
       
   585     }
       
   586 
       
   587 
       
   588 // ---------------------------------------------------------------------------
       
   589 // Service function. Try to find a test record that was suspended.
       
   590 // Leave with KErrNotFound if such test record is not found.
       
   591 // ---------------------------------------------------------------------------
       
   592 // 
       
   593 void CDiagResultsDbSession::GetLastNotCompletedRecordL( const RMessage2 &aMessage )
       
   594     {
       
   595     RArray<TUid> uids;
       
   596     CleanupClosePushL ( uids );
       
   597     iStore->RecordUidsL( uids );
       
   598     
       
   599     TBool found = EFalse;
       
   600     
       
   601     // newest record are on the top.
       
   602 	for (TInt i = uids.Count() -1; i >= 0; --i)
       
   603 	    {
       
   604 	    CDiagResultsDbTestRecordHandle* handle = 
       
   605 	                                iStore->OpenExistingHandleL( uids[i] );
       
   606 	    
       
   607 	    CleanupStack::PushL (handle);
       
   608         
       
   609         if( handle->RecordInfo().iRecordStatus != 
       
   610                                  TDiagResultsDatabaseTestRecordInfo::ECompleted &&
       
   611                !handle->RecordInfo().iCompleted )
       
   612                                  
       
   613             {
       
   614             TPckgBuf<TUid> pckg( handle->RecordInfo().iRecordId ); 
       
   615             aMessage.Write( 0, pckg );
       
   616             found = ETrue;
       
   617             CleanupStack::PopAndDestroy( handle );
       
   618             break;
       
   619             }     
       
   620         
       
   621         CleanupStack::PopAndDestroy( handle );
       
   622 	    }
       
   623 	
       
   624     CleanupStack::PopAndDestroy( &uids );
       
   625 	 
       
   626     if ( !found )
       
   627         {
       
   628         User::Leave ( KErrNotFound );
       
   629         }  
       
   630     }
       
   631 
       
   632 // ---------------------------------------------------------------------------
       
   633 // Service function. Retrieve all test record uids that there are.
       
   634 // ---------------------------------------------------------------------------
       
   635 //     
       
   636 void CDiagResultsDbSession::GetRecordListL( const RMessage2 &aMessage )
       
   637     {    
       
   638     ReadBufferL( aMessage, 0, iBuffer );
       
   639    
       
   640     RArray<TUid> uids; 
       
   641     CleanupClosePushL( uids );
       
   642     iStore->RecordUidsL( uids );
       
   643     
       
   644     RBufWriteStream stream ( *iBuffer );
       
   645     CleanupClosePushL( stream );
       
   646     stream.WriteInt16L( uids.Count() );
       
   647     
       
   648     for ( TInt i = 0; i < uids.Count(); ++i )
       
   649         {    
       
   650         stream.WriteInt32L( uids[i].iUid );  
       
   651         }
       
   652 
       
   653     if ( iBuffer->Ptr(0).Length() > aMessage.GetDesMaxLength(0) )
       
   654         {
       
   655         User::Leave( KErrOverflow );
       
   656         }
       
   657     
       
   658     aMessage.Write( 0, iBuffer->Ptr(0) ); //write to client's address space 
       
   659    
       
   660     CleanupStack::PopAndDestroy( &stream );
       
   661     CleanupStack::PopAndDestroy( &uids );
       
   662 
       
   663     }
       
   664 
       
   665 // ---------------------------------------------------------------------------
       
   666 // Service function. Return overviews of test records.
       
   667 // ---------------------------------------------------------------------------
       
   668 //     
       
   669 void CDiagResultsDbSession::GetRecordInfoListL( const RMessage2 &aMessage )
       
   670     {
       
   671     ReadBufferL( aMessage, 0, iBuffer );
       
   672     
       
   673     CArrayFixFlat<TDiagResultsDatabaseTestRecordInfo>* array = new (ELeave) 
       
   674         CArrayFixFlat<TDiagResultsDatabaseTestRecordInfo>(KArrayGranuality);
       
   675     CleanupStack::PushL (array);
       
   676     
       
   677     RArray<TUid> uids;
       
   678     CleanupClosePushL ( uids );
       
   679     iStore->RecordUidsL( uids );
       
   680     
       
   681 	for (TInt i = 0; i < uids.Count(); ++i)
       
   682 	    {
       
   683 	    CDiagResultsDbTestRecordHandle* handle = 
       
   684 	                                iStore->OpenExistingHandleL( uids[i] );
       
   685 	    
       
   686 	    CleanupStack::PushL (handle);
       
   687         array->AppendL( handle->RecordInfo() );
       
   688         
       
   689         CleanupStack::PopAndDestroy( handle );
       
   690 	    }
       
   691 	
       
   692 	CleanupStack::PopAndDestroy( &uids );
       
   693 	
       
   694     TDiagResultsDbRecordInfoArrayPacked packedArray ( iBuffer );
       
   695     packedArray.PackArrayL ( *array );
       
   696     
       
   697     if ( iBuffer->Ptr(0).Length() > aMessage.GetDesMaxLength(0) )
       
   698         {
       
   699         User::Leave( KErrOverflow );
       
   700         }
       
   701 	
       
   702     aMessage.Write( 0, iBuffer->Ptr(0) ); //write to client's address space 
       
   703    
       
   704     CleanupStack::PopAndDestroy( array );
       
   705     
       
   706     }
       
   707  
       
   708 // ---------------------------------------------------------------------------
       
   709 // Helper function to read a buffer from client side. Leaves the buffer
       
   710 // onto cleanup stack IF it has to create a new one.
       
   711 // ---------------------------------------------------------------------------
       
   712 //    
       
   713 void CDiagResultsDbSession::ReadBufferL(const RMessage2& aMessage, TInt aParam, 
       
   714                                                             CBufFlat*& aBuffer)
       
   715 	{
       
   716 	TInt desLen = aMessage.GetDesLengthL(aParam);
       
   717 
       
   718 	if(desLen >= 0)
       
   719 		{		
       
   720 		if (aBuffer==NULL)
       
   721 			{
       
   722 			aBuffer = CBufFlat::NewL(KArrayGranuality);
       
   723 			aBuffer->ResizeL(desLen);
       
   724 			CleanupStack::PushL(aBuffer);
       
   725 			}
       
   726 		else if (desLen > aBuffer->Ptr(0).MaxLength())
       
   727 			{
       
   728 			iBuffer->Delete( 0, iBuffer->Size() ); // delete old data.
       
   729 			// we have to increase the size of aBuffer	
       
   730 			aBuffer->ResizeL(desLen);		
       
   731 			}
       
   732 
       
   733 		TPtr8 desPtr = aBuffer->Ptr(0);
       
   734 		aMessage.ReadL(aParam, desPtr);
       
   735 
       
   736 		}
       
   737 	else
       
   738 		{
       
   739 		// desLen is negative leave with an error.
       
   740 		User::Leave(KErrArgument);
       
   741 		}
       
   742 	}   
       
   743 
       
   744 // ---------------------------------------------------------------------------
       
   745 // Store observer method. This is called after store has retrieved
       
   746 // test records from the DB file.
       
   747 // ---------------------------------------------------------------------------
       
   748 // 
       
   749 void CDiagResultsDbSession::ExistingRecordsL( TInt aError, 
       
   750                             RPointerArray<CDiagResultsDbTestRecord>* aArray )
       
   751     {
       
   752     CleanupStack::PushL ( aArray );
       
   753     CleanupResetAndDestroyClosePushL( *aArray );
       
   754 
       
   755     //Check if there were any errors during loading the test records.
       
   756     if ( aError != KErrNone )
       
   757         {
       
   758         
       
   759         if ( iLastResultCommand == 
       
   760              DiagResultsDbCommon::EInitiateGetLastResults )
       
   761             {
       
   762             iLastResultsMsg.Complete ( aError );            
       
   763             }
       
   764         else if ( iLastResultCommand == 
       
   765                   DiagResultsDbCommon::EInitiateGetSingleLastResult  )
       
   766             {
       
   767             iLastSingleResultsMsg.Complete ( aError );
       
   768             }        
       
   769         
       
   770         CleanupStack::PopAndDestroy( aArray );
       
   771         CleanupStack::PopAndDestroy( aArray ); //delete the pointer  
       
   772         return;
       
   773         }
       
   774         	
       
   775 	switch( iLastResultCommand )
       
   776         {
       
   777 	
       
   778 	//Find multiple last results
       
   779 	//buffer contains the uids to be searched.
       
   780 	//See RDiagResultsDatabase::InitiateGetLastResults.
       
   781 	case DiagResultsDbCommon::EInitiateGetLastResults:
       
   782 	    {
       
   783         //Trap is needed so that we can complete client's request
       
   784         //if any errors occur.
       
   785         TRAPD(error, FindLastResultsL( *aArray ));	        
       
   786 	        	    
       
   787 	    if ( error != KErrNone )
       
   788 	        {	        
       
   789 	        iLastResultsMsg.Complete (error);	        
       
   790 	        break;
       
   791 	        }
       
   792 	    else 
       
   793 	        {
       
   794 	        iLastResultsMsg.Complete (KErrNone);    
       
   795 	        }
       
   796 	    	    	  
       
   797 	    break;
       
   798 	    }
       
   799 	    
       
   800 	  // Find single test result  
       
   801 	  // see RDiagResultsDatabase::InitiateGetLastResult.
       
   802      case DiagResultsDbCommon::EInitiateGetSingleLastResult:
       
   803         {        
       
   804         TPckgBuf<TUid> uidpckg;
       
   805 	    iLastSingleResultsMsg.Read(0, uidpckg);
       
   806         TUid resultsItemUid = uidpckg();
       
   807                  	    	            
       
   808         CDiagResultsDatabaseItem* item = NULL;
       
   809         
       
   810         // Trap any errors and complete client's request if there
       
   811         // are any errors.
       
   812         TRAPD(error, item = FindDatabaseItemL( resultsItemUid, aArray)) ;	                            	                           
       
   813 
       
   814         if ( error != KErrNone )
       
   815             {
       
   816             delete item;
       
   817             item = NULL;
       
   818             
       
   819             iLastSingleResultsMsg.Complete (error);
       
   820             break;
       
   821             }
       
   822 	        
       
   823 	    if ( item == NULL ) //Not found
       
   824 	        {
       
   825 	        iBufferedSingleResult = NULL;
       
   826 	        
       
   827 	        //Check also the last results buffer  
       
   828 	        CheckLastResultsBufferL( resultsItemUid, iBufferedSingleResult );
       
   829 	        }
       
   830 	    else 
       
   831 	        {	                	                
       
   832 	        iBufferedSingleResult = item;
       
   833 	        }          
       
   834 	       
       
   835 	   
       
   836 	       
       
   837 	    iLastSingleResultsMsg.Complete (KErrNone);
       
   838 	    break;
       
   839         }  
       
   840 	  
       
   841 	  default:
       
   842 	    {
       
   843 	    User::Panic ( _L("Diag results DB"), 
       
   844 	                  DiagResultsDbCommon::EUnknownLastResultState );
       
   845 	    }	    	    
       
   846       }
       
   847     
       
   848     iLastResultCommand = 0;  
       
   849       
       
   850     CleanupStack::PopAndDestroy( aArray ); //call reset and destroy + close
       
   851     CleanupStack::PopAndDestroy( aArray ); //delete the pointer
       
   852     }
       
   853 
       
   854 
       
   855 // ---------------------------------------------------------------------------
       
   856 // Read UIDs from a stream and search last results.
       
   857 // ---------------------------------------------------------------------------
       
   858 // 
       
   859 void CDiagResultsDbSession::FindLastResultsL( 
       
   860                             RPointerArray<CDiagResultsDbTestRecord>& aArray )
       
   861     {
       
   862     
       
   863 	CArrayFixFlat<TUid>* uidArray = new (ELeave) 
       
   864 	                                    CArrayFixFlat<TUid>(KArrayGranuality);
       
   865 	CleanupStack::PushL( uidArray );
       
   866 	     
       
   867     RBufReadStream stream( *iBuffer );
       
   868     CleanupClosePushL ( stream );
       
   869         
       
   870     TInt8 count = stream.ReadInt8L();
       
   871         
       
   872     for ( TInt i = 0; i < count; ++i )
       
   873         {
       
   874         TInt32 uid = stream.ReadInt32L();
       
   875             
       
   876         uidArray->AppendL( TUid::Uid( uid ));
       
   877         }
       
   878 	    
       
   879     CleanupStack::PopAndDestroy( &stream );	 
       
   880 	    	    
       
   881 	iBufferedLastResults = new (ELeave) RPointerArray<CDiagResultsDatabaseItem>;
       
   882 	    	    
       
   883 	SearchLastResultsL( *uidArray, aArray, *iBufferedLastResults  );
       
   884 	
       
   885 	//last results could be also in the last results buffer.
       
   886 	CheckLastResultsBufferL( *uidArray, *iBufferedLastResults );
       
   887 	    
       
   888 	  // there must be exactly the same number of cells in both arrays. 
       
   889 	if ( uidArray->Count() != iBufferedLastResults->Count() ) 
       
   890 	    {
       
   891 	    User::Panic ( _L("Diag results DB"), 
       
   892 	                  DiagResultsDbCommon::EGetLastResultsMismatch );
       
   893 	    }
       
   894 	    
       
   895 	CleanupStack::PopAndDestroy( uidArray );   
       
   896     }
       
   897 
       
   898 
       
   899 // ---------------------------------------------------------------------------
       
   900 // Check last result buffer for test results.
       
   901 // ---------------------------------------------------------------------------
       
   902 // 
       
   903 void CDiagResultsDbSession::CheckLastResultsBufferL( 
       
   904                          const CArrayFixFlat<TUid>& aUidArray,                           
       
   905                          RPointerArray<CDiagResultsDatabaseItem>& aResultsArray )
       
   906     {        
       
   907     CDiagResultsDbTestRecord* buffer = iStore->OpenExistingLastResultsBufferL(); 
       
   908     CleanupStack::PushL( buffer );
       
   909     
       
   910     for (TInt i = 0; i < aResultsArray.Count(); ++i)
       
   911         {        
       
   912         if ( aResultsArray[i] == NULL )
       
   913             {
       
   914             TUid uid = aUidArray[i];
       
   915             
       
   916             CDiagResultsDatabaseItem* item = buffer->FindTestRecord( uid );
       
   917             
       
   918             if ( item )
       
   919                 {
       
   920                 buffer->RemoveL( uid );
       
   921                 aResultsArray[i] = item;
       
   922                 }            
       
   923             }        
       
   924         }
       
   925     
       
   926     CleanupStack::PopAndDestroy( buffer );
       
   927     }
       
   928 
       
   929 
       
   930 // ---------------------------------------------------------------------------
       
   931 // Check last result buffer for test result.
       
   932 // ---------------------------------------------------------------------------
       
   933 // 
       
   934 void CDiagResultsDbSession::CheckLastResultsBufferL( 
       
   935                          TUid aTestUid,                           
       
   936                          CDiagResultsDatabaseItem*& aResult )
       
   937     {
       
   938     
       
   939     
       
   940     CDiagResultsDbTestRecord* buffer = iStore->OpenExistingLastResultsBufferL(); 
       
   941     CleanupStack::PushL( buffer );
       
   942  
       
   943     CDiagResultsDatabaseItem* item = buffer->FindTestRecord( aTestUid );
       
   944             
       
   945     if ( item )
       
   946         {
       
   947         buffer->RemoveL( aTestUid );
       
   948         aResult = item;                                                
       
   949         }
       
   950     
       
   951     CleanupStack::PopAndDestroy( buffer );
       
   952     }
       
   953 
       
   954 
       
   955 // ---------------------------------------------------------------------------
       
   956 // Searches for the newest test results.
       
   957 // ---------------------------------------------------------------------------
       
   958 // 
       
   959 void CDiagResultsDbSession::SearchLastResultsL( 
       
   960                          const CArrayFixFlat<TUid>& aUidArray, 
       
   961                          RPointerArray<CDiagResultsDbTestRecord>& aTestRecordArray, 
       
   962                          RPointerArray<CDiagResultsDatabaseItem>& aResultsArray )
       
   963             
       
   964     {   
       
   965     //Search all records for certain uid.
       
   966 	for ( TInt i = 0; i < aUidArray.Count(); ++i )
       
   967 	    {
       
   968 	      
       
   969 	    CDiagResultsDatabaseItem* item = 
       
   970 	                            FindDatabaseItemL( aUidArray[i], &aTestRecordArray );	                            	                           
       
   971 	        
       
   972 	    if ( item == NULL ) //Not found
       
   973 	        {
       
   974 	        aResultsArray.Append(NULL);
       
   975 	        }
       
   976 	     else 
       
   977 	        {	                	                
       
   978 	        aResultsArray.Append( item );
       
   979 	        }          
       
   980 	    }
       
   981     }
       
   982 	     
       
   983 
       
   984 // ---------------------------------------------------------------------------
       
   985 // Indicates has session written any data into the DB file. 
       
   986 // To be exact only subsession writes data into the file.
       
   987 // ---------------------------------------------------------------------------
       
   988 //     
       
   989 void CDiagResultsDbSession::HasWritten()
       
   990     {
       
   991     iHasWrittenData = ETrue;
       
   992     }
       
   993 
       
   994 // ---------------------------------------------------------------------------
       
   995 // Turn off compacting.
       
   996 // ---------------------------------------------------------------------------
       
   997 //  
       
   998 void CDiagResultsDbSession::DoNotCompact()
       
   999     {
       
  1000     iHasWrittenData = EFalse;
       
  1001     }
       
  1002 
       
  1003 // ---------------------------------------------------------------------------
       
  1004 // Helper function to seach an item from a pointer array.
       
  1005 // Starts from the newest record to search for an UID.
       
  1006 // ---------------------------------------------------------------------------
       
  1007 // 
       
  1008 CDiagResultsDatabaseItem* CDiagResultsDbSession::FindDatabaseItemL( TUid aUid, 
       
  1009                              RPointerArray<CDiagResultsDbTestRecord>* aArray )    
       
  1010     {
       
  1011     
       
  1012     //Check that there is a test record.
       
  1013     if ( !aArray || aArray->Count() == 0 )
       
  1014         {
       
  1015         return NULL;
       
  1016         }
       
  1017     
       
  1018     // start from the newest record
       
  1019     for (TInt x = aArray->Count() -1; x >= 0 ; --x ) 
       
  1020 	    {
       
  1021 	    CDiagResultsDbTestRecord* record = (*aArray)[x];
       
  1022 	    
       
  1023 	    //Assumes that there is only MAX one specific UID in the test record.        
       
  1024 	    for ( TInt y = 0; y < record->Count(); ++y )
       
  1025 	        {
       
  1026 	        CDiagResultsDatabaseItem* item = record->GetItem( y );
       
  1027 	                 
       
  1028              //	 Search for a test result that is not skipped / cancelled.                 
       
  1029 	         if (  item->TestUid() == aUid && 
       
  1030 	              (item->TestResult() == CDiagResultsDatabaseItem::ESuccess ||
       
  1031 	               item->TestResult() == CDiagResultsDatabaseItem::EFailed ))
       
  1032 	            {
       
  1033 	            //Remove the found item to speed up look up times.
       
  1034 	            //This does not remove it from the DB file.
       
  1035 	            record->RemoveL( y ); 
       
  1036 	            return item;
       
  1037 	            }
       
  1038 	        }     
       
  1039 	    }
       
  1040 	     
       
  1041 	return NULL;  
       
  1042     }