memspy/Engine/Source/MemSpyEngineProcessMemoryTracker.cpp
changeset 0 a03f92240627
--- /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" );
+    }
+
+
+