camerauis/cameraapp/generic/src/CamPerformanceLogger.cpp
branchRCL_3
changeset 54 bac7acad7cb3
parent 0 1ddebce53859
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/camerauis/cameraapp/generic/src/CamPerformanceLogger.cpp	Wed Sep 01 12:30:54 2010 +0100
@@ -0,0 +1,477 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Class for managing intercommunication between Camera UI*
+*/
+
+
+// INCLUDE FILES
+
+#include <e32std.h>
+#include <e32base.h> // TTime
+#include <eikenv.h>
+#include <s32file.h> // RFileWriteStream
+
+#include "CamPerformance.h"
+#include "CamAppUid.h" // KCameraappUID
+
+#ifdef CAMERAAPP_PERF_LOG_MEMORY
+// This file needs only be compiled if logging to memory is enabled
+
+// INTERNAL CONSTANTS, ENUMS AND STRUCTS
+
+// Constants related to logging in memory
+const TInt KPerfLogArrayGranularity = 20;
+const TInt KPerfMaxLogItemStringLength = 160;
+
+// Constants for converting 64-bit system time to milliseconds
+// and seconds
+const TInt KDividerSystemToMilliseconds = 1000;
+const TInt KDividerMillisecondsToSeconds = 1000;
+
+// Constants for formatting memory log to text
+_LIT( KPerfLogItemTab, "\t" );
+_LIT8( KPerfLogItemCrLf8, "\n" );
+_LIT( KPerfLogItemSecondsFormatSpace, "%6d.%03d" );
+_LIT( KPerfLogItemSecondsFormat, "%d.%03d" );
+
+// Constants for writing event analysis log
+_LIT( KAnalysisEventType, "Event: %d" );
+_LIT( KAnalysisEventStartTime, ", start time: " );
+_LIT( KAnalysisEventEndTime, ", end time: " );
+_LIT( KAnalysisEventDuration, ", duration: " );
+_LIT( KAnalysisEventAlreadyStarted, "Start for event %d, which has already been started, time: " );
+_LIT( KAnalysisEndWithoutStart, "End for event %d without start, time: " );
+_LIT( KAnalysisStartWithoutEnd, "Start for event %d without end, time: " );
+
+_LIT( KCamPerformanceLogger, "CamPerformanceLogger" );
+
+/**
+* Memory log item types
+*/
+enum TItemType
+	{
+	EItemEventStart,
+	EItemEventEnd,
+	EItemMessage,
+	EItemEngineStateChange,
+	EItemOperationStateChange
+	};
+
+/**
+* TLogitem struct definition. Used for storing log items in memory
+* in an array.
+*/
+struct TLogItem
+	{	
+	public:	
+	TLogItem( TItemType aItemType, TInt aIntValue, 	TInt64 aTime ):
+		iItemType( aItemType ), iIntValue( aIntValue), iTime( aTime ) {}
+		
+	TItemType iItemType;
+	TInt iIntValue;
+	TInt64 iTime;
+	};	
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CCamPerformanceLogger::CCamPerformanceLogger
+// C++ default constructor can NOT contain any code, that
+// might leave
+// -----------------------------------------------------------------------------
+//
+CCamPerformanceLogger::CCamPerformanceLogger() :
+	CCoeStatic( TUid::Uid( KCameraappUID ) ), iLogItems( KPerfLogArrayGranularity )
+	{	
+	iStartTime = Time64();
+	}
+	
+// -----------------------------------------------------------------------------
+// CCamPerformanceLogger::~CCamPerformanceLogger
+// Destructor
+// -----------------------------------------------------------------------------
+//	
+CCamPerformanceLogger::~CCamPerformanceLogger()
+	{
+  PRINT( _L("Camera => ~CCamPerformanceLogger") );
+	if( iLogItems.Count() > 0 )
+		{
+		// Write files only if there are new log items
+		// This is to avoid overwriting log already written using SaveAndReset()	
+		TRAP_IGNORE( SaveLogDataL() );
+		TRAP_IGNORE( SaveAnalysisL() );
+		}
+	iLogItems.Close();	
+  PRINT( _L("Camera <= ~CCamPerformanceLogger") );
+	}
+
+// ---------------------------------------------------------------------------
+// CCamPerformanceLogger::Logger
+// Static function, which returns a pointer to the currently active 
+// CCamPerformanceLogger object or instantiates a new one
+// ---------------------------------------------------------------------------
+//	
+CCamPerformanceLogger* CCamPerformanceLogger::Logger()
+	{	
+	// Get pointer to the current CCamPerformanceLogger object using CCoeEnv.FindStatic()	
+	CCamPerformanceLogger* self = static_cast<CCamPerformanceLogger*>( CCoeEnv::Static()->FindStatic( TUid::Uid( KCameraappUID ) ) );
+	if( self )
+		{
+		return self;
+		}
+	else
+		{
+		// FindStatic returned null, create a new instance
+		self = new CCamPerformanceLogger();
+		if( !self )
+			{
+			// Not enough memory to instantiate CCamPerfomranceLogger
+			User::Panic( KCamPerformanceLogger, KErrNoMemory );			
+			}
+		return self;
+		}
+	}
+
+// ---------------------------------------------------------------------------
+// CCamPerformanceLogger::SaveAndReset
+// Static function, which saves the recoded log data and clears the log
+// ---------------------------------------------------------------------------
+//	
+void CCamPerformanceLogger::SaveAndReset()
+	{
+	// Get pointer to the current CCamPerformanceLogger object using CCoeEnv.FindStatic()	
+	CCamPerformanceLogger* self = static_cast<CCamPerformanceLogger*>( CCoeEnv::Static()->FindStatic( TUid::Uid( KCameraappUID ) ) );
+	
+	if( self && self->iLogItems.Count() > 0 )
+		{
+		TRAP_IGNORE( self->SaveLogDataL() );
+		TRAP_IGNORE( self->SaveAnalysisL() );
+		
+		// Clear the logitems array
+		self->iLogItems.Reset();
+		}		
+	}
+
+// ---------------------------------------------------------------------------
+// CCamPerformanceLogger::EventStart
+// Appends an event start item to the memory log
+// ---------------------------------------------------------------------------
+//		
+void CCamPerformanceLogger::EventStart( TCamEvent aEvent )
+	{
+	TLogItem item( EItemEventStart, aEvent, Time64() - iStartTime );
+	iLogItems.Append( item ); // Ignore return value
+	}
+
+// ---------------------------------------------------------------------------
+// CCamPerformanceLogger::EventEnd
+// Appends an event end item to the memory log
+// ---------------------------------------------------------------------------
+//		
+void CCamPerformanceLogger::EventEnd( TCamEvent aEvent )
+	{
+	TLogItem item( EItemEventEnd, aEvent, Time64() - iStartTime );
+	iLogItems.Append( item );	// Ignore return value
+	}
+
+// ---------------------------------------------------------------------------
+// CCamPerformanceLogger::Message
+// Appends a message to the memory log
+// ---------------------------------------------------------------------------
+//		
+void CCamPerformanceLogger::Message( TCamMessage aMessage )
+	{
+	TLogItem item( EItemMessage, aMessage, Time64() - iStartTime );
+	iLogItems.Append( item );	// Ignore return value
+	}
+
+// ---------------------------------------------------------------------------
+// CCamPerformanceLogger::EngineState
+// Appends an engine state change to the memory log
+// ---------------------------------------------------------------------------
+//	
+void CCamPerformanceLogger::EngineState( TInt aState )
+	{
+	TLogItem item( EItemEngineStateChange, aState, Time64() - iStartTime );
+	iLogItems.Append( item );	// Ignore return value
+	}
+	
+// ---------------------------------------------------------------------------
+// CCamPerformanceLogger::OperationState
+// Appends an operation state change to the memory log
+// ---------------------------------------------------------------------------
+//	
+void CCamPerformanceLogger::OperationState( TInt aState )
+	{
+	TLogItem item( EItemOperationStateChange, aState, Time64() - iStartTime );
+	iLogItems.Append( item );	// Ignore return value
+	}	
+
+// ---------------------------------------------------------------------------
+// CCamPerformanceLogger::LogItemToDes
+// Converts log item data into LogicAnalyzer compatible string, and stores 
+// it in aDes
+// ---------------------------------------------------------------------------
+//		
+void CCamPerformanceLogger::LogItemToDes( const TLogItem& aItem, TDes& aDes )
+	{
+	// Clear the descriptor contents
+	aDes.Zero();
+	
+	// Append time of the log item and space
+	TInt64 time = aItem.iTime;
+	AppendTime( aDes, time, ETrue );
+	aDes.Append( KPerfLogItemTab );
+		
+	// Append item type specific formatted string
+	switch( aItem.iItemType ) 
+		{
+		case EItemEventStart:
+			{
+			aDes.AppendFormat( KPerfEventStart, aItem.iIntValue );
+			}
+			break;
+		case EItemEventEnd:
+			{
+			aDes.AppendFormat( KPerfEventEnd, aItem.iIntValue );	
+			}	
+			break;
+		case EItemMessage:
+			{
+			aDes.AppendFormat( KPerfMessage, aItem.iIntValue );	
+			}
+			break;
+		case EItemEngineStateChange:
+			{
+			aDes.AppendFormat( KPerfEngineStateChange, aItem.iIntValue );	
+			}
+			break;
+		case EItemOperationStateChange:
+			{
+			aDes.AppendFormat( KPerfOperationStateChange, aItem.iIntValue );	
+			}
+			break;			
+		default:
+			{
+			aDes.AppendFormat( KPerfUnknown, aItem.iIntValue );	
+			}
+			break;
+		}	
+	}
+
+
+// ---------------------------------------------------------------------------
+// CCamPerformanceLogger::AppendTime
+// Appends time represendted by aTime to aDes with format seconds.milliseconds
+// ---------------------------------------------------------------------------
+//	
+void CCamPerformanceLogger::AppendTime( TDes& aDes, TInt64 aTime, TBool aSpace )
+	{
+	// Convert system time to milliseconds
+	TInt64 timeInMillis = aTime / KDividerSystemToMilliseconds;
+	
+	// Get seconds and remainder (milliseconds)
+	TInt seconds = timeInMillis / KDividerMillisecondsToSeconds;
+	TInt milliseconds = timeInMillis % KDividerMillisecondsToSeconds;
+	
+	// Append seconds to the log item, with or without trailing space
+	if( aSpace )
+		{
+		aDes.AppendFormat( KPerfLogItemSecondsFormatSpace, seconds, milliseconds );
+		}
+	else
+		{
+		aDes.AppendFormat( KPerfLogItemSecondsFormat, seconds, milliseconds );
+		}
+	}
+
+// ---------------------------------------------------------------------------
+// CCamPerformanceLogger::SaveLogDataL
+// Saves all data from memory log to file KPerfLogFilename
+// ---------------------------------------------------------------------------
+//
+void CCamPerformanceLogger::SaveLogDataL() const
+	{ 	
+	TBuf<KPerfMaxLogItemStringLength> itemDes;	
+	
+	// Connect to file server and create the output stream	
+	RFs fs;
+	User::LeaveIfError( fs.Connect() );
+	CleanupClosePushL( fs );
+	
+	RFileWriteStream writeStream;
+	User::LeaveIfError( writeStream.Replace( fs, KPerfLogFilename, EFileWrite ) );
+	writeStream.PushL();
+	
+	// Convert each item to Des8 and write to the stream
+	TInt n = iLogItems.Count();
+	for( int i=0; i<n; i++ )
+		{
+		const TLogItem& item = iLogItems[i];
+		LogItemToDes( item, itemDes );
+		WriteLineL( writeStream, itemDes );
+		}	
+	
+	// Commit and release the stream		
+	writeStream.CommitL();
+	writeStream.Pop();
+	writeStream.Release();	
+			
+	CleanupStack::PopAndDestroy(); // fs
+	}
+
+// ---------------------------------------------------------------------------
+// CCamPerformanceLogger::SaveAnalysisL
+// Performs simple analysis to event data from memory log and writes the
+// result to file KPerfAnalysisFilenam
+// ---------------------------------------------------------------------------
+//	
+void CCamPerformanceLogger::SaveAnalysisL() const
+	{ 	
+	#ifdef CAMERAAPP_PERF_LOG_ANALYZE_EVENTS
+		
+	TBuf<KPerfMaxLogItemStringLength> itemDes;	
+
+	TBool eventStatus[ EPerfEventLastEvent ];
+	TInt64 startTimes[ EPerfEventLastEvent ];
+	
+	for( int i=0; i<EPerfEventLastEvent; i++)
+		{
+		eventStatus[i] = EFalse;
+		}
+		
+	// Connect to file server and create the output stream	
+	RFs fs;
+	User::LeaveIfError( fs.Connect() );
+	CleanupClosePushL( fs );
+	
+	RFileWriteStream writeStream;
+	User::LeaveIfError( writeStream.Replace( fs, KPerfAnalysisFileName, EFileWrite ) );
+	writeStream.PushL();	
+	
+	TInt n = iLogItems.Count();
+	
+	// Go through each item in the memory log
+	for( TInt i=0; i<n; i++ )
+	{
+		const TLogItem& item = iLogItems[i];
+		
+		TInt intValue = item.iIntValue;
+		TInt64 time = item.iTime;
+		TBool status = eventStatus[ intValue ];
+				
+		if( EItemEventStart == item.iItemType )
+			{
+			if( !status )
+				{
+				// Start for an event that has not yet been start
+				eventStatus[ intValue ] = ETrue;
+				startTimes[ intValue ] = time;
+				}
+			else
+				{
+				// Start for an event that has already been started
+				// Replace old start time with the new one
+				startTimes[ intValue ] = time;
+				#ifdef CAMERAAPP_PERF_ANALYSIS_WARN_MULTIPLE_START				
+				itemDes.Format( KAnalysisEventAlreadyStarted, intValue );
+				AppendTime( itemDes, time );
+				WriteLineL( writeStream, itemDes );
+				#endif	
+				}
+			}	
+		else if( EItemEventEnd == item.iItemType )
+			{
+			if( status )	
+				{
+				// End for an event that has been started
+				itemDes.Format( KAnalysisEventType, intValue );
+				itemDes.Append( KAnalysisEventStartTime );
+				AppendTime( itemDes, startTimes[ intValue ] );
+				itemDes.Append( KAnalysisEventEndTime );
+				AppendTime( itemDes, time );
+				itemDes.Append( KAnalysisEventDuration );
+				AppendTime( itemDes, time - startTimes[ intValue ] );
+				WriteLineL( writeStream, itemDes );
+					
+				eventStatus[ intValue ] = EFalse;
+				}
+			else
+				{	
+				// End for an event that has not been started
+				#ifdef CAMERAAPP_PERF_ANALYSIS_WARN_END_WITHOUT_START
+					itemDes.Format( KAnalysisEndWithoutStart, intValue );
+					AppendTime( itemDes, time );
+					WriteLineL( writeStream, itemDes );
+				#endif
+				}				
+			}
+		else
+			{
+			// Ignore other event types
+			}	
+	}
+	
+	#ifdef CAMERAAPP_PERF_ANALYSIS_WARN_START_WITHOUT_END
+	for( int i=0; i<EPerfEventLastEvent; i++ )
+		{
+		if( eventStatus[ i ] )
+			{
+			itemDes.Format( KAnalysisStartWithoutEnd, i );
+			AppendTime( itemDes, startTimes[ i ] );
+			WriteLineL( writeStream, itemDes );
+			}
+		}
+	#endif
+	
+	// Commit and release the stream		
+	writeStream.CommitL();
+	writeStream.Pop();
+	writeStream.Release();	
+			
+	CleanupStack::PopAndDestroy(); // fs
+	
+	#endif // CAMERAAPP_PERF_LOG_ANALYZE_EVENTS
+	}
+
+
+// ---------------------------------------------------------------------------
+// CCamPerformanceLogger::WriteLineL
+// Writes the contents of descriptor aDes followed by '\n' to aStream
+// ---------------------------------------------------------------------------
+//
+void CCamPerformanceLogger::WriteLineL( RFileWriteStream& aStream, TDes& aDes )
+	{
+	TBuf8<KPerfMaxLogItemStringLength> des8;
+	des8.Copy( aDes );
+	aStream.WriteL( des8 );
+	aStream.WriteL( KPerfLogItemCrLf8 );
+	}	
+
+// ---------------------------------------------------------------------------
+// CCamPerformanceLogger::Time64
+// Returns system 64-bit representation of the current time
+// ---------------------------------------------------------------------------
+//	
+TInt64 CCamPerformanceLogger::Time64()
+	{
+	TTime time;
+	time.HomeTime();
+	return time.Int64();
+	}
+
+#endif // CAMERAAPP_PERF_LOG_MEMORY
+		
+//  End of File  
+