memspy/Engine/Source/DeviceWideOps/MemSpyDeviceWideOperations.cpp
changeset 0 a03f92240627
child 20 ca8a1b6995f6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/memspy/Engine/Source/DeviceWideOps/MemSpyDeviceWideOperations.cpp	Tue Feb 02 01:57:15 2010 +0200
@@ -0,0 +1,448 @@
+/*
+* 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/memspydevicewideoperations.h>
+
+// Engine includes
+#include <memspy/engine/memspyengine.h>
+#include <memspy/engine/memspyengineoutputsink.h>
+#include <memspy/engine/memspyengineobjectthread.h>
+#include <memspy/engine/memspyengineobjectthread.h>
+#include <memspy/engine/memspyengineobjectprocess.h>
+#include <memspy/engine/memspyengineobjectcontainer.h>
+#include <memspy/engine/memspyengineobjectthreadinfocontainer.h>
+#include <memspy/engine/memspyenginehelperchunk.h>
+#include <memspy/engine/memspyenginehelpercodesegment.h>
+#include <memspy/engine/memspyenginehelperheap.h>
+#include <memspy/engine/memspyenginehelperstack.h>
+#include <memspy/engine/memspyenginehelperthread.h>
+#include <memspy/engine/memspyenginehelperprocess.h>
+
+// Driver includes
+#include <memspy/driver/memspydriverenumerationsshared.h>
+
+// Literal constants
+_LIT( KMemSpyUiThreadNameKernel, "Kernel" );
+_LIT( KMemSpyUiCompactHeap, "Compact Heap" );
+_LIT( KMemSpyUiCompactStack, "Compact Stack" );
+
+
+
+CMemSpyDeviceWideOperations::CMemSpyDeviceWideOperations( CMemSpyEngine& aEngine, MMemSpyDeviceWideOperationsObserver& aObserver, TOperation aOperation )
+:   CActive( EPriorityIdle ), iEngine( aEngine ), iObserver( aObserver ), iOperation( aOperation )
+    {
+    CActiveScheduler::Add( this );
+    }
+
+
+EXPORT_C CMemSpyDeviceWideOperations::~CMemSpyDeviceWideOperations()
+    {
+#ifdef _DEBUG
+    RDebug::Printf("CMemSpyDeviceWideOperations::~CMemSpyDeviceWideOperations() - START - iOperationCancelled: %d", iOperationCancelled );
+#endif
+
+    Cancel();
+
+#ifdef _DEBUG
+    RDebug::Printf("CMemSpyDeviceWideOperations::~CMemSpyDeviceWideOperations() - END" );
+#endif
+    }
+
+
+void CMemSpyDeviceWideOperations::ConstructL()
+    {
+#ifdef _DEBUG
+    RDebug::Printf("CMemSpyDeviceWideOperations::ConstructL() - START" );
+#endif
+
+    // Set engine sink time stamp, which will cause the data to be written to a 
+    // uniquely named folder (if we're using a file sink)
+    TTime now;
+    now.HomeTime();
+    iEngine.Sink().DataStreamTimeStampBeginL( now );
+
+    const TInt processCountUser = iEngine.Container().Count();
+    const TInt threadCountUser = TotalNumberOfThreads();
+    const TInt threadCountIncludingKernelSupervisor = threadCountUser + 1; // includes kernel supervisor thread
+
+    // Decide what the maximum progress bar value is...
+    // If we're performing a detailed operation, then skip straight to the end because
+    // the entire operation is performed in one go.
+    iTotalOperationSize = 0;
+    switch( iOperation )
+        {
+    // Only applicable to user-threads
+    default:
+    case EPerEntityGeneralSummary:
+    case EPerEntityGeneralDetailed:
+    case EPerEntityGeneralHandles:
+    case EPerEntityHeapCellListing:
+    case EPerEntityStackInfo:
+    case EPerEntityStackDataUser:
+    case EPerEntityStackDataKernel:
+        iTotalOperationSize = threadCountUser;
+        break;
+    // Applies to user and kernel threads
+    case EPerEntityHeapInfo:
+        iTotalOperationSize = threadCountIncludingKernelSupervisor;
+        break;
+    // Operation is performed in one go
+    case EEntireDeviceHeapInfoCompact:
+    case EEntireDeviceStackInfoCompact:
+        iProcessIndex = processCountUser;
+        iTotalOperationSize = 1;
+        break;
+        }
+
+#ifdef _DEBUG
+    RDebug::Printf("CMemSpyDeviceWideOperations::ConstructL() - op. count: %d", iTotalOperationSize );
+#endif
+
+    // Report total amount of work to observer
+    iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationSized, iTotalOperationSize, KNullDesC );
+
+    // Start the process rolling...
+    CompleteSelf( KErrNone );
+
+    // Indicate that we're now starting the operation
+    iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationStarting, 0, KNullDesC );
+
+#ifdef _DEBUG
+    RDebug::Printf("CMemSpyDeviceWideOperations::ConstructL() - END" );
+#endif
+    }
+
+
+EXPORT_C CMemSpyDeviceWideOperations* CMemSpyDeviceWideOperations::NewL( CMemSpyEngine& aEngine, MMemSpyDeviceWideOperationsObserver& aObserver, TOperation aOperation )
+    {
+    CMemSpyDeviceWideOperations* self = new(ELeave) CMemSpyDeviceWideOperations( aEngine, aObserver, aOperation );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+#ifdef _DEBUG
+    RDebug::Printf("CMemSpyDeviceWideOperations::NewL() - about to pop..." );
+#endif
+    CleanupStack::Pop( self );
+#ifdef _DEBUG
+    RDebug::Printf("CMemSpyDeviceWideOperations::NewL() - popped" );
+#endif
+    return self;
+    }
+
+
+EXPORT_C void CMemSpyDeviceWideOperations::Cancel()
+    {
+#ifdef _DEBUG
+    RDebug::Printf("CMemSpyDeviceWideOperations::Cancel() - START - IsActive: %d", IsActive() );
+#endif
+
+    if  ( IsActive() )
+        {
+        CActive::Cancel();
+        iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationCancelled, 0, KNullDesC );
+        }
+
+#ifdef _DEBUG
+    RDebug::Printf("CMemSpyDeviceWideOperations::Cancel() - END" );
+#endif
+    }
+
+
+EXPORT_C TInt CMemSpyDeviceWideOperations::TotalOperationSize() const
+    {
+#ifdef _DEBUG
+    RDebug::Printf("CMemSpyDeviceWideOperations::TotalOperationSize::Cancel() - ret: %d", iTotalOperationSize );
+#endif
+    return iTotalOperationSize;
+    }
+
+
+void CMemSpyDeviceWideOperations::RunL()
+    {
+#ifdef _DEBUG
+    RDebug::Printf( "CMemSpyDeviceWideOperations::RunL() - START - iStatus: %d, iOperationCancelled: %d, iThreadIndex: %03d, iOperation: %d", iStatus.Int(), iOperationCancelled, iThreadIndex, iOperation );
+#endif
+
+    User::LeaveIfError( iStatus.Int() );
+    User::ResetInactivityTime();
+ 
+    if  ( iOperationCancelled )
+        {
+#ifdef _DEBUG
+        RDebug::Printf( "CMemSpyDeviceWideOperations::RunL() - operation was cancelled whilst running... => Finished" );
+#endif
+        SetFinished();
+        }
+    else
+        {
+        // Get the current process
+        CMemSpyEngineObjectContainer& container = iEngine.Container();
+        const TInt processCount = container.Count();
+        //
+        if  ( iProcessIndex < processCount ) 
+            {
+            PerformNextStepL();
+            }
+        else
+            {
+            // We're done - RunL will not be called again
+            TRAP_IGNORE( PerformFinalOperationL() );
+            SetFinished();
+            }
+        }
+
+#ifdef _DEBUG
+    RDebug::Printf("CMemSpyDeviceWideOperations::RunL() - END" );
+#endif
+    }
+
+
+void CMemSpyDeviceWideOperations::DoCancel()
+    {
+#ifdef _DEBUG
+    RDebug::Printf( "CMemSpyDeviceWideOperations::DoCancel() - START" );
+#endif
+
+    // Nothing to do here
+    iOperationCancelled = ETrue;
+
+#ifdef _DEBUG
+    RDebug::Printf( "CMemSpyDeviceWideOperations::DoCancel() - END" );
+#endif
+    }
+
+
+TInt CMemSpyDeviceWideOperations::RunError( TInt aError )
+    {
+#ifdef _DEBUG
+    RDebug::Printf( "CMemSpyDeviceWideOperations::RunError() - START - iOperationCancelled: %d, aError: %d", iOperationCancelled, aError );
+#endif
+
+    // KErrNotFound can come when trying to suspend a process or thread that no longer exists.
+    if  ( !( aError == KErrDied || aError == KErrNotFound ) )
+        {
+#ifdef _DEBUG
+        RDebug::Printf( "CMemSpyDeviceWideOperations::RunError() - fatal error - cancelling..." );
+#endif       
+        Cancel();
+        }
+    //
+#ifdef _DEBUG
+    RDebug::Printf( "CMemSpyDeviceWideOperations::RunError() - END - iOperationCancelled: %d, aError: %d", iOperationCancelled, aError );
+#endif
+    return KErrNone;
+    }
+
+
+void CMemSpyDeviceWideOperations::CompleteSelf( TInt aError )
+    {
+    TRequestStatus* status = &iStatus;
+    User::RequestComplete( status, aError );
+    SetActive();
+    }
+
+
+void CMemSpyDeviceWideOperations::PerformFinalOperationL()
+    {
+#ifdef _DEBUG
+    RDebug::Printf( "CMemSpyDeviceWideOperations::PerformFinalOperationL() - START" );
+#endif
+
+    iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationCompleting, 0, KNullDesC );
+ 
+    // Carry out any remaining final one-shot operation
+    TPtrC pType( KNullDesC );
+    switch( iOperation )
+        {
+    case EEntireDeviceHeapInfoCompact:
+        // Entire operation is performed here
+        pType.Set( KMemSpyUiCompactHeap );
+        iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationProgressStart, 0, pType );
+        iEngine.HelperHeap().OutputHeapInfoForDeviceL();
+        break;
+    case EEntireDeviceStackInfoCompact:
+        // Entire operation is performed here
+        pType.Set( KMemSpyUiCompactStack );
+        iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationProgressStart, 0, pType );
+        iEngine.HelperStack().OutputStackInfoForDeviceL();
+        break;
+    case EPerEntityHeapInfo:
+        // Complete op by outputting kernel heap summary
+        pType.Set( KMemSpyUiThreadNameKernel );
+        iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationProgressStart, 0, pType );
+        iEngine.HelperHeap().OutputHeapInfoKernelL();
+        break;
+    case EPerEntityHeapData:
+        // Complete op by outputting kernel heap data
+        pType.Set( KMemSpyUiThreadNameKernel );
+        iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationProgressStart, 0, pType );
+        iEngine.HelperHeap().OutputHeapDataKernelL();
+        break;
+    default:
+        break;
+        }
+
+    // Report progress
+    iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationProgressEnd, 1, pType );
+
+#ifdef _DEBUG
+    RDebug::Print( _L("CMemSpyDeviceWideOperations::PerformFinalOperationL() - END - pType: %S"), &pType );
+#endif
+    }
+
+
+void CMemSpyDeviceWideOperations::PerformNextStepL()
+    {
+#ifdef _DEBUG
+    RDebug::Printf( "CMemSpyDeviceWideOperations::PerformNextStepL() - START - iProcessIndex: %d, iThreadIndex: %d", iProcessIndex, iThreadIndex );
+#endif
+
+    // Get the current process
+    CMemSpyEngineObjectContainer& container = iEngine.Container();
+    const TInt processCount = container.Count();
+    CMemSpyProcess& process = container.At( iProcessIndex );
+    const TInt threadCount = process.Count();
+    
+#ifdef _DEBUG
+    RDebug::Printf( "CMemSpyDeviceWideOperations::PerformNextStepL() - threadCount: %d, processCount: %d", threadCount, processCount );
+#endif
+
+    // Get current thread
+    if  ( iThreadIndex < threadCount )
+        {
+        CMemSpyThread& thread = process.At( iThreadIndex++ );
+        const TPtrC pName( thread.Name() );
+    
+#ifdef _DEBUG
+        RDebug::Print( _L("CMemSpyDeviceWideOperations::PerformNextStepL() - thread: %S"), &pName );
+#endif
+
+        // Report progress
+        iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationProgressStart, 0, pName );
+
+        TInt progressAmount = 1;
+        TRAP_IGNORE(
+
+            switch(iOperation)
+                {
+            case EPerEntityGeneralSummary:
+            case EPerEntityGeneralDetailed:
+                if  ( iOperation == EPerEntityGeneralSummary )
+                    {
+                    iEngine.HelperProcess().OutputProcessInfoL( process );
+                    }
+                else
+                    {
+                    iEngine.HelperProcess().OutputProcessInfoDetailedL( process );
+                    }
+
+                // Process specific item, so do this only once per perocess
+                progressAmount = threadCount; 
+                iThreadIndex = threadCount;
+                break;
+            case EPerEntityGeneralHandles:
+                thread.InfoContainerForceSyncronousConstructionL().PrintL();
+                break;
+            case EPerEntityHeapInfo:
+                // Output user thread summary here, kernel thread summary will be
+                // handled when dialog dismissed
+                iEngine.HelperHeap().OutputHeapInfoUserL( thread );
+                break;
+            case EPerEntityHeapCellListing:
+                iEngine.HelperHeap().OutputCellListingUserL( thread );
+                break;
+            case EPerEntityHeapData:
+                iEngine.HelperHeap().OutputHeapDataUserL( thread );
+                break;
+            case EPerEntityStackInfo:
+                iEngine.HelperStack().OutputStackInfoL( thread );
+                break;
+            case EPerEntityStackDataUser:
+                iEngine.HelperStack().OutputStackDataL( thread, EMemSpyDriverDomainUser );
+                break;
+            case EPerEntityStackDataKernel:
+                iEngine.HelperStack().OutputStackDataL( thread, EMemSpyDriverDomainKernel );
+                break;
+            default:
+                break;
+                }
+            );
+
+        // Report progress
+        iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationProgressEnd, progressAmount, pName );
+        }
+    else
+        {
+        // This process is exhausted - move on to the next
+        ++iProcessIndex;
+        iThreadIndex = 0;
+ 
+#ifdef _DEBUG
+        RDebug::Printf( "CMemSpyDeviceWideOperations::PerformNextStepL() - move to next process..." );
+#endif
+        }
+
+    // Request RunL be called again...
+    CompleteSelf( KErrNone );
+
+#ifdef _DEBUG
+    RDebug::Printf( "CMemSpyDeviceWideOperations::PerformNextStepL() - END" );
+#endif
+    }
+
+
+void CMemSpyDeviceWideOperations::SetFinished()
+    {
+#ifdef _DEBUG
+    RDebug::Printf("CMemSpyDeviceWideOperations::SetFinished() - START" );
+#endif
+
+    // Cancel sink time stamp
+    iEngine.Sink().DataStreamTimeStampEnd();
+
+    iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationCompleted, 0, KNullDesC );
+
+#ifdef _DEBUG
+    RDebug::Printf("CMemSpyDeviceWideOperations::SetFinished() - END" );
+#endif
+    }
+
+
+TInt CMemSpyDeviceWideOperations::TotalNumberOfThreads() const
+    {
+    TInt count = 0;
+    //
+    const CMemSpyEngineObjectContainer& container = iEngine.Container();
+    const TInt processCount = container.Count();
+    //
+    for(TInt i=0; i<processCount; i++)
+        {
+        const CMemSpyProcess& process = container.At( i );
+        count += process.Count();
+        }
+    //
+#ifdef _DEBUG
+    RDebug::Printf("CMemSpyDeviceWideOperations::TotalNumberOfThreads() - count: %d", count );
+#endif
+    return count;
+    }
+
+
+
+
+
+
+
+