memspy/Engine/Source/MemSpyEngineProcessMemoryTracker.cpp
changeset 0 a03f92240627
equal deleted inserted replaced
-1:000000000000 0:a03f92240627
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 #include <memspy/engine/memspyengineprocessmemorytracker.h>
       
    19 
       
    20 // System includes
       
    21 #include <e32debug.h>
       
    22 
       
    23 // Driver includes
       
    24 #include <memspy/driver/memspydriverclient.h>
       
    25 
       
    26 // User includes
       
    27 #include <memspy/engine/memspyengine.h>
       
    28 #include <memspy/engine/memspyengineutils.h>
       
    29 #include <memspy/engine/memspyengineoutputsink.h>
       
    30 
       
    31 // Constants
       
    32 const TInt KMemSpyNumberOfChangesReceivedProcessNotYetOpen = -1;
       
    33 const TInt KMemSpyNumberOfChangesReceivedProcessNowOpen = 0;
       
    34 
       
    35 
       
    36 CMemSpyEngineProcessMemoryTracker::CMemSpyEngineProcessMemoryTracker( CMemSpyEngine& aEngine, const TProcessId& aProcessId )
       
    37 :   CActive( EPriorityStandard ), iEngine( aEngine ), iProcessId( aProcessId ), iNumberOfChangesReceived( KMemSpyNumberOfChangesReceivedProcessNotYetOpen )
       
    38     {
       
    39     CActiveScheduler::Add( this );
       
    40     }
       
    41 
       
    42 
       
    43 CMemSpyEngineProcessMemoryTracker::~CMemSpyEngineProcessMemoryTracker()
       
    44     {
       
    45     Cancel();
       
    46     
       
    47     // Don't close the process if we didn't successfully open it...
       
    48     if  ( iNumberOfChangesReceived != KMemSpyNumberOfChangesReceivedProcessNotYetOpen )
       
    49         {
       
    50         iEngine.Driver().ProcessInspectionClose( iProcessId );
       
    51         }
       
    52 
       
    53     iObservers.Close();
       
    54     delete iProcessName;
       
    55     }
       
    56 
       
    57 
       
    58 void CMemSpyEngineProcessMemoryTracker::ConstructL()
       
    59     {
       
    60     // Cache name    
       
    61     RProcess process;
       
    62     User::LeaveIfError( iEngine.Driver().OpenProcess( iProcessId, process ) );
       
    63     CleanupClosePushL( process );
       
    64     iProcessName = process.FullName().AllocL();
       
    65     iSID = process.SecureId();
       
    66     CleanupStack::PopAndDestroy( &process );
       
    67 
       
    68     // Indicate that we've opened the process
       
    69     iNumberOfChangesReceived = KMemSpyNumberOfChangesReceivedProcessNowOpen;
       
    70 
       
    71     // Open driver session
       
    72     const TInt error = iEngine.Driver().ProcessInspectionOpen( iProcessId );
       
    73     User::LeaveIfError( error );
       
    74 
       
    75     // Pull out the first change which the driver always prepares for us when
       
    76     // we open an initial connection.
       
    77     TRequestStatus status = KRequestPending;
       
    78     iEngine.Driver().ProcessInspectionRequestChanges( iProcessId, status, iInfoCurrent );
       
    79     User::WaitForRequest( status );
       
    80     
       
    81     // And update our HWM value based upon this initial seed...
       
    82     UpdatePeaks( iInfoCurrent );
       
    83     UpdateHWMIncShared( iInfoCurrent );
       
    84     UpdateHWMExcShared( iInfoCurrent );
       
    85     }
       
    86 
       
    87 
       
    88 CMemSpyEngineProcessMemoryTracker* CMemSpyEngineProcessMemoryTracker::NewLC( CMemSpyEngine& aEngine, const TProcessId& aProcessId )
       
    89     {
       
    90     CMemSpyEngineProcessMemoryTracker* self = new(ELeave) CMemSpyEngineProcessMemoryTracker( aEngine, aProcessId );
       
    91     CleanupStack::PushL( self );
       
    92     self->ConstructL();
       
    93     return self;
       
    94     }
       
    95 
       
    96 
       
    97 EXPORT_C TBool CMemSpyEngineProcessMemoryTracker::AmTracking() const
       
    98     {
       
    99     return iAmTracking;
       
   100     }
       
   101 
       
   102 
       
   103 EXPORT_C void CMemSpyEngineProcessMemoryTracker::StartL()
       
   104     {
       
   105     Cancel();
       
   106     iNumberOfChangesReceived = 0;
       
   107     //
       
   108     iEngine.Driver().ProcessInspectionRequestChanges( iProcessId, iStatus, iInfoCurrent );
       
   109     SetActive();
       
   110     iAmTracking = ETrue;
       
   111     //
       
   112     const TInt count = iObservers.Count();
       
   113     for( TInt i=0; i<count; i++ )
       
   114         {
       
   115         MMemSpyEngineProcessMemoryTrackerObserver* obs = iObservers[ i ];
       
   116         TRAP_IGNORE( obs->HandleMemoryTrackingStartedL() );
       
   117         }
       
   118     }
       
   119 
       
   120 
       
   121 EXPORT_C void CMemSpyEngineProcessMemoryTracker::Stop()
       
   122     {
       
   123     Cancel();
       
   124     //
       
   125     iAmTracking = EFalse;
       
   126     //
       
   127     const TInt count = iObservers.Count();
       
   128     for( TInt i=0; i<count; i++ )
       
   129         {
       
   130         MMemSpyEngineProcessMemoryTrackerObserver* obs = iObservers[ i ];
       
   131         TRAP_IGNORE( obs->HandleMemoryTrackingStoppedL() );
       
   132         }
       
   133     }
       
   134 
       
   135 
       
   136 EXPORT_C void CMemSpyEngineProcessMemoryTracker::AddObserverL( MMemSpyEngineProcessMemoryTrackerObserver& aObserver )
       
   137     {
       
   138     RemoveObserver( aObserver );
       
   139     User::LeaveIfError( iObservers.Append( &aObserver ) );
       
   140     }
       
   141  
       
   142 
       
   143 EXPORT_C void CMemSpyEngineProcessMemoryTracker::RemoveObserver( MMemSpyEngineProcessMemoryTrackerObserver& aObserver )
       
   144     {
       
   145     TInt pos = iObservers.Find( &aObserver );
       
   146     while( pos >= 0 )
       
   147         {
       
   148         iObservers.Remove( pos );
       
   149         pos = iObservers.Find( &aObserver );
       
   150         }
       
   151     }
       
   152 
       
   153 
       
   154 EXPORT_C void CMemSpyEngineProcessMemoryTracker::ResetHWML()
       
   155     {
       
   156     iInfoHWMIncShared.iMemoryStack = 0;
       
   157     iInfoHWMIncShared.iMemoryHeap = 0;
       
   158     iInfoHWMIncShared.iMemoryChunkLocal = 0;
       
   159     iInfoHWMIncShared.iMemoryChunkShared = 0;
       
   160     iInfoHWMIncShared.iMemoryGlobalData = 0;
       
   161     //
       
   162     iInfoHWMExcShared.iMemoryStack = 0;
       
   163     iInfoHWMExcShared.iMemoryHeap = 0;
       
   164     iInfoHWMExcShared.iMemoryChunkLocal = 0;
       
   165     iInfoHWMExcShared.iMemoryChunkShared = 0;
       
   166     iInfoHWMExcShared.iMemoryGlobalData = 0;
       
   167     //
       
   168     const TInt count = iObservers.Count();
       
   169     for( TInt i=0; i<count; i++ )
       
   170         {
       
   171         MMemSpyEngineProcessMemoryTrackerObserver* obs = iObservers[ i ];
       
   172         TRAP_IGNORE( obs->HandleMemoryChangedL( iProcessId, InfoCurrent(), InfoHWMIncShared(), InfoHWMExcShared() ) );
       
   173         }
       
   174     }
       
   175 
       
   176 
       
   177 void CMemSpyEngineProcessMemoryTracker::RunL()
       
   178     {
       
   179     //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::RunL() - START" );
       
   180     ++iNumberOfChangesReceived;
       
   181     
       
   182     // Copy current results and request next event providing the driver didn't
       
   183     // indicate an error (e.g. KErrDied in the case of process termination)
       
   184     TMemSpyDriverProcessInspectionInfo info( iInfoCurrent );
       
   185     if  ( iStatus.Int() >= KErrNone )
       
   186         {
       
   187         iEngine.Driver().ProcessInspectionRequestChanges( iProcessId, iStatus, iInfoCurrent );
       
   188         SetActive();
       
   189         }
       
   190     else
       
   191         {
       
   192         //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::RunL() - iStatus: %d, not requesting further changes...", iStatus.Int() );
       
   193         }
       
   194 
       
   195     // Update stats
       
   196     UpdatePeaks( info );
       
   197     UpdateHWMIncShared( info );
       
   198     UpdateHWMExcShared( info );
       
   199 
       
   200     // Print out change to file/trace
       
   201     //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::RunL() - printing info..." );
       
   202     PrintInfoL( info );
       
   203     //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::RunL() - done printing info" );
       
   204 
       
   205     // Reset peak flags for next cycle
       
   206     iInfoPeaks.ResetPeakFlags();
       
   207 
       
   208     // Notify observers
       
   209     const TInt count = iObservers.Count();
       
   210     for( TInt i=0; i<count; i++ )
       
   211         {
       
   212         MMemSpyEngineProcessMemoryTrackerObserver* obs = iObservers[ i ];
       
   213         TRAP_IGNORE( obs->HandleMemoryChangedL( iProcessId, info, InfoHWMIncShared(), InfoHWMExcShared() ) );
       
   214         }
       
   215 
       
   216     //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::RunL() - END" );
       
   217     }
       
   218 
       
   219 
       
   220 void CMemSpyEngineProcessMemoryTracker::DoCancel()
       
   221     {
       
   222     ////RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::DoCancel() - START - iStatus: %d", iStatus.Int() );
       
   223     iEngine.Driver().ProcessInspectionRequestChangesCancel( iProcessId );
       
   224     ////RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::DoCancel() - END - iStatus: %d", iStatus.Int() );
       
   225     }
       
   226 
       
   227 
       
   228 void CMemSpyEngineProcessMemoryTracker::UpdatePeaks( const TMemSpyDriverProcessInspectionInfo& aLatestInfo )
       
   229     {
       
   230     if  ( aLatestInfo.iMemoryStack > iInfoPeaks.iMemoryStack )
       
   231         {
       
   232         iInfoPeaks.iPeakStack = ETrue;
       
   233         iInfoPeaks.iMemoryStack = aLatestInfo.iMemoryStack;
       
   234         }
       
   235     if  ( aLatestInfo.iMemoryHeap > iInfoPeaks.iMemoryHeap )
       
   236         {
       
   237         iInfoPeaks.iPeakHeap = ETrue;
       
   238         iInfoPeaks.iMemoryHeap = aLatestInfo.iMemoryHeap;
       
   239         }
       
   240     if  ( aLatestInfo.iMemoryChunkLocal > iInfoPeaks.iMemoryChunkLocal )
       
   241         {
       
   242         iInfoPeaks.iPeakChunkLocal = ETrue;
       
   243         iInfoPeaks.iMemoryChunkLocal = aLatestInfo.iMemoryChunkLocal;
       
   244         }
       
   245     if  ( aLatestInfo.iMemoryChunkShared > iInfoPeaks.iMemoryChunkShared )
       
   246         {
       
   247         iInfoPeaks.iPeakChunkShared = ETrue;
       
   248         iInfoPeaks.iMemoryChunkShared = aLatestInfo.iMemoryChunkShared;
       
   249         }
       
   250     if  ( aLatestInfo.iMemoryGlobalData > iInfoPeaks.iMemoryGlobalData )
       
   251         {
       
   252         iInfoPeaks.iPeakGlobalData = ETrue;
       
   253         iInfoPeaks.iMemoryGlobalData = aLatestInfo.iMemoryGlobalData;
       
   254         }
       
   255     }
       
   256 
       
   257 
       
   258 void CMemSpyEngineProcessMemoryTracker::UpdateHWMIncShared( const TMemSpyDriverProcessInspectionInfo& aLatestInfo )
       
   259     {
       
   260     const TUint32 totalCurrent = aLatestInfo.TotalIncShared();
       
   261     const TUint32 totalHWM = iInfoHWMIncShared.TotalIncShared();
       
   262     //
       
   263     if  ( totalCurrent > totalHWM )
       
   264         {
       
   265         // Got new HWM
       
   266         iInfoHWMIncShared = aLatestInfo;
       
   267         }
       
   268     }
       
   269 
       
   270 
       
   271 void CMemSpyEngineProcessMemoryTracker::UpdateHWMExcShared( const TMemSpyDriverProcessInspectionInfo& aLatestInfo )
       
   272     {
       
   273     const TUint32 totalCurrent = aLatestInfo.TotalExcShared();
       
   274     const TUint32 totalHWM = iInfoHWMExcShared.TotalExcShared();
       
   275     //
       
   276     if  ( totalCurrent > totalHWM )
       
   277         {
       
   278         // Got new HWM
       
   279         iInfoHWMExcShared = aLatestInfo;
       
   280         }
       
   281     }
       
   282 
       
   283 
       
   284 void CMemSpyEngineProcessMemoryTracker::PrintInfoL( const TMemSpyDriverProcessInspectionInfo& aInfo )
       
   285     {
       
   286     //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - START" );
       
   287     TBuf<128> timeBuf;
       
   288     TTime time( aInfo.iTime );
       
   289     MemSpyEngineUtils::FormatTimeSimple( timeBuf, time );
       
   290     //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - got time..." );
       
   291 
       
   292     // Output changes
       
   293     const TBool noOverwrite = EFalse;
       
   294     const TBool noTimeStamp = EFalse;
       
   295 
       
   296     // Prepare prefix
       
   297     _LIT( KMemSpyProcessMemoryTrackerPrefix, "[Change %05d] " );
       
   298     TBuf<25> prefixBuf;
       
   299     prefixBuf.Format( KMemSpyProcessMemoryTrackerPrefix, iNumberOfChangesReceived );
       
   300     iEngine.Sink().OutputPrefixSetLC( prefixBuf );
       
   301     //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - set prefix" );
       
   302 
       
   303     // Resume (or create) a data stream
       
   304     _LIT( KMemSpyFolder, "Process Memory Tracking" );
       
   305     _LIT( KMemSpyContext, "Process [0x%08x]" );
       
   306     HBufC* context = HBufC::NewLC( KMaxFileName );
       
   307     TPtr pContext( context->Des() );
       
   308     pContext.Format( KMemSpyContext, (TUint) iSID );
       
   309     iEngine.Sink().DataStreamBeginL( pContext, KMemSpyFolder, KNullDesC, noOverwrite, noTimeStamp );
       
   310     CleanupStack::PopAndDestroy( context );
       
   311     //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - set context" );
       
   312 
       
   313     // Preapre peak characters
       
   314     const TText KItemPeaked     = '*';
       
   315     const TText KItemDidNotPeak = ' ';
       
   316     const TText peakStack       = ( iInfoPeaks.iPeakStack       ? KItemPeaked : KItemDidNotPeak );
       
   317     const TText peakHeap        = ( iInfoPeaks.iPeakHeap        ? KItemPeaked : KItemDidNotPeak );
       
   318     const TText peakChunkLocal  = ( iInfoPeaks.iPeakChunkLocal  ? KItemPeaked : KItemDidNotPeak );
       
   319     const TText peakChunkShared = ( iInfoPeaks.iPeakChunkShared ? KItemPeaked : KItemDidNotPeak );
       
   320     const TText peakGlobalData  = ( iInfoPeaks.iPeakGlobalData  ? KItemPeaked : KItemDidNotPeak );
       
   321 
       
   322     // Write data
       
   323     _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" );
       
   324     HBufC* buf = HBufC::NewLC( 1024 );
       
   325 
       
   326     //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - formatting buffer..." );
       
   327     buf->Des().Format( KMemSpyMemChangeFormat, &timeBuf, (TUint) iProcessId, 
       
   328                                                peakStack, aInfo.iMemoryStack,
       
   329                                                peakHeap, aInfo.iMemoryHeap,
       
   330                                                peakChunkLocal, aInfo.iMemoryChunkLocal,
       
   331                                                peakChunkShared, aInfo.iMemoryChunkShared, 
       
   332                                                peakGlobalData, aInfo.iMemoryGlobalData, 
       
   333                                                aInfo.TotalIncShared(), aInfo.TotalExcShared(), 
       
   334                                                InfoHWMIncShared().TotalIncShared(), InfoHWMExcShared().TotalExcShared(), 
       
   335                                                iProcessName );
       
   336     //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - outputting - 1, sinkType: %d", iEngine.Sink().Type() );
       
   337     //RDebug::Print( _L("%S"), buf );
       
   338     //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - outputting - 2" );
       
   339     iEngine.Sink().OutputLineL( *buf, ETrue );
       
   340     CleanupStack::PopAndDestroy( buf );
       
   341 
       
   342     // End stream
       
   343     //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - ending stream" );
       
   344     iEngine.Sink().DataStreamEndL();
       
   345 
       
   346     // Remove prefix
       
   347     CleanupStack::PopAndDestroy();
       
   348     //RDebug::Printf( "CMemSpyEngineProcessMemoryTracker::PrintInfoL() - END" );
       
   349     }
       
   350 
       
   351 
       
   352