--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/analyzetool/storageserver/server/src/atstorageserversession.cpp Thu May 13 23:59:27 2010 +0300
@@ -0,0 +1,3397 @@
+/*
+* Copyright (c) 2009 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: Definitions and constants for the class CATStorageServerSession
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <utf.h>
+#include <analyzetool/analyzetooltraceconstants.h>
+#include "atstorageserversession.h"
+#include "atstorageserver.h"
+#include "atstorageservercommon.h"
+#include "atmemoryentry.h"
+#include "atlog.h"
+#include "atdynprocessinfo.h"
+#include "atdriveinfo.h"
+
+// CONSTANTS
+
+// New file name start and end index.
+const TInt KNameIndexStart = 1;
+const TInt KNameIndexEnd = 100;
+
+// ==================== MEMBER FUNCTIONS for TAllocInfo ========================
+
+// -----------------------------------------------------------------------------
+// TAllocInfo::TAllocInfo
+// Implementation for the constructor of the class TAllocInfo
+// -----------------------------------------------------------------------------
+//
+TAllocInfo::TAllocInfo( TUint32 aMemAddress, TInt aAllocSize ) :
+ iMemAddress( aMemAddress ),
+ iAllocSize( aAllocSize )
+ {
+ }
+
+
+// ============== MEMBER FUNCTIONS for CATStorageServerSession =================
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::CATStorageServerSession
+// C++ default constructor. It Does not contain any code that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CATStorageServerSession::CATStorageServerSession( CATStorageServer& aStorageServer ) :
+ iStorageServer( aStorageServer ),
+ iError( 0 ),
+ iLeakArray( KLeakArrayGranularity ),
+ iProcessId( KNullProcessId ),
+ iLoggingOngoing( EFalse ),
+ iLogOption( KDefaultLoggingMode ),
+ iCurAllocSize( 0 ),
+ iMaxAllocs( 0 ),
+ iMaxAllocSize( 0 ),
+ iLogFile( KEmpty() ),
+ iIsUdeb( 1 )
+ {
+ LOGSTR1( "STSE CATStorageServerSession::CATStorageServerSession()" );
+
+ // Initialize iMicroSecondsAt1970
+ TTime time( KJanuaryFirst1970 );
+ iMicroSecondsAt1970 = time.Int64();
+
+ // Increment the server's session count by one (1)
+ iStorageServer.IncSessionCount();
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CATStorageServerSession::ConstructL()
+ {
+ // Intentionally left empty
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CATStorageServerSession* CATStorageServerSession::NewL( CATStorageServer& aStorageServer )
+ {
+ CATStorageServerSession* self = NewLC( aStorageServer );
+ CleanupStack::Pop( self );
+
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CATStorageServerSession* CATStorageServerSession::NewLC( CATStorageServer& aStorageServer )
+ {
+ CATStorageServerSession* self = new ( ELeave ) CATStorageServerSession( aStorageServer );
+
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::~CATStorageServerSession
+// Destructor
+// -----------------------------------------------------------------------------
+CATStorageServerSession::~CATStorageServerSession()
+ {
+ LOGSTR1( "STSE CATStorageServerSession::~CATStorageServerSession()" );
+
+ // Empty the array and delete the referenced objects
+ iLeakArray.ResetAndDestroy();
+
+ // Close the leak array
+ iLeakArray.Close();
+
+ // Close the allocation info array
+ iAllocInfoArray.Close();
+
+ // Check if process closed abnormal
+ if ( iProcessId != KNullProcessId &&
+ iLoggingOngoing && iLogOption != EATLoggingOff &&
+ iError != KErrNoMemory )
+ {
+ LogAbnormalEnd();
+ }
+
+ // Close the file and the handle to the file server
+ CloseFsAndFile();
+
+ // Remove the process with the current PID from the server's array of processes
+ TRAP_IGNORE( iStorageServer.RemoveProcessL( iProcessId ) );
+
+ // Decrement the server's session count by one (1)
+ iStorageServer.DecSessionCount();
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::ServiceL
+// This function is called by the client/server framework
+// -----------------------------------------------------------------------------
+//
+void CATStorageServerSession::ServiceL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE void CATStorageServerSession::ServiceL()" );
+
+ // If logging has been cancelled for this session, return immediately
+ if( iLogOption == EATLoggingOff )
+ {
+ aMessage.Complete( KErrCancel );
+ return;
+ }
+
+ switch ( aMessage.Function() )
+ {
+ case CATStorageServer::EProcessStarted:
+ {
+ // If logging is not ongoing, set the log option
+ if( !iLoggingOngoing )
+ {
+ // Set the operation mode
+ SetLogOption( aMessage );
+ }
+
+ switch ( iLogOption )
+ {
+ case EATLogToTrace:
+ {
+ iError = LogProcessStartTraceL( aMessage );
+ }
+ break;
+
+ case EATLogToFile:
+ {
+ iError = LogProcessStartedL( aMessage );
+ }
+ break;
+
+ default:
+ {
+ // Panic the client and set iError KErrCancel, because being
+ // here implies that an illegal log option has been given.
+ PanicClient( EAToolIllegalLogOption, aMessage );
+ iError = KErrCancel;
+ }
+ break;
+ }
+ }
+ break;
+
+
+ case CATStorageServer::EDllLoaded:
+ {
+ switch ( iLogOption )
+ {
+ case EATLogToTrace:
+ {
+ iError = LogDllLoadTraceL( aMessage );
+ }
+ break;
+
+ case EATLogToFile:
+ {
+ iError = LogDllLoadedL( aMessage );
+ }
+ break;
+
+ default:
+ {
+ // Panic the client and set iError KErrCancel, because being
+ // here implies that an illegal log option has been given.
+ PanicClient( EAToolIllegalLogOption, aMessage );
+ iError = KErrCancel;
+ }
+ break;
+ }
+ }
+ break;
+
+
+ case CATStorageServer::EDllUnloaded:
+ {
+ switch ( iLogOption )
+ {
+ case EATLogToTrace:
+ {
+ iError = LogDllUnloadTraceL( aMessage );
+ }
+ break;
+
+ case EATLogToFile:
+ {
+ iError = LogDllUnloadedL( aMessage );
+ }
+ break;
+
+ default:
+ {
+ // Panic the client and set iError KErrCancel, because being
+ // here implies that an illegal log option has been given.
+ PanicClient( EAToolIllegalLogOption, aMessage );
+ iError = KErrCancel;
+ }
+ break;
+ }
+ }
+ break;
+
+
+ case CATStorageServer::EMemoryAllocated:
+ {
+ switch ( iLogOption )
+ {
+ case EATLogToTrace:
+ {
+ iError = LogMemoryAllocTraceL( aMessage );
+ }
+ break;
+
+ case EATLogToFile:
+ {
+ iError = LogMemoryAllocatedL( aMessage );
+ }
+ break;
+
+ default:
+ {
+ // Panic the client and set iError KErrCancel, because being
+ // here implies that an illegal log option has been given.
+ PanicClient( EAToolIllegalLogOption, aMessage );
+ iError = KErrCancel;
+ }
+ break;
+ }
+ }
+ break;
+
+
+ case CATStorageServer::EMemoryFreed:
+ {
+ switch ( iLogOption )
+ {
+ case EATLogToTrace:
+ {
+ iError = LogMemoryFreedTraceL( aMessage );
+ }
+ break;
+
+ case EATLogToFile:
+ {
+ iError = LogMemoryFreedL( aMessage );
+ }
+ break;
+
+ default:
+ {
+ // Panic the client and set iError KErrCancel, because being
+ // here implies that an illegal log option has been given.
+ PanicClient( EAToolIllegalLogOption, aMessage );
+ iError = KErrCancel;
+ }
+ break;
+ }
+ }
+ break;
+
+
+ case CATStorageServer::EProcessEnded:
+ {
+ switch ( iLogOption )
+ {
+ case EATLogToTrace:
+ {
+ iError = LogProcessEndTraceL( aMessage );
+ }
+ break;
+
+ case EATLogToFile:
+ {
+ iError = LogProcessEndedL( aMessage );
+ }
+ break;
+
+ default:
+ {
+ // Panic the client and set iError KErrCancel, because being
+ // here implies that an illegal log option has been given.
+ PanicClient( EAToolIllegalLogOption, aMessage );
+ iError = KErrCancel;
+ }
+ break;
+ }
+ }
+ break;
+
+
+ case CATStorageServer::EMemoryCheck:
+ {
+ switch ( iLogOption )
+ {
+ case EATLogToTrace:
+ {
+ iError = CheckMemoryAddressTrace( aMessage );
+ }
+ break;
+
+ case EATLogToFile:
+ {
+ iError = CheckMemoryAddressL( aMessage );
+ }
+ break;
+
+ default:
+ {
+ // Panic the client and set iError KErrCancel, because being
+ // here implies that an illegal log option has been given.
+ PanicClient( EAToolIllegalLogOption, aMessage );
+ iError = KErrCancel;
+ }
+ break;
+ }
+ }
+ break;
+
+
+ case CATStorageServer::EGetProcesses:
+ {
+ iError = GetProcessesL( aMessage );
+ }
+ break;
+
+
+ case CATStorageServer::EGetDlls:
+ {
+ iError = GetDllsL( aMessage );
+ }
+ break;
+
+ case CATStorageServer::EGetLoggingMode:
+ {
+ iError = GetLoggingModeL( aMessage );
+ }
+ break;
+
+ case CATStorageServer::ESubtestStart:
+ {
+ iError = StartSubtestL( aMessage );
+ }
+ break;
+
+ case CATStorageServer::ESubtestStop:
+ {
+ iError = StopSubtestL( aMessage );
+ }
+ break;
+
+ case CATStorageServer::ESubtestStart2:
+ {
+ iError = StartSubtest2L( aMessage );
+ }
+ break;
+
+ case CATStorageServer::ESubtestStop2:
+ {
+ iError = StopSubtest2( aMessage );
+ }
+ break;
+
+ case CATStorageServer::EGetCurrentAllocs:
+ {
+ iError = GetCurrentAllocsL( aMessage );
+ }
+ break;
+
+ case CATStorageServer::EGetMaxAllocs:
+ {
+ iError = GetMaxAllocsL( aMessage );
+ }
+ break;
+
+ case CATStorageServer::ECancelLogging:
+ {
+ iError = CancelLoggingL( aMessage );
+ }
+ break;
+
+ case CATStorageServer::EGetUdeb:
+ {
+ iError = GetUdebL( aMessage );
+ }
+ break;
+
+ case CATStorageServer::EGetLoggingFile:
+ {
+ iError = GetLoggingFileL( aMessage );
+ }
+ break;
+
+ case CATStorageServer::EProcessUdeb:
+ {
+ SetUdeb( aMessage );
+ }
+ break;
+
+ case CATStorageServer::EIsMemoryAdded:
+ {
+ iError = IsMemoryAdded( aMessage );
+ LOGSTR2( "STSE > IsMemoryAdded err = %i", iError );
+ }
+ break;
+
+ default:
+ {
+ // Panic both the client and server, because being here implies
+ // that there is an internal error in the client/server.
+ PanicClient( EAToolBadRequest, aMessage );
+ StorageServerPanic( KCategoryServer, EAToolBadRequest );
+ }
+ break;
+
+ }
+
+ // Complete the message, if it has not been already cancelled.
+ if ( iError != KErrCancel )
+ {
+ // Log the error code. Only KErrNoMemory errors are logged.
+ if ( iLogOption == EATLogToFile && iError == KErrNoMemory )
+ {
+ HandleError( iError );
+ }
+ else if ( iLogOption == EATLogToTrace && iError == KErrNoMemory )
+ {
+ HandleErrorTrace( iError );
+ }
+
+ // Complete serving the message
+ aMessage.Complete( iError );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::LogProcessStartedL()
+// Opens a logging file with the requested name and then writes information
+// on process start into the file.
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::LogProcessStartedL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::LogProcessStartedL()" );
+
+ // Panic the client and return, if this method has already been called for this
+ // session object (and a logging file has been opened)
+ if ( iLoggingOngoing )
+ {
+ PanicClient( EAToolNotAllowed, aMessage );
+ return KErrCancel;
+ }
+
+ iError = KErrNone;
+
+ LOGMEM;
+
+ // READ THE FIRST ARGUMENT (descriptor)
+
+ // Length of the first argument (index 0)
+ TInt length = aMessage.GetDesLength( 0 );
+
+ LOGSTR2( "STSE length of the fileName: %i", length );
+
+ // Return if errors
+ if ( length == KErrArgument || length == KErrBadDescriptor )
+ {
+ return length;
+ }
+
+ // Construct a buffer for file name, and leave the pointer on Cleanup Stack
+ HBufC* fileName = HBufC::NewLC( length );
+ TPtr fileNamePtr( fileName->Des() );
+
+ // Read the client side's descriptor at index 0
+ iError = aMessage.Read( 0, fileNamePtr );
+
+ if ( iError != KErrNone )
+ {
+ CleanupStack::PopAndDestroy( fileName );
+ return iError;
+ }
+
+ // READ THE SECOND ARGUMENT (descriptor)
+
+ // Length of the second argument (index 1)
+ length = aMessage.GetDesLength( 1 );
+
+ LOGSTR2( "STSE length of the processName: %i", length );
+
+ // Return if errors
+ if ( length == KErrArgument || length == KErrBadDescriptor )
+ {
+ CleanupStack::PopAndDestroy( fileName );
+ return length;
+ }
+
+ HBufC8* processName = HBufC8::NewL( length );
+ TPtr8 bufPtr( processName->Des() );
+
+ // Read the client side's descriptor at index 1
+ iError = aMessage.Read( 1, bufPtr );
+
+ if ( iError != KErrNone )
+ {
+ delete processName;
+ CleanupStack::PopAndDestroy( fileName );
+ return iError;
+ }
+
+ // READ THE THIRD ARGUMENT (integer, a process ID)
+ TInt processId = aMessage.Int2();
+
+ // Open a file server session and a file. The file
+ // will be opened with the name received from the client
+ iError = OpenFsAndFile( *fileName, *processName );
+ CleanupStack::PopAndDestroy( fileName );
+ // Return without logging, if an error occured
+ if ( iError != KErrNone )
+ {
+ // Delete the local objects
+ delete processName;
+ return iError;
+ }
+
+ // Get the home time for the configuration UI
+ iTime.HomeTime();
+
+ // Add the process into the server's array of processes
+ iError = iStorageServer.AddProcessL( *processName,
+ processId,
+ this,
+ iTime.Int64() );
+
+ // Return without logging, if an error occured
+ if ( iError )
+ {
+ // Remove, if something was added regardless of the error
+ // However, we must not remove an existing process
+ if ( iError != KErrAlreadyExists )
+ {
+ iStorageServer.RemoveProcessL( processId );
+ }
+ return iError;
+ }
+
+ // Make a buffer that will be logged into the opened logging file
+ TBuf8<KProcessStartBufLength> loggingBuf;
+ loggingBuf.Format( KProcessStart, processName, processId );
+
+ delete processName;
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ // Append the current time in the 64-bit (max 16 characters) hexadecimal text
+ // format
+ loggingBuf.AppendNum( timeFrom1970, EHex );
+
+ // Append udeb/urel information to the process start
+ loggingBuf.Append( KSpace );
+ loggingBuf.AppendNum( iIsUdeb, EHex );
+
+ // Append trace version information
+ loggingBuf.Append( KSpace );
+ loggingBuf.AppendNum( KATTraceVersion, EHex );
+
+ // Append a new line
+ loggingBuf.Append( KNewLine );
+
+ // Write the buffer into the file
+ iError = iFile.Write( loggingBuf );
+
+ // Return, if an error occured
+ if ( iError )
+ {
+ iStorageServer.RemoveProcessL( processId );
+ return iError;
+ }
+
+ LOGMEM;
+
+ // Set the process ID value for this logging session
+ iProcessId = processId;
+ // Set logging session started
+ iLoggingOngoing = ETrue;
+
+ return iError;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::LogProcessStartTraceL()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::LogProcessStartTraceL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::LogProcessStartTraceL()" );
+
+ // Panic the client and return, if this method has already been called for this
+ // session object
+ if ( iLoggingOngoing )
+ {
+ PanicClient( EAToolNotAllowed, aMessage );
+ return KErrCancel;
+ }
+
+ iError = KErrNone;
+
+ LOGMEM;
+
+ // READ THE SECOND ARGUMENT (descriptor)
+ // The first argument, file name, is ignored when logging thru trace
+
+ // Length of the second argument (index 1)
+ TInt length = aMessage.GetDesLength( 1 );
+
+ LOGSTR2( "STSE length of the processName: %i", length );
+
+ // Return if errors
+ if ( length == KErrArgument || length == KErrBadDescriptor )
+ {
+ return length;
+ }
+
+ HBufC8* processName = HBufC8::NewL( length );
+ TPtr8 bufPtr( processName->Des() );
+
+ // Read the client side's descriptor at index 1
+ iError = aMessage.Read( 1, bufPtr );
+
+ if ( iError != KErrNone )
+ {
+ // Delete local objects and return
+ delete processName;
+ return iError;
+ }
+
+ // READ THE THIRD ARGUMENT (integer, a process ID)
+ TInt processId = aMessage.Int2();
+
+ // Get the home time for the configuration UI
+ iTime.HomeTime();
+
+ // Add the process into the server's array of processes
+ iError = iStorageServer.AddProcessL( *processName, processId, this,
+ iTime.Int64() );
+
+ // Return without logging, if an error occured
+ if ( iError )
+ {
+ // Remove, if something was added regardless of the error
+ // However, we must not remove an existing process
+ if ( iError != KErrAlreadyExists )
+ {
+ iStorageServer.RemoveProcessL( processId );
+ }
+ return iError;
+ }
+
+ // Make a buffer that will be logged
+ TBuf8<KProcessStartBufLength> loggingBuf;
+
+ loggingBuf.Format( KProcessStart, processName, processId );
+
+ delete processName;
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ // Append the current time in the 64-bit (max 16 characters) hexadecimal text
+ // format
+ loggingBuf.AppendNum( timeFrom1970, EHex );
+
+ // Append udeb/urel information to the process start
+ loggingBuf.Append( KSpace );
+ loggingBuf.AppendNum( iIsUdeb, EHex );
+
+ // Append version number
+ loggingBuf.Append( KSpace );
+ loggingBuf.AppendNum( KATTraceVersion, EHex );
+
+ // Append a new line
+ loggingBuf.Append( KNewLine );
+
+ // Log to trace
+ TBuf<KProcessStartBufLength> traceBuf;
+ traceBuf.Copy( loggingBuf );
+ RDebug::Print( KTraceMessage, processId ,&traceBuf );
+
+ LOGMEM;
+
+ // Set the process ID value for this logging session
+ iProcessId = processId;
+ // Set logging session started
+ iLoggingOngoing = ETrue;
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::LogDllLoadedL()
+// Logs to the file opened by the function LogProcessStartedL()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::LogDllLoadedL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::LogDllLoadedL()" );
+
+ // Panic the client and return, if a logging session is not ongoing
+ // ( can be started by calling the client's LogProcessStarted() )
+ if ( !iLoggingOngoing )
+ {
+ PanicClient( EAToolNotAllowed, aMessage );
+ return KErrCancel;
+ }
+
+ iError = KErrNone;
+
+ // Read the length of the first argument (index 0)
+ TInt length = aMessage.GetDesLength( 0 );
+
+ // Return if errors
+ if ( length == KErrArgument || length == KErrBadDescriptor )
+ {
+ return length;
+ }
+
+ HBufC8* dllName = HBufC8::NewL( length );
+ TPtr8 bufPtr( dllName->Des() );
+
+ // Read the client side's descriptor (the argument 0)
+ iError = aMessage.Read( 0, bufPtr );
+
+ if ( iError != KErrNone )
+ {
+ delete dllName;
+ return iError;
+ }
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ // Add this dll into the server's array
+ TUint32 startAddress( aMessage.Int1() );
+ TUint32 endAddress( aMessage.Int2() );
+ iError = iStorageServer.AddDllL( iProcessId,
+ TATDllInfo( startAddress, endAddress, timeFrom1970, *dllName ) );
+
+ // Return without logging, if an error occured
+ if ( iError )
+ {
+ delete dllName;
+ return iError;
+ }
+
+ // Make a buffer that will be logged into the opened logging file
+ TBuf8<KDllLoadBufLength> loggingBuf;
+ loggingBuf.Format( KDllLoad, dllName, timeFrom1970, startAddress, endAddress );
+
+ delete dllName;
+
+ // Write the buffer into a file and return the error code
+ return iFile.Write( loggingBuf );
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::LogDllLoadTraceL()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::LogDllLoadTraceL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::LogDllLoadTraceL()" );
+
+ // Panic the client and return, if a logging session is not ongoing
+ // ( can be started by calling the client's LogProcessStarted() )
+ if ( !iLoggingOngoing )
+ {
+ PanicClient( EAToolNotAllowed, aMessage );
+ return KErrCancel;
+ }
+
+ iError = KErrNone;
+
+ // Read the length of the first argument (index 0)
+ TInt length = aMessage.GetDesLength( 0 );
+
+ // Return if errors
+ if ( length == KErrArgument || length == KErrBadDescriptor )
+ {
+ return length;
+ }
+
+ HBufC8* dllName = HBufC8::NewL( length );
+ TPtr8 bufPtr( dllName->Des() );
+
+ // Read the client side's descriptor (the argument 0)
+ iError = aMessage.Read( 0, bufPtr );
+
+ if ( iError != KErrNone )
+ {
+ delete dllName;
+ return iError;
+ }
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ TUint32 startAddress( aMessage.Int1() );
+ TUint32 endAddress( aMessage.Int2() );
+
+ // Add this dll into the server's array
+ iError = iStorageServer.AddDllL( iProcessId,
+ TATDllInfo( startAddress, endAddress, timeFrom1970, *dllName ) );
+
+ // Return without logging, if an error occured
+ if ( iError )
+ {
+ delete dllName;
+ return iError;
+ }
+
+ // Make a buffer that will be logged
+ TBuf8<KDllLoadBufLength> loggingBuf;
+ loggingBuf.Format( KDllLoad, dllName, timeFrom1970, startAddress, endAddress );
+
+ delete dllName;
+
+ TBuf<KDllLoadBufLength> traceBuf;
+ traceBuf.Copy( loggingBuf );
+ RDebug::Print( KTraceMessage, iProcessId ,&traceBuf );
+ return iError;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::LogDllUnloadedL()
+// Logs to the file opened by the function LogProcessStartedL()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::LogDllUnloadedL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::LogDllUnloadedL()" );
+
+ // Panic the client and return, if a logging session is not ongoing
+ // ( can be started by calling the client's LogProcessStarted() )
+ if ( !iLoggingOngoing )
+ {
+ PanicClient( EAToolNotAllowed, aMessage );
+ return KErrCancel;
+ }
+
+ iError = KErrNone;
+
+ // Read the length of the first argument (index 0)
+ TInt length = aMessage.GetDesLength( 0 );
+
+ LOGSTR2( "STSE length %i", length );
+
+ // Return if errors
+ if ( length == KErrArgument || length == KErrBadDescriptor )
+ {
+ return length;
+ }
+
+ HBufC8* dllName = HBufC8::NewL( length );
+ TPtr8 bufPtr( dllName->Des() );
+
+ // Read the client side's descriptor (the argument 0)
+ iError = aMessage.Read( 0, bufPtr );
+
+ if ( iError != KErrNone )
+ {
+ delete dllName;
+ return iError;
+ }
+
+ TUint32 startAddress = aMessage.Int1();
+ TUint32 endAddress = aMessage.Int2();
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ // Make a buffer that will be logged into the opened logging file
+ TBuf8<KDllUnloadBufLength> loggingBuf;
+ loggingBuf.Format( KDllUnload, dllName, timeFrom1970, startAddress, endAddress );
+
+ // Remove this dll from the server's array
+ iError = iStorageServer.RemoveDllL( iProcessId, bufPtr );
+
+ delete dllName;
+
+ // Return without logging, if an error occured
+ if ( iError )
+ {
+ return iError;
+ }
+
+ // Write the buffer into a file and return the error code
+ return iFile.Write( loggingBuf );
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::LogDllUnloadTraceL()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::LogDllUnloadTraceL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::LogDllUnloadTraceL()" );
+
+ // Panic the client and return, if a logging session is not ongoing
+ // ( can be started by calling the client's LogProcessStarted() )
+ if ( !iLoggingOngoing )
+ {
+ PanicClient( EAToolNotAllowed, aMessage );
+ return KErrCancel;
+ }
+
+ iError = KErrNone;
+
+ // Read the length of the first argument (index 0)
+ TInt length = aMessage.GetDesLength( 0 );
+
+ LOGSTR2( "STSE length %i", length );
+
+ // Return if errors
+ if ( length == KErrArgument || length == KErrBadDescriptor )
+ {
+ return length;
+ }
+
+ HBufC8* dllName = HBufC8::NewL( length );
+ TPtr8 bufPtr( dllName->Des() );
+
+ // Read the client side's descriptor (the argument 0)
+ iError = aMessage.Read( 0, bufPtr );
+
+ if ( iError != KErrNone )
+ {
+ delete dllName;
+ return iError;
+ }
+
+ TUint32 startAddress = aMessage.Int1();
+ TUint32 endAddress = aMessage.Int2();
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ // Make a buffer that will be logged
+ TBuf8<KDllUnloadBufLength> loggingBuf;
+ loggingBuf.Format( KDllUnload, dllName, timeFrom1970, startAddress, endAddress );
+
+ // Remove this dll from the server's array
+ iError = iStorageServer.RemoveDllL( iProcessId, bufPtr );
+
+ delete dllName;
+
+ // Return without logging, if an error occured
+ if ( iError )
+ {
+ return iError;
+ }
+
+ TBuf<KDllLoadBufLength> traceBuf;
+ traceBuf.Copy( loggingBuf );
+ RDebug::Print( KTraceMessage, iProcessId ,&traceBuf );
+ return iError;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::LogMemoryAllocatedL()
+// Constructs a CATMemoryEntry object and appends it into iLeakArray.
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::LogMemoryAllocatedL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::LogMemoryAllocatedL()" );
+
+ // Panic the client and return, if a logging session is not ongoing
+ // ( can be started by calling the client's LogProcessStarted() )
+ if ( !iLoggingOngoing )
+ {
+ PanicClient( EAToolNotAllowed, aMessage );
+ return KErrCancel;
+ }
+
+ // A pointer to a buffer of call stack's memory addresses
+ CBufFlat* stackBuf = NULL;
+
+ iError = KErrNone;
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ // Read the first argument (index 0)
+ TUint32 memAddress = aMessage.Int0();
+ if ( memAddress == 0 )
+ {
+ return KErrNotSupported;
+ }
+
+ // Read the length of the descriptor argument (index 1) that should include
+ // call stack memory addresses associated with this memory allocation
+ TInt bufferLength = aMessage.GetDesLength( 1 );
+
+ // Construct a buffer for aCallstack
+ stackBuf = CBufFlat::NewL( bufferLength );
+ CleanupStack::PushL( stackBuf );
+
+ // Buffer position
+ TInt pos = 0;
+
+ stackBuf->ExpandL( pos, bufferLength );
+
+ TPtr8 bufPtr = stackBuf->Ptr( pos );
+
+ // Read the descriptor argument into the buffer
+ aMessage.ReadL( 1, bufPtr );
+
+ // Read the third argument (index 2) that tells the size of this allocation
+ TInt size = aMessage.Int2();
+
+ // Construct a new CATMemoryEntry object.
+ // The ownership of the current stackBuf object is given to the "entry" object.
+ CATMemoryEntry* entry =
+ new (ELeave) CATMemoryEntry( memAddress, stackBuf, timeFrom1970, size );
+
+ // Pop stackBuf from CleanupStack and set it to NULL, because it is not used anymore.
+ CleanupStack::Pop( stackBuf );
+ stackBuf = NULL;
+
+ // Make sure that the same memory area is not tryed to be allocated a second time
+ TIdentityRelation<CATMemoryEntry> matcher( CATMemoryEntry::Match );
+
+ TInt index = iLeakArray.Find( entry, matcher );
+
+ if ( index == KErrNotFound )
+ {
+ TLinearOrder<CATMemoryEntry> order( CATMemoryEntry::Compare );
+
+ // Insert the "entry" object into "iLeakArray". The ownership of
+ // the "entry" object is given to the array.
+ iError = iLeakArray.InsertInOrderAllowRepeats( entry, order );
+
+ // If an insertion to the array was not successful, delete the created
+ // entry manually and return.
+ if ( iError )
+ {
+ delete entry;
+ return iError;
+ }
+
+ // Make a TAllocInfo object, and give values for its members.
+ TAllocInfo allocInfo( memAddress, size );
+
+ // Insert the allocInfo object into iAllocInfoArray
+ iError = iAllocInfoArray.InsertInUnsignedKeyOrder( allocInfo );
+
+ // If an insertion to the array was not successful, delete the created entry
+ // and remove its pointer from iLeakArray.
+ if ( iError )
+ {
+ index = iLeakArray.Find( entry, matcher );
+ // Delete the entry object and remove remove the pointer from the array
+ delete entry;
+ // The index should be in a legal range, because the earlier insertion of
+ // the entry was successful
+ iLeakArray.Remove( index );
+ }
+
+ // Otherwise update the iCurAllocSize, iMaxAllocs and iMaxAllocSize variables
+
+ iCurAllocSize += size;
+
+ // The count can never be negative => associate it to an unsigned int
+ TUint allocCount = iAllocInfoArray.Count();
+ if ( allocCount > iMaxAllocs )
+ {
+ iMaxAllocs = allocCount;
+ }
+
+ if ( iCurAllocSize > iMaxAllocSize )
+ {
+ iMaxAllocSize = iCurAllocSize;
+ }
+
+ return iError;
+ }
+
+ // This shouldn't happen, because the same memory area shouldn't be allocated
+ // more than once (without deallocating it first)
+ else
+ {
+ delete entry;
+ return KErrAlreadyExists;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::LogMemoryAllocTraceL()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::LogMemoryAllocTraceL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::LogMemoryAllocTraceL()" );
+
+ // Panic the client and return, if a logging session is not ongoing
+ // ( can be started by calling the client's LogProcessStarted() )
+ if ( !iLoggingOngoing )
+ {
+ PanicClient( EAToolNotAllowed, aMessage );
+ return KErrCancel;
+ }
+
+ // Read the first argument (index 0)
+ TUint32 memAddress = aMessage.Int0();
+ if ( memAddress == 0 )
+ {
+ return KErrNotSupported;
+ }
+
+ // Read the third argument (index 2) that tells the size of this allocation
+ TInt size = aMessage.Int2();
+
+ // Append this allocation into the iAllocInfoArray array. This array is for
+ // providing the configuration UI with information on allocations
+
+ // Make a TAllocInfo object, and give values for its members.
+ TAllocInfo allocInfo( memAddress, size );
+
+ // Insert the allocInfo object into iAllocInfoArray
+ iError = iAllocInfoArray.InsertInUnsignedKeyOrder( allocInfo );
+
+ // Log debug message if duplicated allocation.
+ if ( iError == KErrAlreadyExists )
+ {
+ LOGSTR2( "STSE TInt CATStorageServerSession::LogMemoryAllocTraceL() Error, duplicate allocation :%i", memAddress );
+ }
+
+ // A pointer to a buffer of call stack's memory addresses
+ CBufFlat* stackBuf = NULL;
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ // Read the length of the descriptor argument (index 1) that should include
+ // call stack memory addresses associated with this memory allocation
+ TInt bufferLength = aMessage.GetDesLength( 1 );
+
+ // Construct a buffer for aCallstack
+ stackBuf = CBufFlat::NewL( bufferLength );
+ CleanupStack::PushL( stackBuf );
+
+ // Buffer position
+ TInt pos( 0 );
+ stackBuf->ExpandL( pos, bufferLength );
+
+ TPtr8 bufPtr = stackBuf->Ptr( pos );
+
+ // Read the descriptor argument (index 1) into the buffer
+ aMessage.ReadL( 1, bufPtr );
+
+ // Variable for the number of memory addresses in the call stack
+ TInt addrCount( 0 );
+ TUint32 callStackAddr;
+
+ // Read the first word of the buffer. This includes the number of
+ // memory addresses stored in the current stackBuf
+ stackBuf->Read( pos, &addrCount, KWordSize );
+
+ // Move the position one word onwards.
+ pos += KWordSize;
+
+ // Create a 16-bit buffer, and a pointer descriptor for it
+ // ALLOCH <Memory address> <Time stamp> <Allocation size> <Call stack address count>
+ // <Call stack address> <Call stack address> ...
+ HBufC* traceBuf = HBufC::NewL( KMemAllocBufLength );
+ TPtr tracePtr( traceBuf->Des() );
+
+ // Pop stackBuf from CleanupStack, since no leavable operations will be done
+ // anymore
+ CleanupStack::Pop( stackBuf );
+
+ // Append the tag implying a memory allocation line in the data file
+ tracePtr.Append( KMemoryAllocHeader );
+
+ // Append the start address of this allocation in the 32-bit (max 8 characters)
+ // hexadecimal text format.
+ tracePtr.AppendNum( memAddress, EHex );
+
+ // Append the current time in the 64-bit (max 16 characters) hexadecimal text
+ // format
+ tracePtr.Append( KSpaceTrace );
+ tracePtr.AppendNum( timeFrom1970, EHex );
+
+ // Append the size of the allocation in the 32-bit (max 8 characters) hexadecimal
+ // text format.
+ tracePtr.Append( KSpaceTrace );
+ tracePtr.AppendNum( size, EHex );
+
+ // Append call stack address count
+ tracePtr.Append( KSpaceTrace );
+ tracePtr.AppendNum( addrCount, EHex );
+
+ // Calculate last item length
+ TInt lastItemLength( KTraceMessage().Length() + KHexa32Length +
+ KSpaceLength + KNewlineLength );
+
+ TUint packetNumber( 1 );
+
+ // Go through all call stack's memory addresses associated with
+ // this memory allocation
+ for ( TInt j = 0; j < addrCount; j++ )
+ {
+ // ALLOCF <Memory address> <Time stamp> <Packet number>
+ // <Call stack address> <Call stack address> ...
+ if ( tracePtr.Length() <= 0 )
+ {
+ // Create alloc fragment message header
+ tracePtr.Append( KMemoryAllocFragment );
+ tracePtr.AppendNum( memAddress, EHex );
+ tracePtr.Append( KSpaceTrace );
+ tracePtr.AppendNum( timeFrom1970, EHex );
+ tracePtr.Append( KSpaceTrace );
+ tracePtr.AppendNum( packetNumber, EHex );
+ // Increase packet number
+ packetNumber++;
+ }
+
+ // Read the next call stack's memory address stored in the buffer.
+ stackBuf->Read( pos, &callStackAddr, KWordSize );
+
+ // Append the read memory address as a hexadecimal number
+ tracePtr.AppendFormat( KHexaNumberTrace, callStackAddr );
+
+ // Move the pos variable one word onwards.
+ pos += KWordSize;
+
+ // Check if buffer max length exceed
+ if ( lastItemLength + tracePtr.Length() >= KMemAllocBufLength )
+ {
+ tracePtr.Append( KNewLineTrace );
+ // Log through debug channel
+ RDebug::Print( KTraceMessage, iProcessId, traceBuf );
+ // Empty trace buffer
+ tracePtr.Delete( 0, tracePtr.MaxLength() );
+ }
+ }
+
+ // Send the last message if exists
+ if ( tracePtr.Length() > 0 )
+ {
+ tracePtr.Append( KNewLineTrace );
+
+ // Log through debug channel
+ RDebug::Print( KTraceMessage, iProcessId, traceBuf );
+ }
+
+ delete traceBuf;
+ delete stackBuf;
+
+ // Update the iCurAllocSize, iMaxAllocs and iMaxAllocSize variables
+ iCurAllocSize += size;
+
+ // The count can never be negative => associate it to an unsigned int
+ TUint allocCount = iAllocInfoArray.Count();
+ if ( allocCount > iMaxAllocs )
+ {
+ iMaxAllocs = allocCount;
+ }
+
+ if ( iCurAllocSize > iMaxAllocSize )
+ {
+ iMaxAllocSize = iCurAllocSize;
+ }
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::LogMemoryFreedL()
+// Removes a TATMemoryEntry object with the specified memory address from
+// iLeakArray, if found.
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::LogMemoryFreedL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::LogMemoryFreedL()" );
+
+ // Panic the client and return, if a logging session is not ongoing
+ // ( can be started by calling the client's LogProcessStarted() )
+ if ( !iLoggingOngoing )
+ {
+ PanicClient( EAToolNotAllowed, aMessage );
+ return KErrCancel;
+ }
+
+ // Get the memory address
+ TUint32 memAddress = aMessage.Int0();
+
+ // Remove this memory allocation from the leak array
+ TIdentityRelation<CATMemoryEntry> matcher( CATMemoryEntry::Match );
+ CATMemoryEntry* entry = new (ELeave) CATMemoryEntry( memAddress, NULL, 0, 0 );
+ TInt index = iLeakArray.Find( entry, matcher );
+ delete entry;
+
+ // Return, if the requested memory address was not found
+ // (had not been allocated)
+ if ( index == KErrNotFound )
+ {
+ return index;
+ }
+
+ // Delete the CATMemoryEntry object at "index" and remove from the array
+ delete iLeakArray[index];
+ iLeakArray.Remove( index );
+
+ // Remove this memory allocation also from the allocation info array
+ // Make a TAllocInfo object for a "find" operation
+ TAllocInfo allocInfo( memAddress, 0 );
+ index = iAllocInfoArray.FindInUnsignedKeyOrder( allocInfo );
+
+ // The index should not be KErrNotFound, because an object with this memory address
+ // was found in the iLeakArray array. If the index is out of range, something is
+ // badly wrong, so it would be alright to panic in that case.
+ if ( index == KErrNotFound )
+ {
+ PanicClient( EAToolInternalError, aMessage );
+ return KErrCancel;
+ }
+
+ // Decrease the current alloc size and remove the requested allocation
+ // from iAllocInfoArray
+ iCurAllocSize -= iAllocInfoArray[index].iAllocSize;
+ iAllocInfoArray.Remove( index );
+
+ // If we are here, everything has gone alright
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::IsMemoryAdded()
+// Check a memory allocation (memory address) from an internal array.
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::IsMemoryAdded( const RMessage2& aMessage,
+ const TBool aRemoveAlloc )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::IsMemoryAdded()" );
+
+ // Panic the client and return, if a logging session is not ongoing
+ // ( can be started by calling the client's LogProcessStarted() )
+ if ( !iLoggingOngoing )
+ {
+ PanicClient( EAToolNotAllowed, aMessage );
+ return KErrCancel;
+ }
+
+ // Read the first argument (index 0)
+ TUint32 memAddress = aMessage.Int0();
+
+ // Try to find this memory allocation from the allocation info array
+
+ // Make a TAllocInfo object for a "find" operation
+ TAllocInfo allocInfo( memAddress, 0 );
+ TInt index( iAllocInfoArray.FindInUnsignedKeyOrder( allocInfo ) );
+
+ if ( index == KErrNotFound )
+ {
+ return index;
+ }
+ else if ( aRemoveAlloc )
+ {
+ // Otherwise decrease the current alloc size and remove the requested allocation
+ // from iAllocInfoArray
+ iCurAllocSize -= iAllocInfoArray[index].iAllocSize;
+ iAllocInfoArray.Remove( index );
+ }
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::LogMemoryFreedTraceL()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::LogMemoryFreedTraceL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::LogMemoryFreedTraceL()" );
+
+ // Panic the client and return, if a logging session is not ongoing
+ // ( can be started by calling the client's LogProcessStarted() )
+ if ( !iLoggingOngoing )
+ {
+ PanicClient( EAToolNotAllowed, aMessage );
+ return KErrCancel;
+ }
+
+ // A pointer to a buffer of call stack's memory addresses
+ CBufFlat* stackBuf = NULL;
+ iError = KErrNone;
+
+ // Read the first argument (index 0)
+ TUint32 memAddress = aMessage.Int0();
+
+ // Remove address from allocation table and its size from alloc size,
+ // if found from table.
+ TAllocInfo allocInfo( memAddress, 0 ); // Dummy info for search.
+ TInt index( iAllocInfoArray.FindInUnsignedKeyOrder( allocInfo ) );
+ if ( index != KErrNotFound )
+ {
+ // Decrease the current alloc size and remove the requested allocation
+ // from table.
+ iCurAllocSize -= iAllocInfoArray[index].iAllocSize;
+ iAllocInfoArray.Remove( index );
+ }
+ else
+ {
+ LOGSTR2( "STSE TInt CATStorageServerSession::LogMemoryFreedTrace() Error, cannot find alloc for free: %i", memAddress );
+ }
+
+ // Read the length of the descriptor argument (index 1) that should include
+ // call stack memory addresses associated with this memory allocation
+ TInt bufferLength = aMessage.GetDesLength( 1 );
+
+ // Construct a buffer for aCallstack
+ stackBuf = CBufFlat::NewL( bufferLength );
+ CleanupStack::PushL( stackBuf );
+
+ // Buffer position
+ TInt pos = 0;
+
+ stackBuf->ExpandL( pos, bufferLength );
+
+ TPtr8 bufPtr = stackBuf->Ptr( pos );
+
+ // Read the descriptor argument (index 1) into the buffer
+ aMessage.ReadL( 1, bufPtr );
+
+ // Variable for the number of memory addresses in the call stack
+ TInt addrCount( 0 );
+ TUint32 callStackAddr( 0 );
+
+ // Read the first word of the buffer. This includes the number of
+ // memory addresses stored in the current stackBuf
+ stackBuf->Read( pos, &addrCount, KWordSize );
+
+ // Move the position one word onwards.
+ pos += KWordSize;
+
+ // Create a 16-bit buffer, and a pointer descriptor for it
+ HBufC* traceBuf = HBufC::NewL( KMemFreedBufLength );
+ TPtr tracePtr( traceBuf->Des() );
+
+ // Pop stackBuf from CleanupStack, since no leavable operations will be done
+ // anymore
+ CleanupStack::Pop( stackBuf );
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ // Memory deallocation header message.
+ // FREEH <Memory address> <Time stamp> <Call stack address count> <Call stack address>
+ // <Call stack address> ...
+
+ // Append the tag implying a memory free line in the data file
+ tracePtr.Append( KMemoryFreedHeader );
+
+ // Append the start address of this allocation in the 32-bit (max 8 characters)
+ // hexadecimal text format.
+ tracePtr.AppendNum( memAddress, EHex );
+
+ // Append the current time in the 64-bit (max 16 characters) hexadecimal text
+ // format
+ tracePtr.Append( KSpaceTrace );
+ tracePtr.AppendNum( timeFrom1970, EHex );
+
+ // Append call stack address count
+ tracePtr.Append( KSpaceTrace );
+ tracePtr.AppendNum( addrCount, EHex );
+
+ // Packet number
+ TUint packetNumber( 1 );
+
+ // Calculate last item length
+ TInt lastItemLength( KTraceMessage().Length() + KHexa32Length +
+ KSpaceLength + KNewlineLength );
+
+ // Go through all call stack's memory addresses associated with
+ // this memory allocation
+ for ( TInt j = 0; j < addrCount; j++ )
+ {
+ if ( tracePtr.Length() <= 0 )
+ {
+ // Memory deallocation fragment message.
+ // FREEF <Memory address> <Time stamp> <Packet number> <Call stack address count>
+ // <Call stack address>...
+ // Create free fragment message header
+ tracePtr.Append( KMemoryFreedFragment );
+ tracePtr.AppendNum( memAddress, EHex );
+ tracePtr.Append( KSpaceTrace );
+ tracePtr.AppendNum( timeFrom1970, EHex );
+ tracePtr.Append( KSpaceTrace );
+ tracePtr.AppendNum( packetNumber, EHex );
+ // Increase packet number
+ packetNumber++;
+ }
+
+ // Read the next call stack's memory address stored in the buffer.
+ stackBuf->Read( pos, &callStackAddr, KWordSize );
+
+ // Append the read memory address as a hexadecimal number
+ tracePtr.AppendFormat( KHexaNumberTrace, callStackAddr );
+
+ // Move the pos variable one word onwards.
+ pos += KWordSize;
+
+ // Check if buffer max length exceed
+ if ( lastItemLength + tracePtr.Length() >= KMemFreedBufLength )
+ {
+ tracePtr.Append( KNewLineTrace );
+ // Log through debug channel
+ RDebug::Print( KTraceMessage, iProcessId, traceBuf );
+ // Empty trace buffer
+ tracePtr.Delete( 0, tracePtr.MaxLength() );
+ }
+ }
+
+ // Send the last message if exists
+ if ( tracePtr.Length() > 0 )
+ {
+ tracePtr.Append( KNewLineTrace );
+
+ // Log through debug channel
+ RDebug::Print( KTraceMessage, iProcessId, traceBuf );
+ }
+
+ delete traceBuf;
+ delete stackBuf;
+ // If we are here, everything has gone alright
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::LogProcessEndedL()
+// Prints memory leaks and information on process end into a file opened by the
+// function LogProcessStartedL()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::LogProcessEndedL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::LogProcessEndedL()" );
+
+ // Panic the client and return, if a logging session is not ongoing
+ // ( can be started by calling the client's LogProcessStarted() )
+ if ( !iLoggingOngoing )
+ {
+ PanicClient( EAToolNotAllowed, aMessage );
+ return KErrCancel;
+ }
+
+ iError = KErrNone;
+
+ // Read the sent process ID
+ TUint processId = aMessage.Int0();
+
+ // The process ID got from the client should equal iProcessId.
+ // If it does not, return KErrNotSupported
+ if ( processId != iProcessId )
+ {
+ return KErrNotSupported;
+ }
+
+ //////////////////////////////////////////////
+ // Log memory leaks
+ //////////////////////////////////////////////
+
+ // Print the information on the memory allocations that were never freed
+ iError = PrintLeaksL( aMessage );
+
+ if ( iError != KErrNone )
+ {
+ return iError;
+ }
+
+ //////////////////////////////////////////////
+ // Log handle leaks
+ //////////////////////////////////////////////
+
+ TUint handleLeakCount = aMessage.Int1();
+
+ if( handleLeakCount == 0 )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::LogProcessEndedL() No handle leaks to report" );
+ }
+ else
+ {
+ // Make a buffer that will be logged
+ TBuf8<KHandleLeakBufLength> loggingBuf;
+
+ // Set handle leak module name to unknown since it can not be defined.
+ // Write the handle leak count from aMessage.
+ loggingBuf.Format( KHandleLeak, &KUnknownModule, handleLeakCount );
+
+ // Write the constructed string into the data file and return if error
+ iError = iFile.Write( loggingBuf );
+
+ if ( iError != KErrNone )
+ {
+ return iError;
+ }
+ }
+
+ //////////////////////////////////////////////
+ // Log process end
+ //////////////////////////////////////////////
+
+ // Make a buffer that will be logged into the opened logging file
+ TBufC8<KProcessEndBufLength> processEndBuf;
+
+ TPtr8 bufPtr = processEndBuf.Des();
+
+ bufPtr.AppendFormat( KProcessEnd, iProcessId );
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ // Append the current time in the 64-bit (max 16 characters) hexadecimal text
+ // format
+ bufPtr.AppendNum( timeFrom1970, EHex );
+
+ // Append a new line
+ bufPtr.Append( KNewLine );
+
+ // Write the buffer into a file and return the error code
+ iError = iFile.Write( processEndBuf );
+
+ // Close the file and the handle to the file server
+ CloseFsAndFile();
+
+ // Remove the process from the server's array of processes
+ iError = iStorageServer.RemoveProcessL( processId );
+
+ // Reset iProcesssId and set the logging flag false
+ iProcessId = KNullProcessId;
+ iLoggingOngoing = EFalse;
+
+ return iError;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::LogProcessEndTraceL()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::LogProcessEndTraceL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::LogProcessEndTraceL()" );
+
+ // Panic the client and return, if a logging session is not ongoing
+ // ( can be started by calling the client's LogProcessStarted() )
+ if ( !iLoggingOngoing )
+ {
+ PanicClient( EAToolNotAllowed, aMessage );
+ return KErrCancel;
+ }
+
+ iError = KErrNone;
+
+ // Read the sent process ID
+ TUint processId = aMessage.Int0();
+
+ // The process ID got from the client should equal iProcessId.
+ // If it does not, return KErrNotSupported
+ if ( processId != iProcessId )
+ {
+ return KErrNotSupported;
+ }
+
+ //////////////////////////////////////////////
+ // Log handle leaks
+ //////////////////////////////////////////////
+
+ TUint handleLeakCount = aMessage.Int1();
+
+ if( handleLeakCount == 0 )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::LogProcessEndTraceL() No handle leaks to report" );
+ }
+ else
+ {
+ // Make a buffer that will be logged
+ TBuf8<KHandleLeakBufLength> loggingBuf;
+
+ // Make a 16-bit buffer that can be logged using RDebug
+ TBuf<KHandleLeakBufLength> traceBuf;
+
+ // Set handle leak module name to unknown since it can not be defined.
+ // Write the handle leak count from aMessage.
+ loggingBuf.Format( KHandleLeak, &KUnknownModule, handleLeakCount );
+
+ traceBuf.Copy( loggingBuf );
+
+ // Log through debug channel
+ RDebug::Print( KTraceMessage, iProcessId , &traceBuf );
+ }
+
+ //////////////////////////////////////////////
+ // Log process end
+ //////////////////////////////////////////////
+
+ // Make a buffer that will be logged
+ TBuf<KProcessEndBufLength> processEndBuf;
+ processEndBuf.AppendFormat( KProcessEndTrace, iProcessId );
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ // Append the current time in the 64-bit (max 16 characters) hexadecimal text
+ // format
+ processEndBuf.AppendNum( timeFrom1970, EHex );
+
+ // Append a new line
+ processEndBuf.Append( KNewLineTrace );
+
+ // Log through debug channel
+ RDebug::Print( KTraceMessage, iProcessId, &processEndBuf );
+
+ // Remove the process from the server's array of processes
+ iError = iStorageServer.RemoveProcessL( iProcessId );
+
+ // Reset iProcesssId and set the logging flag false
+ iProcessId = KNullProcessId;
+ iLoggingOngoing = EFalse;
+
+ return iError;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::CheckMemoryAddressL()
+// Checks if given memory address can be found
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::CheckMemoryAddressL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::CheckMemoryAddressL()" );
+
+ // Panic the client and return, if a logging session is not ongoing
+ // ( can be started by calling the client's LogProcessStarted() )
+ if ( !iLoggingOngoing )
+ {
+ PanicClient( EAToolNotAllowed, aMessage );
+ return KErrCancel;
+ }
+
+ iError = KErrNone;
+
+ // Check if memory address can be found in iLeakArray
+ TUint32 memAddress = aMessage.Int0();
+ TIdentityRelation<CATMemoryEntry> matcher( CATMemoryEntry::Match );
+ CATMemoryEntry* entry = new (ELeave) CATMemoryEntry( memAddress, NULL, 0, 0 );
+
+ // Get the index or an error code
+ iError = iLeakArray.Find( entry, matcher );
+ delete entry;
+
+ return iError;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::CheckMemoryAddressTrace()
+// Checks if some memory address can be found
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::CheckMemoryAddressTrace( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::CheckMemoryAddressTrace()" );
+
+ // Panic the client and return, if a logging session is not ongoing
+ // ( can be started by calling the client's LogProcessStarted() )
+ if ( !iLoggingOngoing )
+ {
+ PanicClient( EAToolNotAllowed, aMessage );
+ return KErrCancel;
+ }
+
+ // Always return KErrNone in this mode
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::GetProcessesL()
+// Checks if some memory address can be found
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::GetProcessesL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::GetProcessesL()" );
+
+ iError = KErrNone;
+
+ TInt processInfoSize = sizeof( TATProcessInfo );
+
+ CBufFlat* processInfoBuf;
+
+ // Buffer position
+ TInt pos( 0 );
+
+ // Calculate the length of the buffer to be constructed for processes
+ // One word will be reserved for the length of the array.
+ TInt bufferLength = KWordSize + KATMaxProcesses * processInfoSize;
+
+ // Construct processInfoBuf and expand it before the beginning (index 0)
+ processInfoBuf = CBufFlat::NewL( bufferLength );
+ CleanupStack::PushL( processInfoBuf );
+ processInfoBuf->ExpandL( pos, bufferLength );
+
+ RArray<TATProcessInfo> processArray = iStorageServer.ProcessInfoArray();
+
+ // Variable for the number of TATProcessInfo objects in processArray
+ TInt count = processArray.Count();
+
+ // The count cannot be greater than KATMaxProcesses, because the client
+ // has reserved a buffer of this size to be filled by the server
+ if ( count > KATMaxProcesses )
+ {
+ count = KATMaxProcesses;
+ }
+
+ // Write the count (4 bytes) into the beginning of processInfoBuf
+ processInfoBuf->Write( pos, &count, KWordSize );
+
+ // Move the position one word onwards.
+ pos += KWordSize;
+
+ // Write all the process info objects into the buffer
+ for ( TInt i = 0; i < count; i++ )
+ {
+ TATProcessInfo& processInfo = processArray[i];
+
+ // Write the current process info into the buffer
+ processInfoBuf->Write( pos, &processInfo, processInfoSize );
+
+ // Move the pos variable onwards.
+ pos += processInfoSize;
+ }
+
+ // Make a pointer descriptor pointing to the start of processInfoBuf
+ TPtr8 bufPtr( processInfoBuf->Ptr(0) );
+
+ // Write the buffer into aMessage at index 0 for the client
+ aMessage.WriteL( 0, bufPtr );
+
+ CleanupStack::PopAndDestroy( processInfoBuf );
+
+ return iError;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::GetDllsL()
+// Checks if some memory address can be found
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::GetDllsL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::GetDllsL()" );
+
+ // Read the process ID at index 0
+ TUint processId = aMessage.Int0();
+
+ // Size of a DLL descriptor
+ TInt sizeOfDllDesc = sizeof( TBuf8<KMaxLibraryName> );
+
+ // Buffer position
+ TInt pos( 0 );
+
+ // Calculate the length of the buffer to be constructed for DLL names.
+ // One word will be reserved for the length of the array.
+ TInt bufferLength = KWordSize + KATMaxDlls * sizeOfDllDesc;
+
+ CBufFlat* dllBuf;
+ // Construct dllBuf and expand it before the beginning (index 0)
+ dllBuf = CBufFlat::NewL( bufferLength );
+ CleanupStack::PushL( dllBuf );
+ dllBuf->ExpandL( pos, bufferLength );
+
+ RPointerArray<CATDynProcessInfo> dynProcessArray =
+ iStorageServer.DynProcessInfoArray();
+
+ // Construct a CATDynProcessInfo object with the given process ID for searching
+ CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId );
+
+ // Find the index of a CATDynProcessInfo object with the given process ID
+ TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare );
+ TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order );
+ delete dynProcessInfo;
+ dynProcessInfo = NULL;
+
+ // Return, if a process with the requested process ID was not found
+ if ( index == KErrNotFound )
+ {
+ CleanupStack::PopAndDestroy( dllBuf );
+ return index;
+ }
+
+ // Get the wanted dynamic process info
+ dynProcessInfo = dynProcessArray[index];
+
+ // Fetch a reference to the desired DLL array
+ RArray<TATDllInfo>& dllArray = dynProcessInfo->iDlls;
+
+ // Take the count of names in the array
+ TInt count = dllArray.Count();
+
+ // The count cannot be greater than KATMaxDlls, because the client
+ // has reserved a buffer of this size to be filled by the server
+ if ( count > KATMaxDlls )
+ {
+ count = KATMaxDlls;
+ }
+
+ // Write the count (4 bytes) into the beginning of dllBuf
+ dllBuf->Write( pos, &count, KWordSize );
+
+ // Move the position one word onwards.
+ pos += KWordSize;
+
+ // Go through all DLL names objects sent to the server
+ for ( TInt i = 0; i < count; i++ )
+ {
+ TBuf8<KMaxLibraryName>& dllName = dllArray[i].iName;
+
+ // Write the current DLL name into the buffer
+ dllBuf->Write( pos, &dllName, sizeOfDllDesc );
+
+ // Move the pos variable onwards.
+ pos += sizeOfDllDesc;
+ }
+
+ // Make a pointer descriptor pointing to the start of dllBuf
+ TPtr8 bufPtr( dllBuf->Ptr(0) );
+
+ // Write the whole buffer into aMessage at index 1 for the client
+ aMessage.WriteL( 1, bufPtr );
+
+ CleanupStack::PopAndDestroy( dllBuf );
+
+ // The dynProcessInfo object will not be deleted, because it is still owned by the
+ // server object's dynamic process info array.
+ dynProcessInfo = NULL;
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::GetLoggingModeL()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::GetLoggingModeL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::GetLoggingModeL()" );
+
+ iError = KErrNone;
+
+ // Read the process ID at index 0
+ TUint processId = aMessage.Int0();
+
+ // Buffer position
+ TInt pos( 0 );
+
+ // The length of the buffer to be constructed for logging mode
+ TInt bufferLength = KWordSize;
+
+ // Get the dynamic process info array
+ RPointerArray<CATDynProcessInfo> dynProcessArray =
+ iStorageServer.DynProcessInfoArray();
+
+ // Construct a CATDynProcessInfo object with the given process ID for searching
+ CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId );
+
+ // Find the index of a CATDynProcessInfo object with the given process ID
+ TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare );
+ TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order );
+ delete dynProcessInfo;
+ dynProcessInfo = NULL;
+
+ // Return, if a process with the requested process ID was not found
+ if ( index == KErrNotFound )
+ {
+ return index;
+ }
+
+ // Otherwise get the wanted dynamic process info
+ dynProcessInfo = dynProcessArray[index];
+
+ // Get the desired process's associated session object
+ CATStorageServerSession* sessionObject = dynProcessInfo->iSessionObject;
+ CBufFlat* loggingModeBuf;
+ // Construct allocInfoBuf and expand it before the beginning (index 0)
+ loggingModeBuf = CBufFlat::NewL( bufferLength );
+ CleanupStack::PushL( loggingModeBuf );
+ loggingModeBuf->ExpandL( 0, bufferLength );
+
+ // Write the current logging mode of the requested process into the buffer.
+ loggingModeBuf->Write( pos, &sessionObject->iLogOption, KWordSize );
+
+ // Make a pointer descriptor that points to the data of allocInfoBuf
+ TPtr8 bufPtr( loggingModeBuf->Ptr(0) );
+
+ // Write the whole buffer into aMessage at index 1 for the client
+ aMessage.WriteL( 1, bufPtr );
+
+ CleanupStack::PopAndDestroy( loggingModeBuf );
+
+ return iError;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::StartSubtestL()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::StartSubtestL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::StartSubtestL()" );
+
+ iError = KErrNone;
+
+ // Read the process ID at index 0
+ TUint processId = aMessage.Int0();
+
+ // Read the sub test ID at index 1
+ TBuf8<KATMaxSubtestIdLength> subTestName;
+ iError = aMessage.Read( 1, subTestName );
+
+ // Return if reading was not successful
+ if ( iError != KErrNone )
+ {
+ return iError;
+ }
+
+ // Create another (non-8-bit) descriptor for logging to trace
+ // and copy the contents
+ TBuf<KATMaxSubtestIdLength> subTestNameTrace;
+ subTestNameTrace.Copy( subTestName );
+
+ // Read the handle count at index 2
+ TInt handleCount = aMessage.Int2();
+
+ // FIND THE REQUESTED PROCESS
+
+ // Get the dynamic process array
+ RPointerArray<CATDynProcessInfo> dynProcessArray =
+ iStorageServer.DynProcessInfoArray();
+
+ // Construct a CATDynProcessInfo object with the given process ID for searching
+ CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId );
+
+ // Find the index of a CATDynProcessInfo object with the given process ID
+ TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare );
+ TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order );
+ delete dynProcessInfo;
+ dynProcessInfo = NULL;
+
+ // Return, if a process with the requested process ID was not found
+ if ( index == KErrNotFound )
+ {
+ return index;
+ }
+
+ // Get the wanted dynamic process info
+ dynProcessInfo = dynProcessArray[index];
+
+ // Get the desired process's associated session object
+ const CATStorageServerSession* sessionObject = dynProcessInfo->iSessionObject;
+
+ // Make a buffer for logging thru trace
+ TBuf<KTestStartBufLength> loggingBuf;
+
+ // Copy the line tag into the buffer
+ loggingBuf.Copy( KSubtestStart );
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ // Append the current time in the 64-bit (max 16 characters) hexadecimal text
+ // format
+ loggingBuf.AppendNum( timeFrom1970, EHex );
+
+ // Append a space
+ loggingBuf.Append( KSpaceTrace );
+
+ // Append the sub test ID
+ loggingBuf.Append( subTestNameTrace );
+
+ // Append a space
+ loggingBuf.Append( KSpaceTrace );
+
+ // Append current handle leak count
+ loggingBuf.AppendNum( handleCount );
+
+ // Append a new line
+ loggingBuf.Append( KNewLineTrace );
+
+ // Log the string through trace
+ iError = sessionObject->LogThroughTrace( loggingBuf );
+
+ // *******************
+ // Send loaded DLL's
+ // *******************
+
+ // Fetch a reference to the desired DLL array
+ RArray<TATDllInfo>& dllArray = dynProcessInfo->iDlls;
+
+ // Take the count of dll info items
+ TInt count( dllArray.Count() );
+ LOGSTR2( "STSE > dllArray.Count( %i )", count );
+
+ // Create buffers
+ TBuf<KDllLoadBufLength> traceBuf;
+ TBuf8<KDllLoadBufLength> dllBuf;
+
+ for ( TInt x = 0; x < count; x++ )
+ {
+ dllBuf.Format( KDllLoad, &dllArray[x].iName, dllArray[x].iLoadTime,
+ dllArray[x].iStartAddress, dllArray[x].iEndAddress );
+ traceBuf.Copy( dllBuf );
+
+ // Log the string through trace
+ iError = sessionObject->LogThroughTrace( traceBuf );
+ if ( iError != KErrNone )
+ {
+ LOGSTR2( "STSE > LogThroughTrace() err( %i )", iError );
+ }
+ }
+ sessionObject = NULL;
+
+ return iError;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::StopSubtestL()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::StopSubtestL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::StopSubtestL()" );
+
+ iError = KErrNone;
+
+ // Read the process ID at index 0
+ TUint processId = aMessage.Int0();
+
+ // Read the sub test ID at index 1
+ TBuf8<KATMaxSubtestIdLength> subTestName;
+ iError = aMessage.Read( 1, subTestName );
+
+ // Return if reading was not successful
+ if ( iError != KErrNone )
+ {
+ return iError;
+ }
+
+ // Create another (non-8-bit) descriptor for logging to trace,
+ // and copy the contents
+ TBuf<KATMaxSubtestIdLength> subTestNameTrace;
+ subTestNameTrace.Copy( subTestName );
+
+ // Read the handle count at index 2
+ TInt handleCount = aMessage.Int2();
+
+ // FIND THE REQUESTED PROCESS
+
+ // Get the dynamic process array
+ RPointerArray<CATDynProcessInfo> dynProcessArray =
+ iStorageServer.DynProcessInfoArray();
+
+ // Construct a CATDynProcessInfo object with the given process ID for searching
+ CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId );
+
+ // Find the index of a CATDynProcessInfo object with the given process ID
+ TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare );
+ TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order );
+ delete dynProcessInfo;
+ dynProcessInfo = NULL;
+
+ // Return, if a process with the requested process ID was not found
+ if ( index == KErrNotFound )
+ {
+ return index;
+ }
+
+ // Get the wanted dynamic process info
+ dynProcessInfo = dynProcessArray[index];
+
+ // Get the desired process's associated session object
+ const CATStorageServerSession* sessionObject = dynProcessInfo->iSessionObject;
+
+ // Make a buffer for logging thru trace
+ TBuf<KTestEndBufLength> loggingBuf;
+
+ // Copy the line tag into the buffer
+ loggingBuf.Copy( KSubtestEnd );
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ // Append the current time in the 64-bit (max 16 characters) hexadecimal text
+ // format
+ loggingBuf.AppendNum( timeFrom1970, EHex );
+
+ // Append a space
+ loggingBuf.Append( KSpaceTrace );
+
+ // Append the sub test ID
+ loggingBuf.Append( subTestNameTrace );
+
+ // Append a space
+ loggingBuf.Append( KSpaceTrace );
+
+ // Append current handle leak count
+ loggingBuf.AppendNum( handleCount );
+
+ // Append a new line
+ loggingBuf.Append( KNewLineTrace );
+
+ // Log the string through trace
+ iError = sessionObject->LogThroughTrace( loggingBuf );
+
+ sessionObject = NULL;
+
+ return iError;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::StartSubtest2L()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::StartSubtest2L( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::StartSubtest2L()" );
+
+ iError = KErrNone;
+
+ // Read the sub test ID at index 0
+ TBuf8<KATMaxSubtestIdLength> subTestName;
+ iError = aMessage.Read( 0, subTestName );
+
+ // Return if reading was not successful
+ if ( iError != KErrNone )
+ {
+ return iError;
+ }
+
+ // Create another (non-8-bit) descriptor for logging to trace
+ // and copy the contents
+ TBuf<KATMaxSubtestIdLength> subTestNameTrace;
+ subTestNameTrace.Copy( subTestName );
+
+ // Make a buffer for logging thru trace
+ TBuf<KTestStartBufLength> loggingBuf;
+
+ // Copy the line tag into the buffer
+ loggingBuf.Copy( KSubtestStart );
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ // Append the current time in the 64-bit (max 16 characters) hexadecimal text
+ // format
+ loggingBuf.AppendNum( timeFrom1970, EHex );
+
+ // Append a space
+ loggingBuf.Append( KSpaceTrace );
+
+ // Append the sub test ID
+ loggingBuf.Append( subTestNameTrace );
+
+ // Append a new line
+ loggingBuf.Append( KNewLineTrace );
+
+ // Log the string through trace
+ iError = LogThroughTrace( loggingBuf );
+
+ // *******************
+ // Send loaded DLL's
+ // *******************
+
+ // Get the dynamic process array
+ RPointerArray<CATDynProcessInfo> dynProcessArray =
+ iStorageServer.DynProcessInfoArray();
+
+ // Construct a CATDynProcessInfo object with the given process ID for searching
+ CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( iProcessId );
+
+ // Find the index of a CATDynProcessInfo object with the given process ID
+ TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare );
+ TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order );
+ delete dynProcessInfo;
+ dynProcessInfo = NULL;
+
+ // Return, if a process with the requested process ID was not found
+ if ( index == KErrNotFound )
+ {
+ return index;
+ }
+
+ // Get the wanted dynamic process info
+ dynProcessInfo = dynProcessArray[index];
+
+ // Fetch a reference to the desired DLL array
+ RArray<TATDllInfo>& dllArray = dynProcessInfo->iDlls;
+
+ // Take the count of dll info items
+ TInt count( dllArray.Count() );
+ LOGSTR2( "STSE > dllArray.Count( %i )", count );
+
+ // Create buffers
+ TBuf<KDllLoadBufLength> traceBuf;
+ TBuf8<KDllLoadBufLength> dllBuf;
+
+ for ( TInt x = 0; x < count; x++ )
+ {
+ dllBuf.Format( KDllLoad, &dllArray[x].iName, dllArray[x].iLoadTime,
+ dllArray[x].iStartAddress, dllArray[x].iEndAddress );
+ traceBuf.Copy( dllBuf );
+
+ // Log the string through trace
+ iError = LogThroughTrace( traceBuf );
+ if ( iError != KErrNone )
+ {
+ LOGSTR2( "STSE > LogThroughTrace() err( %i )", iError );
+ }
+ }
+
+ return iError;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::StopSubtest2()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::StopSubtest2( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::StopSubtest2()" );
+
+ iError = KErrNone;
+
+ // Read the sub test ID at index 0
+ TBuf8<KATMaxSubtestIdLength> subTestName;
+ iError = aMessage.Read( 0, subTestName );
+
+ // Return if reading was not successful
+ if ( iError != KErrNone )
+ {
+ return iError;
+ }
+
+ // Create another (non-8-bit) descriptor for logging to trace,
+ // and copy the contents
+ TBuf<KATMaxSubtestIdLength> subTestNameTrace;
+ subTestNameTrace.Copy( subTestName );
+
+ // Make a buffer for logging thru trace
+ TBuf<KTestEndBufLength> loggingBuf;
+
+ // Copy the line tag into the buffer
+ loggingBuf.Copy( KSubtestEnd );
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ // Append the current time in the 64-bit (max 16 characters) hexadecimal text
+ // format
+ loggingBuf.AppendNum( timeFrom1970, EHex );
+
+ // Append a space
+ loggingBuf.Append( KSpaceTrace );
+
+ // Append the sub test ID
+ loggingBuf.Append( subTestNameTrace );
+
+ // Append a new line
+ loggingBuf.Append( KNewLineTrace );
+
+ // Log the string through trace
+ iError = LogThroughTrace( loggingBuf );
+
+ return iError;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::GetCurrentAllocsL()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::GetCurrentAllocsL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::GetCurrentAllocsL()" );
+
+ iError = KErrNone;
+
+ // Read the process ID at index 0
+ TUint processId = aMessage.Int0();
+ TUint32 allocNumber( 0 );
+ TUint32 allocSize( 0 );
+
+ // Buffer position
+ TInt pos( 0 );
+
+ // The length of the buffer to be constructed for allocation number and size
+ TInt bufferLength = KWordSize + KWordSize;
+
+ // Get the dynamic process info array
+ RPointerArray<CATDynProcessInfo> dynProcessArray =
+ iStorageServer.DynProcessInfoArray();
+
+ // Construct a CATDynProcessInfo object with the given process ID for searching
+ CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId );
+
+ // Find the index of a CATDynProcessInfo object with the given process ID
+ TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare );
+ TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order );
+ delete dynProcessInfo;
+ dynProcessInfo = NULL;
+
+ // Return, if a process with the requested process ID was not found
+ if ( index == KErrNotFound )
+ {
+ return index;
+ }
+
+ // Otherwise get the wanted dynamic process info
+ dynProcessInfo = dynProcessArray[index];
+
+ // Get the desired process's associated session object
+ CATStorageServerSession* sessionObject = dynProcessInfo->iSessionObject;
+
+ // Get the alloc info array of that session object
+ RArray<TAllocInfo> allocInfo = sessionObject->AllocInfoArray();
+
+ // Get the values for current allocations number and size
+ allocNumber = allocInfo.Count();
+
+ // Calculate the total size of the current allocations
+ for ( TUint32 i = 0; i < allocNumber; i++ )
+ {
+ allocSize += allocInfo[i].iAllocSize;
+ }
+
+ LOGSTR2( "STSE allocSize: %u", allocSize );
+ LOGSTR2( "STSE iCurAllocSize: %u", iCurAllocSize );
+
+ CBufFlat* allocInfoBuf;
+ // Construct allocInfoBuf and expand it before the beginning (index 0)
+ allocInfoBuf = CBufFlat::NewL( bufferLength );
+ CleanupStack::PushL( allocInfoBuf );
+ allocInfoBuf->ExpandL( 0, bufferLength );
+
+ // Write the current number of allocations of the requested process into the buffer.
+ allocInfoBuf->Write( pos, &allocNumber, KWordSize );
+
+ // Move the position one word onwards
+ pos += KWordSize;
+
+ // Write the current total size of the allocations of the requested process into the
+ // buffer.
+ allocInfoBuf->Write( pos, &allocSize, KWordSize );
+
+ // Make a pointer descriptor that points to the data of allocInfoBuf
+ TPtr8 bufPtr( allocInfoBuf->Ptr(0) );
+
+ // Write the whole buffer into aMessage at index 1 for the client
+ aMessage.WriteL( 1, bufPtr );
+
+ CleanupStack::PopAndDestroy( allocInfoBuf );
+
+ return iError;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::GetMaxAllocsL()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::GetMaxAllocsL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::GetMaxAllocsL()" );
+
+ iError = KErrNone;
+
+ // Read the process ID at index 0
+ TUint processId = aMessage.Int0();
+ TUint32 allocNumber( 0 );
+ TUint32 allocSize( 0 );
+
+ // Buffer position
+ TInt pos( 0 );
+
+ // The length of the buffer to be constructed for allocation number and size
+ TInt bufferLength = KWordSize + KWordSize;
+
+ // Get the dynamic process info array
+ RPointerArray<CATDynProcessInfo> dynProcessArray =
+ iStorageServer.DynProcessInfoArray();
+
+ // Construct a CATDynProcessInfo object with the given process ID for searching
+ CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId );
+
+ // Find the index of a CATDynProcessInfo object with the given process ID
+ TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare );
+ TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order );
+ delete dynProcessInfo;
+ dynProcessInfo = NULL;
+
+ // Return, if a process with the requested process ID was not found
+ if ( index == KErrNotFound )
+ {
+ return index;
+ }
+
+ // Otherwise get the wanted dynamic process info
+ dynProcessInfo = dynProcessArray[index];
+
+ // Get the desired process's associated session object
+ CATStorageServerSession* sessionObject = dynProcessInfo->iSessionObject;
+
+ // Get values for the maximum allocations number and size
+ allocNumber = sessionObject->iMaxAllocs;
+ allocSize = sessionObject->iMaxAllocSize;
+
+ CBufFlat* allocInfoBuf;
+ // Construct allocInfoBuf and expand it before the beginning (index 0)
+ allocInfoBuf = CBufFlat::NewL( bufferLength );
+ CleanupStack::PushL( allocInfoBuf );
+ allocInfoBuf->ExpandL( 0, bufferLength );
+
+ // Write the maximum number of allocations of the requested process into the buffer.
+ allocInfoBuf->Write( pos, &allocNumber, KWordSize );
+
+ // Move the position one word onwards
+ pos += KWordSize;
+
+ // Write the maximum total size of the allocations of the requested process into the
+ // buffer.
+ allocInfoBuf->Write( pos, &allocSize, KWordSize );
+
+ // Make a pointer descriptor that points to the data of allocInfoBuf
+ TPtr8 bufPtr( allocInfoBuf->Ptr(0) );
+
+ // Write the whole buffer into aMessage at index 1 for the client
+ aMessage.WriteL( 1, bufPtr );
+
+ CleanupStack::PopAndDestroy( allocInfoBuf );
+
+ return iError;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::CancelLoggingL()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::CancelLoggingL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::CancelLoggingL()" );
+
+ iError = KErrNone;
+
+ // Read the process ID at index 0
+ TUint processId = aMessage.Int0();
+
+ // FIND THE REQUESTED PROCESS
+
+ // Get the dynamic process array
+ RPointerArray<CATDynProcessInfo> dynProcessArray =
+ iStorageServer.DynProcessInfoArray();
+
+ // Construct a CATDynProcessInfo object with the given process ID for searching
+ CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId );
+
+ // Find the index of a CATDynProcessInfo object with the given process ID
+ TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare );
+ TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order );
+ delete dynProcessInfo;
+ dynProcessInfo = NULL;
+
+ // Return, if a process with the requested process ID was not found
+ if ( index == KErrNotFound )
+ {
+ return index;
+ }
+
+ // Otherwise get the wanted dynamic process info
+ dynProcessInfo = dynProcessArray[index];
+
+ // Get the session object of the requested process
+ CATStorageServerSession* sessionObject = dynProcessInfo->iSessionObject;
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ // Make a buffer for logging "logging cancelled"
+ TBuf8<KCancelBufLength> loggingBuf;
+
+ // Copy the "logging cancelled" tag into the buffer with the current time
+ loggingBuf.AppendFormat( KLoggingCancelled, timeFrom1970 );
+
+ // Log the buffer eather to a file or to debug channel depending on the current
+ // logging mode
+
+ if ( sessionObject->iLoggingOngoing &&
+ sessionObject->iLogOption == EATLogToFile )
+ {
+ // Write the buffer into the file
+ sessionObject->iFile.Write( loggingBuf );
+ }
+
+ else if ( sessionObject->iLoggingOngoing &&
+ sessionObject->iLogOption == EATLogToTrace )
+ {
+ // Make a buffer for logging to trace
+ TBuf<KCancelBufLength> traceBuf;
+ traceBuf.Copy( loggingBuf );
+
+ // Write the buffer into the debug channel
+ RDebug::Print( KTraceMessage, processId ,&traceBuf );
+ }
+
+ // Switch off logging of the requested process
+ sessionObject->iLogOption = EATLoggingOff;
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::HandleError
+// Internally used for handling error situations.
+// -----------------------------------------------------------------------------
+//
+void CATStorageServerSession::HandleError( TInt aError )
+ {
+ LOGSTR1( "STSE void CATStorageServerSession::HandleError()" );
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ // Make a buffer that will be logged into the opened logging file
+ TBufC8<KErrOccuredBufLength> loggingBuf;
+
+ TPtr8 bufPtr( loggingBuf.Des() );
+
+ // Write the error code to the buffer
+ bufPtr.Format( KErrorOccured, aError );
+
+ // Append the current time in the 64-bit (max 16 characters) hexadecimal text
+ // format
+ bufPtr.AppendNum( timeFrom1970, EHex );
+
+ // Append a new line
+ bufPtr.Append( KNewLine );
+
+ // Write the buffer into a file (if possible in the current condition)
+ iFile.Write( loggingBuf );
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::HandleErrorTrace()
+// Internally used for handling error situations.
+// -----------------------------------------------------------------------------
+//
+void CATStorageServerSession::HandleErrorTrace( TInt aError )
+ {
+ LOGSTR1( "STSE void CATStorageServerSession::HandleErrorTrace()" );
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ // Make a buffer that will be logged
+ TBuf<KErrOccuredBufLength> traceBuf;
+
+ // Write the error code to the buffer
+ traceBuf.Format( KErrorOccuredTrace, aError );
+
+ // Append the current time in the 64-bit (max 16 characters) hexadecimal text
+ // format
+ traceBuf.AppendNum( timeFrom1970, EHex );
+
+ // Append a new line
+ traceBuf.Append( KNewLineTrace );
+
+ RDebug::Print( KTraceMessage, iProcessId , &traceBuf );
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::OpenFsAndFile
+// Internally used for opening a handle to the file server and a file
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::OpenFsAndFile( const TDesC& aFileName,
+ const TDesC8& aProcessName )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::OpenFsAndFile()" );
+
+ // Connect file server, return if error occured
+ iError = iFileServer.Connect();
+ if ( iError )
+ {
+ iFileServer.Close();
+ return iError;
+ }
+
+ // Open a file
+ TBuf<KMaxFileName> fileNameBuf;
+ iError = TATDriveInfo::CreatePath( fileNameBuf, aFileName, iFileServer );
+
+ // Return, if an error occured, and it
+ // is not KErrAlreadyExists
+ if ( iError && iError != KErrAlreadyExists )
+ {
+ iFileServer.Close();
+ return iError;
+ }
+
+ // Save the file name for this session
+ CnvUtfConverter::ConvertFromUnicodeToUtf8( iLogFile, fileNameBuf );
+
+ // Try to open file
+ CheckIfFileAlreadyExist( fileNameBuf );
+
+ // If a data file with the requested name already existed, and was opened
+ // successfully, check the version of the file. If the line telling the version of
+ // the file is not the expected, replace the file
+ // If cannot open the file(error is KErrInUse), generate new filename and
+ // then try to create new file.
+ if ( iError == KErrNone )
+ {
+ CheckFileVersion( fileNameBuf );
+ }
+ else if ( iError == KErrInUse )
+ {
+ GenerateNewFileName( fileNameBuf, aProcessName );
+
+ // Save the file name for this session
+ CnvUtfConverter::ConvertFromUnicodeToUtf8( iLogFile, fileNameBuf );
+ }
+ LOGSTR2( "STSE > iError(%i)", iError );
+
+ // If the file does not exist, create it. Write also the version number of
+ // the file at the beginning of the new file
+ if ( iError == KErrNotFound )
+ {
+ iError = iFile.Create( iFileServer, fileNameBuf, EFileWrite );
+
+ if ( !iError )
+ {
+ iError = iFile.Write( KDataFileVersion );
+ }
+ }
+
+ if ( iError )
+ {
+ iFile.Close();
+ iFileServer.Close();
+ return iError;
+ }
+
+ // Seek the end of the file and set the current file position there
+ TInt offset = 0;
+ iError = iFile.Seek( ESeekEnd, offset );
+
+ return iError;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::GenerateNewFileName
+// Called internally when need generate new file name.
+// -----------------------------------------------------------------------------
+//
+void CATStorageServerSession::GenerateNewFileName( TDes& aFileName,
+ const TDesC8& aProcessName )
+ {
+ LOGSTR1( "STSE void CATStorageServerSession::GenerateNewFileName()" );
+
+ // Extension
+ TBuf<KExtensionLength> extension;
+
+ // Parse file extension
+ ParseExtension( aFileName, extension );
+
+ // Try to find UID3 from current process name
+ TInt uidErr( KErrBadName );
+ TBuf<KMaxFileName> unicodeFile;
+
+ // Converts text encoded using the Unicode transformation format UTF-8
+ // into the Unicode UCS-2 character set.
+ CnvUtfConverter::ConvertToUnicodeFromUtf8( unicodeFile, aProcessName );
+ LOGSTR2( "STSE > unicodeFile(%S)", &unicodeFile );
+
+ // Find square brackets
+ TInt sPos( unicodeFile.Find( KOpenSquareBracket ) );
+ TInt ePos( unicodeFile.Find( KCloseSquareBracket ) );
+ LOGSTR3( "STSE > sPos(%i), ePos(%i)", sPos, ePos );
+
+ if ( sPos != KErrNotFound && ePos != KErrNotFound )
+ {
+ TBuf<KProcessUidLength> processUid;
+ TInt pEnd( ePos - sPos - KOpenSquareBracket().Length() );
+ LOGSTR2( "STSE > pEnd(%i)", pEnd );
+
+ // Copy UID value
+ if ( pEnd > 0 )
+ {
+ processUid.Copy( unicodeFile.Mid(
+ sPos + KOpenSquareBracket().Length(), pEnd ) );
+ LOGSTR2( "STSE > processUid(%S)", &processUid );
+ }
+
+ if ( aFileName.Find( processUid ) == KErrNotFound )
+ {
+ // UID not exist, create new filename
+ // Append uid to filename (<file name>_<uid>.<extension>)
+ aFileName.Append( KUnderLine );
+ aFileName.Append( processUid );
+ aFileName.Append( extension );
+ // Try to open file
+ CheckIfFileAlreadyExist( aFileName );
+
+ if ( iError == KErrNone )
+ {
+ uidErr = KErrNone;
+ CheckFileVersion( aFileName );
+ }
+ }
+ }
+
+ if ( uidErr == KErrBadName && iError != KErrNotFound )
+ {
+ // Need re-create file name, add end off file _xx (xx=01, 02...)
+ LOGSTR2( "STSE > Re-create file name, aFileName(%S)", &aFileName );
+
+ // Parse file extension if exists.
+ ParseExtension( aFileName, extension );
+
+ // Temp file name
+ TBuf<KMaxFileName> tempName;
+
+ for ( TInt i = KNameIndexStart; i < KNameIndexEnd; i++ )
+ {
+ tempName.Delete( 0, tempName.MaxLength() );
+ tempName.Format( KFormat, &aFileName, &KUnderLine, i, &extension );
+ LOGSTR2( "STSE > tempName(%S)", &tempName );
+ // Try to open file
+ CheckIfFileAlreadyExist( tempName );
+
+ if ( iError == KErrNone || iError == KErrNotFound )
+ {
+ aFileName.Copy( tempName );
+ break;
+ }
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::ParseExtension
+// Method is used to parse file name extension.
+// -----------------------------------------------------------------------------
+//
+void CATStorageServerSession::ParseExtension(
+ TDes& aFileName, TDes& aExtension )
+ {
+ LOGSTR2( "STSE void CATStorageServerSession::ParseExtension(%S)",
+ &aFileName );
+
+ // Parse current file name
+ TParse parse;
+ // Set up the TParse object
+ parse.Set( aFileName, NULL, NULL );
+
+ // Tests whether an extension is present.
+ if ( parse.ExtPresent() )
+ {
+ // Gets the extension
+ aExtension.Copy( parse.Ext() );
+ // Remove extension from file name
+ TInt pos( aFileName.Find( aExtension ) );
+ aFileName.Delete( pos, aFileName.Length() );
+ LOGSTR3( "STSE > aFileName(%S), aExtension(%S)",
+ &aFileName, &aExtension );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::CheckIfFileAlreadyExist
+// Method is used to check that file exists and is valid.
+// -----------------------------------------------------------------------------
+//
+void CATStorageServerSession::CheckIfFileAlreadyExist(
+ const TDes& aFileName )
+ {
+ LOGSTR2( "STSE void CATStorageServerSession::CheckIfFileAlreadyExist(%S)",
+ &aFileName );
+
+ iError = iFile.Open( iFileServer, aFileName, EFileWrite );
+ LOGSTR2( "STSE > iError(%i)", iError );
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::CheckFileVersion
+// Method is used to check file version.
+// -----------------------------------------------------------------------------
+//
+void CATStorageServerSession::CheckFileVersion(
+ const TDes& aFileName )
+ {
+ LOGSTR2( "STSE void CATStorageServerSession::CheckFileVersion(%S)",
+ &aFileName );
+
+ TBuf8<KVersionStringLength> versionString;
+
+ // Read version information from the beginning of the file (offset 0)
+ iFile.Read( 0, versionString, KVersionStringLength );
+
+ // Delete the existing file, if the version string read from the file does not
+ // match with KDataFileVersion.
+ if ( versionString.Compare( KDataFileVersion ) != 0 )
+ {
+ // Close the existing, opened file, and delete it
+ iFile.Close();
+ iError = iFileServer.Delete( aFileName );
+
+ // If the deletion was successful, set iError = KErrNotFound, so a new
+ // file will be created in the next few lines
+ if ( iError == KErrNone )
+ {
+ iError = KErrNotFound;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::CloseFsAndFile
+// Internally used for closing a handle to the file server and a file
+// -----------------------------------------------------------------------------
+//
+void CATStorageServerSession::CloseFsAndFile()
+ {
+ LOGSTR1( "STSE void CATStorageServerSession::CloseFsAndFile()" );
+
+ // Close the file
+ iFile.Close();
+
+ // Close the server session and return the error code
+ iFileServer.Close();
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::PrintLeaksL()
+// Called internally when a process is closed. Prints possible memory leaks
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::PrintLeaksL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::PrintLeaksL()" );
+
+ // Panic both the client and the server, if this method is called in a wrong
+ // state (logging should be ongoing, and the system should be logging into a file,
+ // not into debug channel)
+ if ( !iLoggingOngoing || iLogOption != EATLogToFile )
+ {
+ PanicClient( EAToolInternalError, aMessage );
+ StorageServerPanic( KCategoryServer, EAToolInternalError );
+ }
+
+ LOGMEM;
+
+ // A pointer to a buffer of call stack's memory addresses
+ CBufFlat* stackBuf = NULL;
+
+ iError = KErrNone;
+
+ TUint32 callStackAddr;
+
+ // Number of leaks
+ TInt leakCount = iLeakArray.Count();
+
+ // Variable for the number of memory addresses in the call stack
+ TInt addrCount( 0 );
+
+ // Buffer position
+ TInt pos( 0 );
+
+ // Go through all the leaks
+ for ( TInt i = 0; i < leakCount; i++ )
+ {
+ pos = 0;
+
+ // Get the call stack buffer of the the leak i.
+ stackBuf = const_cast<CBufFlat*>( iLeakArray[i]->iCallstackBuf );
+
+ // Read the first word of the buffer. This includes the number of
+ // memory addresses stored in the current stackBuf
+ stackBuf->Read( pos, &addrCount, KWordSize );
+
+ // Move the position one word onwards.
+ pos += KWordSize;
+
+ // Construct a buffer for the string to be written into the logging file
+ // because of this memory leak. MEM_LEAK: <Memory address> <Time stamp>
+ // <Allocation size> <Call stack address> <Call stack address> ...
+ HBufC8* leakString =
+ HBufC8::NewL( KMemleakLength +
+ KHexa32Length +
+ KSpaceLength + KHexa64Length +
+ KSpaceLength + KHexa32Length +
+ ( addrCount * (KSpaceLength + KHexa32Length) ) +
+ KNewlineLength
+ );
+
+ // Make a pointer descriptor that points to leakString
+ TPtr8 leakStringPtr( leakString->Des() );
+
+ // Append the tag implying a memory leak line in the data file
+ leakStringPtr.Append( KMemoryLeak );
+
+ // Append the address of the memory leak
+ TUint32 memAddress = iLeakArray[i]->iMemAddress;
+ leakStringPtr.AppendNum( memAddress, EHex );
+
+ // Append the current time in the 64-bit (max 16 characters) hexadecimal text
+ // format
+ leakStringPtr.Append( KSpace );
+ TInt64 allocTime = iLeakArray[i]->iAllocTime;
+ leakStringPtr.AppendNum( allocTime, EHex );
+
+ // Append the size of the allocation in the 32-bit (max 8 characters) hexadecimal
+ // text format.
+ leakStringPtr.Append( KSpace );
+ TInt allocSize = iLeakArray[i]->iAllocSize;
+ leakStringPtr.AppendNum( allocSize, EHex );
+
+ // Go through all call stack's memory addresses associated with
+ // the current memory leak
+ for ( TInt j = 0; j < addrCount; j++ )
+ {
+ // Read the next call stack's memory address stored in the buffer.
+ stackBuf->Read( pos, &callStackAddr, KWordSize );
+
+ // Append the read memory address as a hexadecimal number
+ leakStringPtr.AppendFormat( KHexaNumber, callStackAddr );
+
+ // Move the pos variable one word onwards.
+ pos += KWordSize;
+ }
+
+ leakStringPtr.Append( KNewLine );
+
+ // Set stackBuf to NULL, because it is not used anymore.
+ stackBuf = NULL;
+
+ // Write the constructed string into the data file and return if error
+ iError = iFile.Write( *leakString );
+
+ delete leakString;
+
+ if ( iError != KErrNone )
+ {
+ return iError;
+ }
+
+ } // The outer for
+
+ LOGSTR1( "STSE End of CATStorageServerSession::PrintLeaks()" );
+ LOGMEM;
+
+ // Empty the leak array and delete the referenced objects
+ iLeakArray.ResetAndDestroy();
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::SetLogOption()
+// For setting the logging mode.
+// -----------------------------------------------------------------------------
+//
+void CATStorageServerSession::SetLogOption( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE void CATStorageServerSession::SetLogOption()" );
+
+ // Panic both the client and the server, if this method is called in a wrong
+ // state (logging must not be ongoing when changing the mode of operation).
+ // So, the mode cannot be changed "on the fly".
+ if ( iLoggingOngoing )
+ {
+ PanicClient( EAToolInternalError, aMessage );
+ StorageServerPanic( KCategoryServer, EAToolInternalError );
+ }
+
+ iLogOption = static_cast<TATLogOption>( aMessage.Int3() );
+
+ // The default is EATLogToFile
+ if ( iLogOption == EATUseDefault )
+ {
+ iLogOption = KDefaultLoggingMode;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::LogThroughTrace()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::LogThroughTrace( const TDesC& aLogString ) const
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::LogThroughTrace()" );
+
+ // Return KErrNotSupported, if a logging session is not currently ongoing, or
+ // the logging mode is not EATLogToTrace
+ if ( !iLoggingOngoing || iLogOption != EATLogToTrace)
+ {
+ return KErrNotSupported;
+ }
+
+ RDebug::Print( KTraceMessage, iProcessId, &aLogString );
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::AllocInfoArray
+// -----------------------------------------------------------------------------
+//
+RArray<TAllocInfo>& CATStorageServerSession::AllocInfoArray()
+ {
+ LOGSTR1( "STSE RArray<TAllocInfo>& CATStorageServerSession::AllocInfoArray()" );
+
+ return iAllocInfoArray;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::PanicClient
+// Creates a panic in the associated client's code.
+// -----------------------------------------------------------------------------
+//
+void CATStorageServerSession::PanicClient( TInt aPanic, const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE void CATStorageServerSession::PanicClient()" );
+
+ aMessage.Panic( KCategoryClient, aPanic );
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::GetLoggingFileL()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::GetLoggingFileL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::GetLoggingFileL()" );
+
+ iError = KErrNone;
+
+ // Read the process ID at index 0
+ TUint processId = aMessage.Int0();
+
+ // Get the dynamic process info array
+ RPointerArray<CATDynProcessInfo> dynProcessArray =
+ iStorageServer.DynProcessInfoArray();
+
+ // Construct a CATDynProcessInfo object with the given process ID for searching
+ CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId );
+
+ // Find the index of a CATDynProcessInfo object with the given process ID
+ TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare );
+ TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order );
+ delete dynProcessInfo;
+ dynProcessInfo = NULL;
+
+ // Return, if a process with the requested process ID was not found
+ if ( index == KErrNotFound )
+ {
+ return index;
+ }
+
+ // Otherwise get the wanted dynamic process info
+ dynProcessInfo = dynProcessArray[index];
+
+ // Get the desired process's associated session object
+ CATStorageServerSession* sessionObject = dynProcessInfo->iSessionObject;
+
+ // Write the whole buffer into aMessage at index 1 for the client
+ aMessage.WriteL( 1, sessionObject->iLogFile );
+
+ return iError;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::GetUdebL()
+// -----------------------------------------------------------------------------
+//
+TInt CATStorageServerSession::GetUdebL( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE TInt CATStorageServerSession::GetUdebL()" );
+
+ iError = KErrNone;
+
+ // Read the process ID at index 0
+ TUint processId = aMessage.Int0();
+
+ // Get the dynamic process info array
+ RPointerArray<CATDynProcessInfo> dynProcessArray =
+ iStorageServer.DynProcessInfoArray();
+
+ // Construct a CATDynProcessInfo object with the given process ID for searching
+ CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId );
+
+ // Find the index of a CATDynProcessInfo object with the given process ID
+ TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare );
+ TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order );
+ delete dynProcessInfo;
+ dynProcessInfo = NULL;
+
+ // Return, if a process with the requested process ID was not found
+ if ( index == KErrNotFound )
+ {
+ return index;
+ }
+
+ // Otherwise get the wanted dynamic process info
+ dynProcessInfo = dynProcessArray[index];
+
+ // Get the desired process's associated session object
+ CATStorageServerSession* sessionObject = dynProcessInfo->iSessionObject;
+
+ TBuf8<KMaxVersionName> isUdeb;
+ if ( sessionObject->iIsUdeb == 1 )
+ {
+ isUdeb.Copy( KUdeb() );
+ }
+ else if ( sessionObject->iIsUdeb == 0 )
+ {
+ isUdeb.Copy( KUrel() );
+ }
+ else
+ {
+ return KErrNotFound;
+ }
+ // Write the whole buffer into aMessage at index 1 for the client
+ aMessage.WriteL( 1, isUdeb );
+
+ return iError;
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::SetUdeb()
+// -----------------------------------------------------------------------------
+//
+void CATStorageServerSession::SetUdeb( const RMessage2& aMessage )
+ {
+ LOGSTR1( "STSE void CATStorageServerSession::SetUdeb()" );
+
+ iIsUdeb = aMessage.Int0();
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::LogAbnormalEnd()
+// -----------------------------------------------------------------------------
+//
+void CATStorageServerSession::LogAbnormalEnd()
+ {
+ LOGSTR1( "STSE void CATStorageServerSession::LogAbnormalEnd()" );
+
+ // Get the current universal time
+ TInt64 timeFrom1970( GetTime() );
+
+ switch ( iLogOption )
+ {
+ case EATLogToTrace:
+ {
+ // Make a buffer that will be logged
+ TBuf<KEndAbnormalBufLength> traceBuf;
+
+ // Write the process id to the buffer
+ traceBuf.Format( KProcessEndAbnormalTrace, iProcessId );
+
+ // Append the current time in the 64-bit (max 16 characters) hexadecimal text
+ // format
+ traceBuf.AppendNum( timeFrom1970, EHex );
+
+ // Append a new line
+ traceBuf.Append( KNewLineTrace );
+
+ // Write the buffer into the debug channel
+ RDebug::Print( KTraceMessage, iProcessId, &traceBuf );
+ }
+ break;
+
+ case EATLogToFile:
+ {
+ // Make a buffer that will be logged
+ TBuf8<KEndAbnormalBufLength> loggingBuf;
+
+ // Write the process id to the buffer
+ loggingBuf.Format( KProcessEndAbnormal, iProcessId );
+
+ // Append the current time in the 64-bit (max 16 characters) hexadecimal text
+ // format
+ loggingBuf.AppendNum( timeFrom1970, EHex );
+
+ // Append a new line
+ loggingBuf.Append( KNewLine );
+
+ // Write the buffer into a file (if possible in the current condition)
+ iFile.Write( loggingBuf );
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CATStorageServerSession::GetTime()
+// Get the current universal time
+// -----------------------------------------------------------------------------
+//
+TInt64 CATStorageServerSession::GetTime()
+ {
+ LOGSTR1( "STSE void CATStorageServerSession::GetTime()" );
+
+ // Get the current universal time
+ iTime.UniversalTime();
+
+ // Change the time format that tells the number of microseconds from January First,
+ // 0 AD nominal Gregorian, into a format that tells the number of microseconds from
+ // January First, 1970 AD nominal Gregorian. This is a more generic format and
+ // can be directly exploited by the PC code parsing the data file that this
+ // server generates.
+ return ( iTime.Int64() - iMicroSecondsAt1970 );
+ }
+
+// End of File