photosgallery/logging/client/src/glxlogchunk.cpp
changeset 0 4e91876724a2
child 18 bcb43dc84c44
equal deleted inserted replaced
-1:000000000000 0:4e91876724a2
       
     1 /*
       
     2 * Copyright (c) 2008-2009 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:    Logging to chunk wrappe for MC Photos
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 // CLASS HEADER
       
    22 #include "glxlogchunk.h"
       
    23 
       
    24 // EXTERNAL INCLUDES
       
    25 #include <e32svr.h>
       
    26 
       
    27 // LOCAL DECLARATIONS
       
    28 namespace
       
    29 	{
       
    30 	// size for the chunks
       
    31 	const TInt KLogChunkSize = 1000000; // 1 million bytes
       
    32 	// name for chunk 1
       
    33 	_LIT( KLogChunk1Name, "MC_Photos_Logchunk1" );
       
    34 	// name for chunk 2
       
    35 	_LIT( KLogChunk2Name, "MC_Photos_Logchunk2" );
       
    36 	// extension for log file
       
    37 	_LIT( KLogFileExtension, ".log" );
       
    38 	// carriage return / line feed
       
    39 	_LIT8( KLogCR, "\r" );
       
    40 	_LIT8( KLogLF, "\n" );
       
    41 	// constant for machine word alignment
       
    42 	const TInt KBytesInAWord = sizeof( TInt32 );
       
    43 	}
       
    44 	
       
    45 inline void Panic(TInt aReason)
       
    46     {
       
    47 	_LIT(applicationName,"Glx Logging");
       
    48     User::Panic(applicationName, aReason);
       
    49     }
       
    50 
       
    51 // -----------------------------------------------------------------------------
       
    52 // RGlxLogUtility::Open
       
    53 // -----------------------------------------------------------------------------
       
    54 TInt RGlxLogUtility::Open( const TDesC& aName, TBool aReadOnly )
       
    55 	{
       
    56 	// open the chunk
       
    57 	return iChunk.OpenGlobal( aName, aReadOnly );
       
    58 	}
       
    59 
       
    60 // -----------------------------------------------------------------------------
       
    61 // RGlxLogUtility::CreateL
       
    62 // -----------------------------------------------------------------------------
       
    63 void RGlxLogUtility::CreateL( const TDesC& aName )
       
    64     {
       
    65 	// create the chunk, leave if error
       
    66 	TInt error = iChunk.CreateGlobal( aName, KLogChunkSize, KLogChunkSize  );
       
    67 	// dont treate already exists as an error
       
    68 	if( KErrAlreadyExists == error )
       
    69 		{
       
    70 		// open in read-write
       
    71 		User::LeaveIfError( iChunk.OpenGlobal( aName, EFalse ) );
       
    72 		}
       
    73 	else
       
    74 		{
       
    75 		User::LeaveIfError( error );
       
    76 		}
       
    77 
       
    78     // initialise the iChunk to all zeros.
       
    79     Mem::FillZ( iChunk.Base(), iChunk.Size() );
       
    80     // initialise current address to base
       
    81     SetCurrentAddress( BaseAddress() );
       
    82     // initialise last logged address to base
       
    83     SetLastLoggedAddress( BaseAddress() );
       
    84     }
       
    85 
       
    86 // -----------------------------------------------------------------------------
       
    87 // RGlxLogUtility::Close
       
    88 // -----------------------------------------------------------------------------
       
    89 void RGlxLogUtility::Close()
       
    90 	{
       
    91 	iChunk.Close();
       
    92 	}
       
    93 
       
    94 // -----------------------------------------------------------------------------
       
    95 // RGlxLogUtility::ChunkSize
       
    96 // -----------------------------------------------------------------------------
       
    97 TInt RGlxLogUtility::ChunkSize()
       
    98 	{
       
    99 	return iChunk.Size();
       
   100 	}
       
   101     
       
   102 // -----------------------------------------------------------------------------
       
   103 // RGlxLogUtility::Id
       
   104 // -----------------------------------------------------------------------------
       
   105 TObjectId RGlxLogUtility::Id()
       
   106 	{
       
   107 	// take chunk base address
       
   108 	TUint8* ptr_in_chunk = iChunk.Base();
       
   109 	// cast that to TObjectId*
       
   110 	TObjectId* ptr_as_tobjectid = reinterpret_cast< TObjectId* >( ptr_in_chunk );
       
   111 	// return the id
       
   112 	return *ptr_as_tobjectid;
       
   113 	}
       
   114 
       
   115 // -----------------------------------------------------------------------------
       
   116 // RGlxLogUtility::SetId
       
   117 // -----------------------------------------------------------------------------
       
   118 void RGlxLogUtility::SetId( TObjectId aId )
       
   119 	{
       
   120 	// take chunk base address
       
   121 	TUint8* ptr_in_chunk = iChunk.Base();
       
   122 	// cast that to TObjectId*
       
   123 	TObjectId* ptr_as_tobjectid = reinterpret_cast< TObjectId* >( ptr_in_chunk );
       
   124 	// assign the id in place
       
   125 	*ptr_as_tobjectid = aId;
       
   126 	}
       
   127 
       
   128 // -----------------------------------------------------------------------------
       
   129 // RGlxLogUtility::CurrentAddress
       
   130 // -----------------------------------------------------------------------------
       
   131 TUint8* RGlxLogUtility::CurrentAddress()
       
   132 	{
       
   133 	// take chunk base address plus object id
       
   134 	TUint8* ptr_in_chunk = iChunk.Base() + sizeof( TObjectId );
       
   135 	// cast that to TInt*
       
   136 	TUint32* ptr_as_tint = reinterpret_cast< TUint32* >( ptr_in_chunk );
       
   137 	// dereference that pointer to read the 32 bits that are the address
       
   138 	TUint32 value_of_pointer = *ptr_as_tint;
       
   139 	// then return the value as TUint8*
       
   140 	return reinterpret_cast< TUint8* >( value_of_pointer );
       
   141 	}
       
   142 
       
   143 // -----------------------------------------------------------------------------
       
   144 // RGlxLogUtility::SetCurrentAddress
       
   145 // -----------------------------------------------------------------------------
       
   146 void RGlxLogUtility::SetCurrentAddress( TUint8* aValue )
       
   147 	{
       
   148 	// take chunk base address plus object id
       
   149 	TUint8* ptr_in_chunk = iChunk.Base() + sizeof( TObjectId );
       
   150 	// cast that to TInt*
       
   151 	TUint32* ptr_as_tint = reinterpret_cast< TUint32* >( ptr_in_chunk );
       
   152 	// assign the addres to TInt
       
   153 	TUint32 new_value = reinterpret_cast< TUint32 >( aValue );
       
   154 	// ensure we're byte aligned - ARM requires 32 bit alignment to machine word
       
   155 	// boundary!!
       
   156 	TInt remainder = new_value % KBytesInAWord;
       
   157 	if ( remainder > 0 )
       
   158 	    {
       
   159 	    new_value += ( KBytesInAWord - remainder );
       
   160 	    }
       
   161 	// set the new value to the chunk
       
   162 	*ptr_as_tint = new_value;
       
   163 	}
       
   164 
       
   165 // -----------------------------------------------------------------------------
       
   166 // RGlxLogUtility::LastLoggedAddress
       
   167 // -----------------------------------------------------------------------------
       
   168 TUint8* RGlxLogUtility::LastLoggedAddress()
       
   169 	{
       
   170 	// take chunk base address plus object id plus one pointer
       
   171 	TUint8* ptr_in_chunk = 
       
   172 		iChunk.Base() + sizeof( TObjectId ) + sizeof( TUint8* );
       
   173 	// cast that to TInt*
       
   174 	TUint32* ptr_as_tint = reinterpret_cast< TUint32* >( ptr_in_chunk );
       
   175 	// dereference that pointer to read the 32 bits that are the address
       
   176 	TUint32 value_of_pointer = *ptr_as_tint;
       
   177 	// then return the value as TUint8*
       
   178 	return reinterpret_cast< TUint8* >( value_of_pointer );
       
   179 	}
       
   180 
       
   181 // -----------------------------------------------------------------------------
       
   182 // RGlxLogUtility::SetLastLoggedAddress
       
   183 // -----------------------------------------------------------------------------
       
   184 void RGlxLogUtility::SetLastLoggedAddress( TUint8* aValue )
       
   185 	{
       
   186 	// take chunk base address plus object id plus one pointer
       
   187 	TUint8* ptr_in_chunk = 
       
   188 		iChunk.Base() + sizeof( TObjectId ) + sizeof( TUint8* );
       
   189 	// cast that to TInt*
       
   190 	TUint32* ptr_as_tint = reinterpret_cast< TUint32* >( ptr_in_chunk );
       
   191 	// assign the addres to TInt
       
   192 	TUint32 new_value = reinterpret_cast< TUint32 >( aValue );
       
   193 	// ensure we're byte aligned - ARM requires 32 bit alignment to machine word
       
   194 	// boundary!!
       
   195     TInt remainder = new_value % KBytesInAWord;
       
   196 	if ( remainder > 0 )
       
   197 	    {
       
   198 	    new_value += ( KBytesInAWord - remainder );
       
   199 	    }	
       
   200 	// set the new value to the chunk
       
   201 	*ptr_as_tint = new_value;
       
   202 	}
       
   203 
       
   204 // -----------------------------------------------------------------------------
       
   205 // RGlxLogUtility::BaseAddress
       
   206 // -----------------------------------------------------------------------------
       
   207 TUint8* RGlxLogUtility::BaseAddress()
       
   208 	{
       
   209 	// take chunks base address
       
   210 	TUint8* base = iChunk.Base();
       
   211 	// calculate the topmost write address, our header is 
       
   212 	// TObjectId and two TUint8*
       
   213 	return base + sizeof( TObjectId ) + sizeof( TUint8* ) * 2;
       
   214 	}
       
   215 
       
   216 // -----------------------------------------------------------------------------
       
   217 // RGlxLogUtility::LastAddress
       
   218 // -----------------------------------------------------------------------------
       
   219 TUint8* RGlxLogUtility::LastAddress()
       
   220 	{
       
   221 	// return chunks base address plus its size
       
   222 	return iChunk.Base() + iChunk.Size();
       
   223 	}
       
   224 
       
   225 // -----------------------------------------------------------------------------
       
   226 // RGlxLogClient::Open
       
   227 // -----------------------------------------------------------------------------
       
   228 EXPORT_C TInt RGlxLogClient::Open( TObjectId aId )
       
   229     {
       
   230     // try to open first log chunk, in read-write mode
       
   231     TInt err = iLogUtility.Open( KLogChunk1Name(), EFalse );
       
   232     if ( err != KErrNone )
       
   233         {
       
   234         return err;
       
   235         }
       
   236     // check id
       
   237     TObjectId id = iLogUtility.Id();
       
   238     if ( id  == TObjectId( 0 ) )
       
   239         {
       
   240         // no id set, so reserve this for us and use this chunk
       
   241         iLogUtility.SetId( aId );
       
   242         }
       
   243     // check if our id was there?
       
   244     else if( id != aId )
       
   245         {
       
   246         // not our chunk, try second chunk in read-write mode
       
   247         err = iLogUtility.Open( KLogChunk2Name(), EFalse );
       
   248         if ( err != KErrNone )
       
   249             {
       
   250             return err;
       
   251             }
       
   252         // check id
       
   253         id = iLogUtility.Id();
       
   254         if ( id  == TObjectId( 0 ) )
       
   255             {
       
   256             // no id, reserve this for us and use this chunk
       
   257             iLogUtility.SetId( aId );
       
   258             }
       
   259         else if ( id != aId )
       
   260             {
       
   261             // both chunks already reserved, return error
       
   262             return KErrNotFound;
       
   263             }
       
   264        	}
       
   265     return KErrNone;
       
   266     }
       
   267 
       
   268 // -----------------------------------------------------------------------------
       
   269 // RGlxLogClient::Close
       
   270 // -----------------------------------------------------------------------------
       
   271 EXPORT_C void RGlxLogClient::Close()
       
   272 	{
       
   273     iLogUtility.Close();
       
   274 	}
       
   275 
       
   276 // -----------------------------------------------------------------------------
       
   277 // RGlxLogClient::Write
       
   278 // -----------------------------------------------------------------------------
       
   279 EXPORT_C void RGlxLogClient::Write( const TDesC8& aLogEntry )
       
   280     {
       
   281     // get the size of log entry (in bytes)
       
   282     TInt num_bytes = aLogEntry.Size();
       
   283     // take current address and chunk size to ensure log entry fits
       
   284     TUint8* current_address = iLogUtility.CurrentAddress();
       
   285     // calculate the new current address, we write the size and the data
       
   286     TUint8* after_write = current_address + num_bytes + sizeof( TInt );
       
   287     // chck that we fit
       
   288     if( after_write >= iLogUtility.LastAddress() )
       
   289     	{
       
   290     	// we dont fit in the end
       
   291     	// need to mark the old current_address so that
       
   292     	// manager knows we jumped to the start
       
   293 	    TInt* last_indicator_ptr = 
       
   294 	    	reinterpret_cast< TInt* >( current_address );
       
   295 	   	// assign KErrNotFound there
       
   296 		*last_indicator_ptr = KErrNotFound;
       
   297     	// write this entry to the base address
       
   298     	current_address = iLogUtility.BaseAddress();
       
   299     	}
       
   300     // we need to store the size in the chunk first so take a TInt*
       
   301     TInt* size_ptr = reinterpret_cast< TInt* >( current_address );
       
   302     // assign new value in place
       
   303     *size_ptr = num_bytes;
       
   304     // increase address
       
   305     current_address += sizeof( TInt );
       
   306     // copy the data, first target, then source and last number of bytes
       
   307     Mem::Copy( current_address, aLogEntry.Ptr(), num_bytes );
       
   308     // and set the new current address
       
   309     iLogUtility.SetCurrentAddress( current_address + num_bytes );
       
   310     }
       
   311 
       
   312 // -----------------------------------------------------------------------------
       
   313 // RGlxLogManager::CreateL
       
   314 // -----------------------------------------------------------------------------
       
   315 EXPORT_C void RGlxLogManager::CreateL()
       
   316     {
       
   317     // connect to the file server
       
   318     User::LeaveIfError( iFs.Connect() );
       
   319     
       
   320     // create two log chunks
       
   321     iLogUtility1.CreateL( KLogChunk1Name );
       
   322     iLogUtility2.CreateL( KLogChunk2Name );
       
   323     }
       
   324 
       
   325 // -----------------------------------------------------------------------------
       
   326 // RGlxLogManager::Release
       
   327 // -----------------------------------------------------------------------------
       
   328 EXPORT_C void RGlxLogManager::Release()
       
   329     {
       
   330     // close file server handle
       
   331     iFs.Close();
       
   332     
       
   333     // release both log chunks
       
   334     iLogUtility1.Close();
       
   335     iLogUtility2.Close();
       
   336     }
       
   337 
       
   338 // -----------------------------------------------------------------------------
       
   339 // RGlxLogManager::CommitToFileL
       
   340 // -----------------------------------------------------------------------------
       
   341 EXPORT_C void RGlxLogManager::CommitToFileL( const TDesC& aFolder )
       
   342 	{
       
   343 	// open the file
       
   344 	RFile file;
       
   345 	CleanupClosePushL( file );
       
   346 	
       
   347 	// chunk1
       
   348 	// create the file name
       
   349 	TFileName fileName;
       
   350 	fileName = aFolder;
       
   351 	fileName.Append( KLogChunk1Name );
       
   352 	fileName.Append( KLogFileExtension );
       
   353 	// try to open the file	
       
   354 	TInt err = file.Open( iFs, fileName, EFileWrite );
       
   355 	if ( err == KErrNotFound )
       
   356 	    {
       
   357 	    // file doesn't exist so create it
       
   358 	    err = file.Create( iFs, fileName, EFileWrite );
       
   359 	    }
       
   360 	User::LeaveIfError( err );
       
   361 	// write the first chunk to file
       
   362 	CommitToFileL( iLogUtility1, file );
       
   363 	// close the file
       
   364 	file.Close();
       
   365 	
       
   366 	// chunk2
       
   367 	// reset the file name
       
   368 	fileName.Zero();
       
   369 	// create the file name
       
   370 	fileName = aFolder;
       
   371 	fileName.Append( KLogChunk2Name );
       
   372 	fileName.Append( KLogFileExtension );
       
   373 	// try to open the file
       
   374 	err = file.Open( iFs, fileName, EFileWrite );
       
   375 	if ( err == KErrNotFound )
       
   376 	    {
       
   377 	    // file doesn't exist so create it
       
   378 	    err = file.Create( iFs, fileName, EFileWrite );
       
   379 	    }
       
   380 	User::LeaveIfError( err );
       
   381 	// write the second chunk to file
       
   382 	CommitToFileL( iLogUtility2, file );
       
   383 
       
   384 	CleanupStack::PopAndDestroy( &file );
       
   385 	}
       
   386 
       
   387 // -----------------------------------------------------------------------------
       
   388 // RGlxLogManager::CommitToFileL
       
   389 // -----------------------------------------------------------------------------    
       
   390 void RGlxLogManager::CommitToFileL( RGlxLogUtility& aUtility, RFile& aFile )
       
   391     {
       
   392     // Need to explicitly move to the end of the file as it's not done
       
   393     // automatically on call to Write
       
   394     TInt pos = 0;
       
   395     TInt err = aFile.Seek( ESeekEnd, pos );
       
   396     User::LeaveIfError( err );
       
   397     TPtr8 logEntryPtr( 0, 0 );
       
   398     TInt logEntrySize = 0;
       
   399     
       
   400     // what's previously been logged to the file?
       
   401     TUint8* lastLoggedAddress = aUtility.LastLoggedAddress();
       
   402     
       
   403     // how much more has been added to the chunk?
       
   404     TUint8* currentAddress = aUtility.CurrentAddress();
       
   405     
       
   406     // write each of the chunk's logged entries to the file 
       
   407     TInt32* sizePtr = NULL;
       
   408     while ( currentAddress != lastLoggedAddress && err == KErrNone )
       
   409         {
       
   410         // get the logEntry's size
       
   411         sizePtr = reinterpret_cast< TInt32* >( lastLoggedAddress );
       
   412         logEntrySize = *sizePtr;
       
   413         if ( logEntrySize == KErrNotFound )
       
   414             {
       
   415             // logged entries have wrapped around the end of the chunk
       
   416             // so start from the beginning
       
   417             lastLoggedAddress = aUtility.BaseAddress();
       
   418             sizePtr = reinterpret_cast< TInt32* >( lastLoggedAddress );
       
   419             logEntrySize = *sizePtr;
       
   420             }
       
   421         // set an error - this will be reset to KErrNone if we succeed
       
   422         // with finding and writing a log entry
       
   423         err = KErrNotFound;
       
   424         if ( logEntrySize > 0 )
       
   425             {
       
   426             // move the current address to the data
       
   427             lastLoggedAddress += sizeof( TInt32 );
       
   428             // extract the log entry's data 
       
   429             logEntryPtr.Set( lastLoggedAddress, logEntrySize, logEntrySize );
       
   430             // write the log entry to the file
       
   431             err = aFile.Write( logEntryPtr );
       
   432             // append carriage return and line feed to the entry
       
   433             err = aFile.Write( KLogCR );
       
   434             err = aFile.Write( KLogLF );
       
   435             // ensure we align to a multiple of a 4-byte boundary
       
   436             TInt remainder = logEntrySize % KBytesInAWord;
       
   437             if ( remainder > 0 )
       
   438                 {
       
   439                 // not aligned so add some padding
       
   440                 logEntrySize += ( KBytesInAWord - remainder );
       
   441                 }
       
   442  
       
   443             // update the last logged address
       
   444             lastLoggedAddress += logEntrySize;
       
   445             }
       
   446         }
       
   447     // update the last logged address
       
   448     aUtility.SetLastLoggedAddress( lastLoggedAddress );
       
   449 	// 
       
   450 	// commit the data
       
   451 	err = aFile.Flush();
       
   452 	User::LeaveIfError( err );
       
   453     }