--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/perfsrv/memspy/Console/Source/ConsoleMenu.cpp Mon Sep 06 15:00:47 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 <e32debug.h>
+
+// Engine includes
+#include <memspyengineclientinterface.h>
+#include <memspy/engine/memspyengine.h>
+#include <memspy/engine/memspyenginehelperheap.h>
+#include <memspy/engine/memspyengineoutputsink.h>
+#include <memspy/engine/memspyenginehelperstack.h>
+#include <memspy/engine/memspyengineobjectthread.h>
+#include <memspy/engine/memspyengineobjectprocess.h>
+#include <memspy/engine/memspydevicewideoperations.h>
+#include <memspy/engine/memspyengineobjectcontainer.h>
+#include <memspy/engine/memspyenginehelperkernelcontainers.h>
+#include <memspy/engine/memspyengineobjectthreadinfoobjects.h>
+#include <memspy/engine/memspyengineobjectthreadinfocontainer.h>
+
+// 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<CMemSpyApiThread*> threads;
+
+ TRAP(err, iSession.GetThreadsL(procId, threads));
+ if (err == KErrNone)
+ {
+ _LIT( KProcessingRequest, "** Dumping Heap Data for thread: %S" );
+ TFullName fullThreadName;
+
+ for( TInt i=0; i<threads.Count(); i++ )
+ {
+ CMemSpyApiThread* thread = threads[i];
+ //
+ fullThreadName = thread->Name();
+ 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<CMemSpyApiThread*> 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; i<threads.Count(); i++ )
+ {
+ CMemSpyApiThread* thread = threads[i];
+ //
+ fullThreadName = thread->Name();
+ 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
+ }
+
+
+