perfsrv/memspy/Console/Source/ConsoleMenu.cpp
changeset 51 98307c651589
parent 20 a71a3e32a2ae
--- /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
+    }
+
+
+