--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/memspy/Engine/Source/MemSpyEngineProcessMemoryTracker.cpp Tue Feb 02 01:57:15 2010 +0200
@@ -0,0 +1,352 @@
+/*
+* 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:
+*
+*/
+
+#include <memspy/engine/memspyengineprocessmemorytracker.h>
+
+// System includes
+#include <e32debug.h>
+
+// Driver includes
+#include <memspy/driver/memspydriverclient.h>
+
+// User includes
+#include <memspy/engine/memspyengine.h>
+#include <memspy/engine/memspyengineutils.h>
+#include <memspy/engine/memspyengineoutputsink.h>
+
+// Constants
+const TInt KMemSpyNumberOfChangesReceivedProcessNotYetOpen = -1;
+const TInt KMemSpyNumberOfChangesReceivedProcessNowOpen = 0;
+
+
+CMemSpyEngineProcessMemoryTracker::CMemSpyEngineProcessMemoryTracker( CMemSpyEngine& aEngine, const TProcessId& aProcessId )
+: CActive( EPriorityStandard ), iEngine( aEngine ), iProcessId( aProcessId ), iNumberOfChangesReceived( KMemSpyNumberOfChangesReceivedProcessNotYetOpen )
+ {
+ CActiveScheduler::Add( this );
+ }
+
+
+CMemSpyEngineProcessMemoryTracker::~CMemSpyEngineProcessMemoryTracker()
+ {
+ Cancel();
+
+ // Don't close the process if we didn't successfully open it...
+ if ( iNumberOfChangesReceived != KMemSpyNumberOfChangesReceivedProcessNotYetOpen )
+ {
+ iEngine.Driver().ProcessInspectionClose( iProcessId );
+ }
+
+ iObservers.Close();
+ delete iProcessName;
+ }
+
+
+void CMemSpyEngineProcessMemoryTracker::ConstructL()
+ {
+ // Cache name
+ RProcess process;
+ User::LeaveIfError( iEngine.Driver().OpenProcess( iProcessId, process ) );
+ CleanupClosePushL( process );
+ iProcessName = process.FullName().AllocL();
+ iSID = process.SecureId();
+ CleanupStack::PopAndDestroy( &process );
+
+ // Indicate that we've opened the process
+ iNumberOfChangesReceived = KMemSpyNumberOfChangesReceivedProcessNowOpen;
+
+ // Open driver session
+ const TInt error = iEngine.Driver().ProcessInspectionOpen( iProcessId );
+ User::LeaveIfError( error );
+
+ // Pull out the first change which the driver always prepares for us when
+ // we open an initial connection.
+ TRequestStatus status = KRequestPending;
+ iEngine.Driver().ProcessInspectionRequestChanges( iProcessId, status, iInfoCurrent );
+ User::WaitForRequest( status );
+
+ // And update our HWM value based upon this initial seed...
+ UpdatePeaks( iInfoCurrent );
+ UpdateHWMIncShared( iInfoCurrent );
+ UpdateHWMExcShared( iInfoCurrent );
+ }
+
+
+CMemSpyEngineProcessMemoryTracker* CMemSpyEngineProcessMemoryTracker::NewLC( CMemSpyEngine& aEngine, const TProcessId& aProcessId )
+ {
+ CMemSpyEngineProcessMemoryTracker* self = new(ELeave) CMemSpyEngineProcessMemoryTracker( aEngine, aProcessId );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+
+EXPORT_C TBool CMemSpyEngineProcessMemoryTracker::AmTracking() const
+ {
+ return iAmTracking;
+ }
+
+
+EXPORT_C void CMemSpyEngineProcessMemoryTracker::StartL()
+ {
+ Cancel();
+ iNumberOfChangesReceived = 0;
+ //
+ iEngine.Driver().ProcessInspectionRequestChanges( iProcessId, iStatus, iInfoCurrent );
+ SetActive();
+ iAmTracking = ETrue;
+ //
+ const TInt count = iObservers.Count();
+ for( TInt i=0; i<count; i++ )
+ {
+ MMemSpyEngineProcessMemoryTrackerObserver* obs = iObservers[ i ];
+ TRAP_IGNORE( obs->HandleMemoryTrackingStartedL() );
+ }
+ }
+
+
+EXPORT_C void CMemSpyEngineProcessMemoryTracker::Stop()
+ {
+ Cancel();
+ //
+ iAmTracking = EFalse;
+ //
+ const TInt count = iObservers.Count();
+ for( TInt i=0; i<count; i++ )
+ {
+ MMemSpyEngineProcessMemoryTrackerObserver* obs = iObservers[ i ];
+ TRAP_IGNORE( obs->HandleMemoryTrackingStoppedL() );
+ }
+ }
+
+
+EXPORT_C void CMemSpyEngineProcessMemoryTracker::AddObserverL( MMemSpyEngineProcessMemoryTrackerObserver& aObserver )
+ {
+ RemoveObserver( aObserver );
+ User::LeaveIfError( iObservers.Append( &aObserver ) );
+ }
+
+
+EXPORT_C void CMemSpyEngineProcessMemoryTracker::RemoveObserver( MMemSpyEngineProcessMemoryTrackerObserver& aObserver )
+ {
+ TInt pos = iObservers.Find( &aObserver );
+ while( pos >= 0 )
+ {
+ iObservers.Remove( pos );
+ pos = iObservers.Find( &aObserver );
+ }
+ }
+
+
+EXPORT_C void CMemSpyEngineProcessMemoryTracker::ResetHWML()
+ {
+ iInfoHWMIncShared.iMemoryStack = 0;
+ iInfoHWMIncShared.iMemoryHeap = 0;
+ iInfoHWMIncShared.iMemoryChunkLocal = 0;
+ iInfoHWMIncShared.iMemoryChunkShared = 0;
+ iInfoHWMIncShared.iMemoryGlobalData = 0;
+ //
+ iInfoHWMExcShared.iMemoryStack = 0;
+ iInfoHWMExcShared.iMemoryHeap = 0;
+ iInfoHWMExcShared.iMemoryChunkLocal = 0;
+ iInfoHWMExcShared.iMemoryChunkShared = 0;
+ iInfoHWMExcShared.iMemoryGlobalData = 0;
+ //
+ const TInt count = iObservers.Count();
+ for( TInt i=0; i<count; i++ )
+ {
+ MMemSpyEngineProcessMemoryTrackerObserver* obs = iObservers[ i ];
+ TRAP_IGNORE( obs->HandleMemoryChangedL( iProcessId, InfoCurrent(), InfoHWMIncShared(), InfoHWMExcShared() ) );
+ }
+ }
+
+
+void CMemSpyEngineProcessMemoryTracker::RunL()
+ {
+ //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::RunL() - START" );
+ ++iNumberOfChangesReceived;
+
+ // Copy current results and request next event providing the driver didn't
+ // indicate an error (e.g. KErrDied in the case of process termination)
+ TMemSpyDriverProcessInspectionInfo info( iInfoCurrent );
+ if ( iStatus.Int() >= KErrNone )
+ {
+ iEngine.Driver().ProcessInspectionRequestChanges( iProcessId, iStatus, iInfoCurrent );
+ SetActive();
+ }
+ else
+ {
+ //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::RunL() - iStatus: %d, not requesting further changes...", iStatus.Int() );
+ }
+
+ // Update stats
+ UpdatePeaks( info );
+ UpdateHWMIncShared( info );
+ UpdateHWMExcShared( info );
+
+ // Print out change to file/trace
+ //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::RunL() - printing info..." );
+ PrintInfoL( info );
+ //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::RunL() - done printing info" );
+
+ // Reset peak flags for next cycle
+ iInfoPeaks.ResetPeakFlags();
+
+ // Notify observers
+ const TInt count = iObservers.Count();
+ for( TInt i=0; i<count; i++ )
+ {
+ MMemSpyEngineProcessMemoryTrackerObserver* obs = iObservers[ i ];
+ TRAP_IGNORE( obs->HandleMemoryChangedL( iProcessId, info, InfoHWMIncShared(), InfoHWMExcShared() ) );
+ }
+
+ //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::RunL() - END" );
+ }
+
+
+void CMemSpyEngineProcessMemoryTracker::DoCancel()
+ {
+ ////RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::DoCancel() - START - iStatus: %d", iStatus.Int() );
+ iEngine.Driver().ProcessInspectionRequestChangesCancel( iProcessId );
+ ////RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::DoCancel() - END - iStatus: %d", iStatus.Int() );
+ }
+
+
+void CMemSpyEngineProcessMemoryTracker::UpdatePeaks( const TMemSpyDriverProcessInspectionInfo& aLatestInfo )
+ {
+ if ( aLatestInfo.iMemoryStack > iInfoPeaks.iMemoryStack )
+ {
+ iInfoPeaks.iPeakStack = ETrue;
+ iInfoPeaks.iMemoryStack = aLatestInfo.iMemoryStack;
+ }
+ if ( aLatestInfo.iMemoryHeap > iInfoPeaks.iMemoryHeap )
+ {
+ iInfoPeaks.iPeakHeap = ETrue;
+ iInfoPeaks.iMemoryHeap = aLatestInfo.iMemoryHeap;
+ }
+ if ( aLatestInfo.iMemoryChunkLocal > iInfoPeaks.iMemoryChunkLocal )
+ {
+ iInfoPeaks.iPeakChunkLocal = ETrue;
+ iInfoPeaks.iMemoryChunkLocal = aLatestInfo.iMemoryChunkLocal;
+ }
+ if ( aLatestInfo.iMemoryChunkShared > iInfoPeaks.iMemoryChunkShared )
+ {
+ iInfoPeaks.iPeakChunkShared = ETrue;
+ iInfoPeaks.iMemoryChunkShared = aLatestInfo.iMemoryChunkShared;
+ }
+ if ( aLatestInfo.iMemoryGlobalData > iInfoPeaks.iMemoryGlobalData )
+ {
+ iInfoPeaks.iPeakGlobalData = ETrue;
+ iInfoPeaks.iMemoryGlobalData = aLatestInfo.iMemoryGlobalData;
+ }
+ }
+
+
+void CMemSpyEngineProcessMemoryTracker::UpdateHWMIncShared( const TMemSpyDriverProcessInspectionInfo& aLatestInfo )
+ {
+ const TUint32 totalCurrent = aLatestInfo.TotalIncShared();
+ const TUint32 totalHWM = iInfoHWMIncShared.TotalIncShared();
+ //
+ if ( totalCurrent > totalHWM )
+ {
+ // Got new HWM
+ iInfoHWMIncShared = aLatestInfo;
+ }
+ }
+
+
+void CMemSpyEngineProcessMemoryTracker::UpdateHWMExcShared( const TMemSpyDriverProcessInspectionInfo& aLatestInfo )
+ {
+ const TUint32 totalCurrent = aLatestInfo.TotalExcShared();
+ const TUint32 totalHWM = iInfoHWMExcShared.TotalExcShared();
+ //
+ if ( totalCurrent > totalHWM )
+ {
+ // Got new HWM
+ iInfoHWMExcShared = aLatestInfo;
+ }
+ }
+
+
+void CMemSpyEngineProcessMemoryTracker::PrintInfoL( const TMemSpyDriverProcessInspectionInfo& aInfo )
+ {
+ //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - START" );
+ TBuf<128> timeBuf;
+ TTime time( aInfo.iTime );
+ MemSpyEngineUtils::FormatTimeSimple( timeBuf, time );
+ //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - got time..." );
+
+ // Output changes
+ const TBool noOverwrite = EFalse;
+ const TBool noTimeStamp = EFalse;
+
+ // Prepare prefix
+ _LIT( KMemSpyProcessMemoryTrackerPrefix, "[Change %05d] " );
+ TBuf<25> prefixBuf;
+ prefixBuf.Format( KMemSpyProcessMemoryTrackerPrefix, iNumberOfChangesReceived );
+ iEngine.Sink().OutputPrefixSetLC( prefixBuf );
+ //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - set prefix" );
+
+ // Resume (or create) a data stream
+ _LIT( KMemSpyFolder, "Process Memory Tracking" );
+ _LIT( KMemSpyContext, "Process [0x%08x]" );
+ HBufC* context = HBufC::NewLC( KMaxFileName );
+ TPtr pContext( context->Des() );
+ pContext.Format( KMemSpyContext, (TUint) iSID );
+ iEngine.Sink().DataStreamBeginL( pContext, KMemSpyFolder, KNullDesC, noOverwrite, noTimeStamp );
+ CleanupStack::PopAndDestroy( context );
+ //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - set context" );
+
+ // Preapre peak characters
+ const TText KItemPeaked = '*';
+ const TText KItemDidNotPeak = ' ';
+ const TText peakStack = ( iInfoPeaks.iPeakStack ? KItemPeaked : KItemDidNotPeak );
+ const TText peakHeap = ( iInfoPeaks.iPeakHeap ? KItemPeaked : KItemDidNotPeak );
+ const TText peakChunkLocal = ( iInfoPeaks.iPeakChunkLocal ? KItemPeaked : KItemDidNotPeak );
+ const TText peakChunkShared = ( iInfoPeaks.iPeakChunkShared ? KItemPeaked : KItemDidNotPeak );
+ const TText peakGlobalData = ( iInfoPeaks.iPeakGlobalData ? KItemPeaked : KItemDidNotPeak );
+
+ // Write data
+ _LIT( KMemSpyMemChangeFormat, "%S - pID: 0x%04x, stack[%c]: %6d, heap[%c]: %10d, local[%c]: %10d, shared[%c]: %10d, globalD[%c]: %10d, totalC: [%10d/%10d], totalHWM: [%10d/%10d] %S" );
+ HBufC* buf = HBufC::NewLC( 1024 );
+
+ //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - formatting buffer..." );
+ buf->Des().Format( KMemSpyMemChangeFormat, &timeBuf, (TUint) iProcessId,
+ peakStack, aInfo.iMemoryStack,
+ peakHeap, aInfo.iMemoryHeap,
+ peakChunkLocal, aInfo.iMemoryChunkLocal,
+ peakChunkShared, aInfo.iMemoryChunkShared,
+ peakGlobalData, aInfo.iMemoryGlobalData,
+ aInfo.TotalIncShared(), aInfo.TotalExcShared(),
+ InfoHWMIncShared().TotalIncShared(), InfoHWMExcShared().TotalExcShared(),
+ iProcessName );
+ //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - outputting - 1, sinkType: %d", iEngine.Sink().Type() );
+ //RDebug::Print( _L("%S"), buf );
+ //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - outputting - 2" );
+ iEngine.Sink().OutputLineL( *buf, ETrue );
+ CleanupStack::PopAndDestroy( buf );
+
+ // End stream
+ //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - ending stream" );
+ iEngine.Sink().DataStreamEndL();
+
+ // Remove prefix
+ CleanupStack::PopAndDestroy();
+ //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - END" );
+ }
+
+
+