diff -r 185201be11b0 -r 516af714ebb4 perfsrv/memspy/Console/Source/ConsoleMenu.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/perfsrv/memspy/Console/Source/ConsoleMenu.cpp Fri Sep 17 08:38:31 2010 +0300 @@ -0,0 +1,649 @@ +/* +* 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 "ConsoleMenu.h" + +// System includes +#include + +// Engine includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// User includes +#include "ConsoleConstants.h" +#include "ConsoleDWOperation.h" + + +CMemSpyConsoleMenu::CMemSpyConsoleMenu( RMemSpySession& aSession, CConsoleBase& aConsole ) +: CActive( EPriorityHigh ), iSession( aSession ), iConsole( aConsole ), iOutputType(EOutputTypeDebug) + { + CActiveScheduler::Add( this ); + // TODO: iEngine.SetObserver( this ); + } + + +CMemSpyConsoleMenu::~CMemSpyConsoleMenu() + { + Cancel(); + } + + +void CMemSpyConsoleMenu::ConstructL() + { + DrawMenuL(); + WaitForInput(); + } + + +CMemSpyConsoleMenu* CMemSpyConsoleMenu::NewLC( RMemSpySession& aSession, CConsoleBase& aConsole ) + { + CMemSpyConsoleMenu* self = new(ELeave) CMemSpyConsoleMenu( aSession, aConsole ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + + +void CMemSpyConsoleMenu::DrawMenuL() + { + iConsole.ClearScreen(); + + // First line - sink type (defaults to file) + _LIT( KLine1, "1 or T. Toggle output mode between file or trace [%S]" ); + if ( iOutputType == EOutputTypeDebug ) + { + _LIT( KLine1Trace, "Trace" ); + iConsole.Printf( KLine1, &KLine1Trace ); + } + else + { + _LIT( KLine1File, "File" ); + iConsole.Printf( KLine1, &KLine1File ); + } + iConsole.Write( KMemSpyConsoleNewLine ); + + // Kernel heap dump + _LIT( KLine2, "2 or K. Dump kernel heap data" ); + iConsole.Write( KLine2 ); + iConsole.Write( KMemSpyConsoleNewLine ); + + // Kernel heap dump + _LIT( KLine3, "3 or O. Dump kernel object listing" ); + iConsole.Write( KLine3 ); + iConsole.Write( KMemSpyConsoleNewLine ); + + // Heap (CSV) listing + _LIT( KLine4, "4 or H. Heap CSV-information (for all threads)" ); + iConsole.Write( KLine4 ); + iConsole.Write( KMemSpyConsoleNewLine ); + + // Stack (CSV) listing + _LIT( KLine5, "5 or S. Stack CSV-information (for all threads)" ); + iConsole.Write( KLine5 ); + iConsole.Write( KMemSpyConsoleNewLine ); + + // Heap data + _LIT( KLine6, "6 or D. Get heap data for a user-thread" ); + iConsole.Write( KLine6 ); + iConsole.Write( KMemSpyConsoleNewLine ); + + // Heap cell listing + _LIT( KLine7, "7 or L. Get heap cell list for a user-thread" ); + iConsole.Write( KLine7 ); + iConsole.Write( KMemSpyConsoleNewLine ); + + // Exit key + _LIT( KLine8, "8 or X. Exit" ); + iConsole.Write( KLine8 ); + iConsole.Write( KMemSpyConsoleNewLine ); + + // Spacer + iConsole.Write( KMemSpyConsoleNewLine ); + iConsole.Write( KMemSpyConsoleNewLine ); + + // Status message + iStatusMessagePos = iConsole.CursorPos(); + RedrawStatusMessage(); + + // Spacer + iConsole.Write( KMemSpyConsoleNewLine ); + + // Show input prompt. + iCommandPromptPos = iConsole.CursorPos(); + RedrawInputPrompt(); + } + + +void CMemSpyConsoleMenu::WaitForInput() + { + ASSERT( !IsActive() ); + iConsole.Read( iStatus ); + SetActive(); + } + + +void CMemSpyConsoleMenu::RunL() + { + TKeyCode key = iConsole.KeyCode(); + // +#ifdef _DEBUG + RDebug::Printf( "[MCon] CMemSpyConsoleMenu::RunL() - START - key = %d", key ); +#endif + // + if ( key == EKeyEnter || key == KMemSpyUiS60KeyCodeButtonOk || key == KMemSpyUiS60KeyCodeRockerEnter ) + { + TRAP_IGNORE( ProcessCommandBufferL() ); + } + else if ( key == EKeyEscape || key == KMemSpyUiS60KeyCodeButtonCancel ) + { + ClearCommandBuffer(); + RedrawInputPrompt(); + } + else if ( key == EKeyBackspace ) + { + const TInt cmdBufLength = iCommandBuffer.Length(); + if ( cmdBufLength > 0 ) + { + iCommandBuffer.SetLength( cmdBufLength - 1 ); + RedrawInputPrompt(); + } + } + else + { + TChar character( key ); + if ( character.IsPrint() ) + { + if ( iCommandBuffer.Length() < iCommandBuffer.MaxLength() ) + { + iCommandBuffer.Append( TChar( key ) ); + } + + RedrawInputPrompt(); + } + } + + WaitForInput(); + +#ifdef _DEBUG + RDebug::Printf( "[MCon] CMemSpyConsoleMenu::RunL() - END" ); +#endif + } + + +void CMemSpyConsoleMenu::DoCancel() + { + iConsole.ReadCancel(); + } + + +void CMemSpyConsoleMenu::OnCmdSinkTypeToggleL() + { + iOutputType = iOutputType == EOutputTypeFile ? EOutputTypeDebug : EOutputTypeFile; + } + + +void CMemSpyConsoleMenu::OnCmdHeapDataKernelL() + { +#ifdef _DEBUG + RDebug::Printf( "[MCon] CMemSpyConsoleMenu::OnCmdHeapDataKernelL() - START" ); +#endif + + _LIT( KMsg, "Ouputting Kernel data..." ); + RedrawStatusMessage( KMsg ); + + iSession.OutputKernelHeapDataL( iOutputType ); + + RedrawStatusMessage( KNullDesC ); + } + + +void CMemSpyConsoleMenu::OnCmdKernelObjectListingL() + { +#ifdef _DEBUG + RDebug::Printf( "[MCon] CMemSpyConsoleMenu::OnCmdKernelObjectListingL() - START" ); +#endif + + _LIT( KMsg, "Ouputting Kernel Object listing..." ); + RedrawStatusMessage( KMsg ); + // + iSession.OutputKernelObjectsL( iOutputType ); + + RedrawStatusMessage( KNullDesC ); + } + + +void CMemSpyConsoleMenu::OnCmdCSVListingStackL() + { +#ifdef _DEBUG + RDebug::Printf( "[MCon] CMemSpyConsoleMenu::OnCmdCSVListingStackL() - START" ); +#endif + + iSession.OutputCompactStackInfoL( iOutputType ); + } + + +void CMemSpyConsoleMenu::OnCmdCSVListingHeapL() + { +#ifdef _DEBUG + RDebug::Printf( "[MCon] CMemSpyConsoleMenu::OnCmdCSVListingHeapL() - START" ); +#endif + + iSession.OutputCompactHeapInfoL( iOutputType ); + } + + +void CMemSpyConsoleMenu::OnCmdHeapDataUserL() + { +#ifdef _DEBUG + RDebug::Printf( "[MCon] CMemSpyConsoleMenu::OnCmdHeapDataUserL() - START" ); +#endif + + GetProcessName(); + + // Work out what to do. + iCommandBuffer.Trim(); + +#ifdef _DEBUG + RDebug::Print( _L("[MCon] CMemSpyConsoleMenu::OnCmdHeapDataUserL() - requested dump heap for proc: %S"), &iCommandBuffer ); +#endif + + if ( iCommandBuffer.Length() > 0 ) + { + iConsole.Write( KMemSpyConsoleNewLine ); + iConsole.Write( KMemSpyConsoleNewLine ); + // + HBufC* cmdBuf = HBufC::NewLC( KMemSpyMaxInputBufferLength + 10 ); + TPtr pCmdBuf( cmdBuf->Des() ); + pCmdBuf.Copy( iCommandBuffer ); + pCmdBuf.Append( KMemSpyConsoleWildcardCharacter ); + + TInt err; + TProcessId procId; + TRAP(err, procId = iSession.GetProcessIdByNameL(pCmdBuf)); + // + if (err == KErrNone) + { + RArray threads; + + TRAP(err, iSession.GetThreadsL(procId, threads)); + if (err == KErrNone) + { + _LIT( KProcessingRequest, "** Dumping Heap Data for thread: %S" ); + TFullName fullThreadName; + + for( TInt i=0; iName(); + iConsole.Printf( KProcessingRequest, &fullThreadName ); + iConsole.Write( KMemSpyConsoleNewLine ); + // + TRAP_IGNORE( iSession.OutputThreadHeapDataL(iOutputType, thread->Id()) ); + + delete thread; + } + } + } + + CleanupStack::PopAndDestroy( cmdBuf ); + DrawMenuL(); + } + else + { + // Bad user data entry + DrawMenuL(); + _LIT( KInvalidEntry, "*** ERROR - Invalid Command ***" ); + RedrawStatusMessage( KInvalidEntry ); + RedrawInputPrompt(); + } + } + + +void CMemSpyConsoleMenu::OnCmdHeapCellListUserL() + { +#ifdef _DEBUG + RDebug::Printf( "[MCon] CMemSpyConsoleMenu::OnCmdHeapCellListUserL() - START" ); +#endif + + GetProcessName(); + + // Work out what to do. + iCommandBuffer.Trim(); + if ( iCommandBuffer.Length() > 0 ) + { + iConsole.Write( KMemSpyConsoleNewLine ); + iConsole.Write( KMemSpyConsoleNewLine ); + // + HBufC* cmdBuf = HBufC::NewLC( KMemSpyMaxInputBufferLength + 10 ); + TPtr pCmdBuf( cmdBuf->Des() ); + pCmdBuf.Copy( iCommandBuffer ); + pCmdBuf.Append( KMemSpyConsoleWildcardCharacter ); + + TInt err; + TProcessId procId; + TRAP(err, procId = iSession.GetProcessIdByNameL(pCmdBuf)); + // + if (err == KErrNone) + { + RArray threads; + + TRAP(err, iSession.GetThreadsL(procId, threads)); + if (err == KErrNone) + { + _LIT( KProcessingRequest, "** Dumping Heap Cell List for thread: %S" ); + TFullName fullThreadName; + + for( TInt i=0; iName(); + iConsole.Printf( KProcessingRequest, &fullThreadName ); + iConsole.Write( KMemSpyConsoleNewLine ); + // + TRAP_IGNORE( iSession.OutputThreadCellListL(iOutputType, thread->Id()) ); + + delete thread; + } + } + } + + CleanupStack::PopAndDestroy( cmdBuf ); + DrawMenuL(); + } + else + { + // Bad user data entry + DrawMenuL(); + _LIT( KInvalidEntry, "*** ERROR - Invalid Command ***" ); + RedrawStatusMessage( KInvalidEntry ); + RedrawInputPrompt(); + } + } + + +void CMemSpyConsoleMenu::ClearCommandBuffer() + { + iCommandBuffer.Zero(); + } + + +void CMemSpyConsoleMenu::ProcessCommandBufferL() + { + iCommandBuffer.Trim(); + // +#ifdef _DEBUG + RDebug::Print( _L("[MCon] CMemSpyConsoleMenu::ProcessCommandBufferL() - cmd: [%S]"), &iCommandBuffer ); +#endif + // + TBool validCommand = EFalse; + if ( iCommandBuffer.Length() == 1 ) + { + // Reset if not recognised... + validCommand = ETrue; + + const TChar cmd = iCommandBuffer[ 0 ]; + switch( cmd ) + { + case '1': + case 't': + case 'T': + OnCmdSinkTypeToggleL(); + break; + case '2': + case 'k': + case 'K': + OnCmdHeapDataKernelL(); + break; + case '3': + case 'o': + case 'O': + OnCmdKernelObjectListingL(); + break; + case '4': + case 'h': + case 'H': + OnCmdCSVListingHeapL(); + break; + case '5': + case 's': + case 'S': + OnCmdCSVListingStackL(); + break; + case '6': + case 'd': + case 'D': + OnCmdHeapDataUserL(); + break; + case '7': + case 'l': + case 'L': + OnCmdHeapCellListUserL(); + break; + case '8': + case 'x': + case 'X': + CActiveScheduler::Stop(); + return; // NB: avoid redrawing menu when exiting + + default: + validCommand = EFalse; + break; + } + } + // + ClearCommandBuffer(); + // + if ( !validCommand ) + { + _LIT( KInvalidEntry, "*** ERROR - Invalid Command ***" ); + RedrawStatusMessage( KInvalidEntry ); + RedrawInputPrompt(); + } + else + { + DrawMenuL(); + } + +#ifdef _DEBUG + RDebug::Printf( "[MCon] CMemSpyConsoleMenu::ProcessCommandBufferL() - END" ); +#endif + } + + +void CMemSpyConsoleMenu::RedrawInputPrompt() + { + iConsole.SetCursorPosAbs( iCommandPromptPos ); + iConsole.ClearToEndOfLine(); + iConsole.Printf( KMemSpyConsoleInputPrompt, &iCommandBuffer ); + } + + +void CMemSpyConsoleMenu::RedrawStatusMessage() + { + RedrawStatusMessage( KNullDesC ); + } + + +void CMemSpyConsoleMenu::RedrawStatusMessage( const TDesC& aMessage ) + { + iConsole.SetCursorPosAbs( iStatusMessagePos ); + iConsole.ClearToEndOfLine(); + iConsole.Write( aMessage ); + iConsole.Write( KMemSpyConsoleNewLine ); + } + + +void CMemSpyConsoleMenu::GetProcessName() + { + iConsole.ClearScreen(); + + _LIT( KPromptMessage1, "Enter the full or partial process name" ); + iConsole.Write( KPromptMessage1 ); + iConsole.Write( KMemSpyConsoleNewLine ); + _LIT( KPromptMessage2, "of the process that you are interested in." ); + iConsole.Write( KPromptMessage2 ); + iConsole.Write( KMemSpyConsoleNewLine ); + _LIT( KPromptMessage3, "Press \'enter\' when done." ); + iConsole.Write( KPromptMessage3 ); + iConsole.Write( KMemSpyConsoleNewLine ); + // + ClearCommandBuffer(); + iConsole.Write( KMemSpyConsoleNewLine ); + iCommandPromptPos = iConsole.CursorPos(); + RedrawInputPrompt(); + // + TBool done = EFalse; + while( !done ) + { + // Get a key + const TKeyCode key = iConsole.Getch(); + + // Process it +#ifdef _DEBUG + RDebug::Printf( "[MCon] CMemSpyConsoleMenu::OnCmdHeapDataUserL() - START - key = %d", key ); +#endif + // + if ( key == EKeyEnter || key == KMemSpyUiS60KeyCodeButtonOk || key == KMemSpyUiS60KeyCodeRockerEnter ) + { + done = ETrue; + } + else if ( key == EKeyEscape || key == KMemSpyUiS60KeyCodeButtonCancel ) + { + ClearCommandBuffer(); + done = ETrue; + } + else if ( key == EKeyBackspace ) + { + const TInt cmdBufLength = iCommandBuffer.Length(); + if ( cmdBufLength > 0 ) + { + iCommandBuffer.SetLength( cmdBufLength - 1 ); + RedrawInputPrompt(); + } + } + else + { + TChar character( key ); + if ( character.IsPrint() ) + { + if ( iCommandBuffer.Length() < iCommandBuffer.MaxLength() ) + { + iCommandBuffer.Append( TChar( key ) ); + } + + RedrawInputPrompt(); + } + } + } + } + + +void CMemSpyConsoleMenu::HandleMemSpyEngineEventL( MMemSpyEngineObserver::TEvent aEvent, TAny* aContext ) + { + if ( aEvent == MMemSpyEngineObserver::EHandleClientServerOperationRequest ) + { + const TInt function = reinterpret_cast< TInt >( aContext ); + InitiateMemSpyClientServerOperationL( function ); + } + } + + +void CMemSpyConsoleMenu::InitiateMemSpyClientServerOperationL( TInt aOpCode ) + { + // TODO: .... +//#ifdef _DEBUG +// RDebug::Printf( "[MCon] CMemSpyConsoleMenu::InitiateMemSpyClientServerOperationL() - START - aOpCode: %d, iRunningDeviceWideOperation: %d", aOpCode, iRunningDeviceWideOperation ); +//#endif +// // +// if ( aOpCode == EMemSpyClientServerOpExit ) +// { +// // Exit console app UI +// CActiveScheduler::Stop(); +// } +// else +// { +// CMemSpyDeviceWideOperations::TOperation op = CMemSpyDeviceWideOperations::EPerEntityGeneralSummary; +// switch( aOpCode ) +// { +// case EMemSpyClientServerOpSummaryInfo: +// op = CMemSpyDeviceWideOperations::EPerEntityGeneralSummary; +// break; +// case EMemSpyClientServerOpSummaryInfoDetailed: +// op = CMemSpyDeviceWideOperations::EPerEntityGeneralDetailed; +// break; +// // +// case EMemSpyClientServerOpHeapInfo: +// op = CMemSpyDeviceWideOperations::EPerEntityHeapInfo; +// break; +// case EMemSpyClientServerOpHeapCellListing: +// op = CMemSpyDeviceWideOperations::EPerEntityHeapCellListing; +// break; +// case EMemSpyClientServerOpHeapData: +// op = CMemSpyDeviceWideOperations::EPerEntityHeapData; +// break; +// // +// case EMemSpyClientServerOpStackInfo: +// op = CMemSpyDeviceWideOperations::EPerEntityStackInfo; +// break; +// case EMemSpyClientServerOpStackDataUser: +// op = CMemSpyDeviceWideOperations::EPerEntityStackDataUser; +// break; +// case EMemSpyClientServerOpStackDataKernel: +// op = CMemSpyDeviceWideOperations::EPerEntityStackDataKernel; +// break; +// +// // These are not supported by the console UI +// default: +// case EMemSpyClientServerOpBitmapsSave: +// case EMemSpyClientServerOpSendToBackground: +// case EMemSpyClientServerOpBringToForeground: +// User::Leave( KErrNotSupported ); +// break; +// } +// +// if ( iRunningDeviceWideOperation ) +// { +// User::Leave( KErrInUse ); +// } +// else +// { +// iRunningDeviceWideOperation = ETrue; +// TRAP_IGNORE( CMemSpyDeviceWideOperationWaiter::ExecuteLD( iEngine, op ) ); +// iRunningDeviceWideOperation = EFalse; +// } +// } +// +//#ifdef _DEBUG +// RDebug::Printf( "[MCon] CMemSpyConsoleMenu::InitiateMemSpyClientServerOperationL() - END - aOpCode: %d", aOpCode ); +//#endif + } + + +