diff -r 000000000000 -r a03f92240627 memspy/Engine/Source/DeviceWideOps/MemSpyDeviceWideOperations.cpp --- /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 + +// Engine includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Driver includes +#include + +// 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