diff -r 07b41fa8d1dd -r ca8a1b6995f6 memspy/Engine/Source/ClientServer/MemSpyEngineServer.cpp --- a/memspy/Engine/Source/ClientServer/MemSpyEngineServer.cpp Thu Aug 19 11:25:43 2010 +0300 +++ b/memspy/Engine/Source/ClientServer/MemSpyEngineServer.cpp Tue Aug 31 16:45:49 2010 +0300 @@ -19,6 +19,9 @@ // System includes #include +#include +#include +#include // User includes #include @@ -38,7 +41,40 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +inline CShutdown::CShutdown() :CTimer(-1) + { + CActiveScheduler::Add(this); + } + +inline void CShutdown::ConstructL() + { + CTimer::ConstructL(); + } + +inline void CShutdown::Start() + { + After(KMyShutdownDelay); + } + +void CShutdown::RunL() + // + // Initiate server exit when the timer expires + // + { + CActiveScheduler::Stop(); + } CMemSpyEngineServer::CMemSpyEngineServer( CMemSpyEngine& aEngine ) : CServer2( EPriorityNormal ), iEngine( aEngine ) @@ -54,6 +90,10 @@ void CMemSpyEngineServer::ConstructL() { StartL( KMemSpyServerName ); + + iShutdown.ConstructL(); + // ensure that the server still exits even if the 1st client fails to connect + iShutdown.Start(); } @@ -79,6 +119,34 @@ return session; } +void CMemSpyEngineServer::AddSession(TBool aCliRequest) + { + if (aCliRequest) + { + iCliConnected = ETrue; + } + else + { + ++iSessionCount; + } + iShutdown.Cancel(); + } + +void CMemSpyEngineServer::DropSession(TBool aCliRequest) + { + if (!aCliRequest) + { + --iSessionCount; + } + + if (iSessionCount == 0 && !iCliConnected) + { + iShutdown.Start(); + } + } + + + @@ -120,6 +188,8 @@ #endif delete iClientThreadName; + + Server().DropSession(iIsCliRequest); } @@ -138,10 +208,17 @@ iClientThreadId = thread.Id(); CleanupStack::PopAndDestroy( &thread ); - + + const TUid KCliUid3 = { 0x2002129D }; + iIsCliRequest = aMessage.SecureId() == TSecureId(KCliUid3); + TRACE( RDebug::Print( _L("[MemSpy] CMemSpyEngineSession::ConstructL() - NEW SESSION - this: 0x%08x, id: %4d, client: %S"), this, iClientThreadId, iClientThreadName ) ); } +void CMemSpyEngineSession::CreateL() + { + Server().AddSession(iIsCliRequest); + } CMemSpyEngineSession* CMemSpyEngineSession::NewL( CMemSpyEngine& aEngine, const RMessage2& aMessage ) { @@ -162,13 +239,669 @@ { RDebug::Print( _L("[MemSpy] CMemSpyEngineSession::ServiceL() - SERVICE ERROR - this: 0x%08x, fn: %d, err: %d, client: %S"), this, aMessage.Function(), error, iClientThreadName ); } - aMessage.Complete( error ); + + if ((aMessage.Function() & KMemSpyOpFlagsAsyncOperation) == 0 || error != KErrNone) + { + aMessage.Complete( error ); + } TRACE( RDebug::Print( _L("[MemSpy] CMemSpyEngineSession::ServiceL() - END - this: 0x%08x, fn: 0x%08x, id: %4d, client: %S"), this, aMessage.Function(), iClientThreadId, iClientThreadName ) ); } +// --------------------------------------------------------- +// DoServiceL( const RMessage2& aMessage ) +// --------------------------------------------------------- +// +void CMemSpyEngineSession::DoServiceL( const RMessage2& aMessage ) + { + TInt function = aMessage.Function() & KMemSpyOpFlagsTypeMask; + if (function >= EMemSpyClientServerOpMarkerUiFirst && + function < EMemSpyClientServerOpMarkerUiLast) + + DoUiServiceL(aMessage); + else + DoCmdServiceL(aMessage); + } +// --------------------------------------------------------- +// DoUiServiceL( const RMessage2& aMessage ) +// --------------------------------------------------------- +// +void CMemSpyEngineSession::DoUiServiceL( const RMessage2& aMessage ) + { + switch (aMessage.Function() & KMemSpyOpFlagsTypeMask) + { + case EMemSpyClientServerOpGetProcessCount: + { + aMessage.WriteL(0, TPckgBuf(iEngine.Container().Count())); + break; + } + case EMemSpyClientServerOpGetProcesses: + { + CMemSpyEngineObjectContainer& list = iEngine.Container(); + + TPckgBuf a0; + aMessage.ReadL(0, a0); + TInt realCount = Min(a0(), list.Count()); + + for(TInt i=0, offset = 0; i buffer(data); + aMessage.WriteL(1, buffer, offset); + } + + a0 = list.Count(); + aMessage.WriteL(0, a0); -void CMemSpyEngineSession::DoServiceL( const RMessage2& aMessage ) + break; + } + case EMemSpyClienServerOpGetProcessIdByName: + { + TFullName processName; + aMessage.ReadL(0, processName); + + TBool found(EFalse); + + for (TInt i=0; i= 0) + { + found = ETrue; + TPckgBuf procId(process.Id()); + aMessage.WriteL(1, procId); + } + } + + if (!found) + { + User::Leave(KErrNotFound); + } + + break; + } + case EMemSpyClientServerOpProcessSystemPermanentOrCritical: + { + TBool ret = EFalse; + TPckgBuf id; + aMessage.ReadL( 0, id ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess& process = container.ProcessByIdL( id() ); + + if ( process.IsSystemPermanent() || process.IsSystemCritical() ) + { + ret = ETrue; + } + TPckgBuf retBuf( ret ); + aMessage.WriteL( 1, retBuf ); + + break; + } + case EMemSpyClientServerOpEndProcess: + { + TPckgBuf id; + aMessage.ReadL( 0, id ); + TPckgBuf type; + aMessage.ReadL( 1, type ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess& process = container.ProcessByIdL( id() ); + + switch ( type() ) + { + case ETerminate: + { + process.TerminateL(); + break; + } + case EPanic: + { + process.PanicL(); + break; + } + case EKill: + { + process.KillL(); + break; + } + } + break; + } + case EMemSpyClientServerOpSwitchToProcess: + {/* + TInt wgCount; + RWsSession wsSession; + User::LeaveIfError( wsSession.Connect() ); + CleanupClosePushL( wsSession ); + User::LeaveIfError( wgCount = wsSession.NumWindowGroups() ); + RArray wgArray; + CleanupClosePushL( wgArray ); + User::LeaveIfError( wsSession.WindowGroupList( &wgArray ) ); + TApaTask task( wsSession ); + TBool brought( EFalse ); + TInt wgId( KErrNotFound ); + TThreadId threadId; + + TPckgBuf id; + aMessage.ReadL( 0, id ); + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess& process = container.ProcessByIdL( id() ); + + // loop trough threads in a process + for ( TInt i = 0; i < process.MdcaCount(); i++ ) + { + TInt wgCountLocal = wgCount; + + // loop trough all window groups and see if a thread id matches + while( !brought && wgCountLocal-- ) + { + wgId = wgArray[wgCountLocal].iId; + User::LeaveIfError( wsSession.GetWindowGroupClientThreadId( wgId, threadId ) ); + if ( threadId == process.At( i ).Id() ) + { + CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC( wsSession, wgId ); + task.SetWgId( wgId ); + if ( !wgName->Hidden() && task.Exists() ) + { + task.BringToForeground(); + brought = ETrue; + } + CleanupStack::PopAndDestroy( wgName ); + } + } + } + + TPckgBuf ret( brought ); + aMessage.WriteL( 1, ret ); + + break;*/ + } + case EMemSpyClientServerOpGetThreadCount: + { + TPckgBuf pid; + aMessage.ReadL(1, pid); + CMemSpyProcess& process = iEngine.Container().ProcessByIdL(pid()); + aMessage.WriteL(0, TPckgBuf(process.Count())); + break; + } + case EMemSpyClientServerOpGetThreads: + { + TPckgBuf pid; + aMessage.ReadL(2, pid); + + CMemSpyProcess& list = iEngine.Container().ProcessByIdL(pid()); + + TPckgBuf a0; + aMessage.ReadL(0, a0); + TInt realCount = Min(a0(), list.Count()); + + for(TInt i=0, offset = 0; i buffer(data); + aMessage.WriteL(1, buffer, offset); + } + + a0 = list.Count(); + aMessage.WriteL(0, a0); + + break; + } + case EMemSpyClientServerOpSetThreadPriority: + { + TPckgBuf tid; + TPckgBuf priority; + aMessage.ReadL(0, tid); + aMessage.ReadL(1, priority); + + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError(iEngine.Container().ProcessAndThreadByThreadId(tid(), process, thread)); + + if (thread) + { + thread->SetPriorityL(static_cast(priority())); + } + break; + } + case EMemSpyClientServerOpThreadSystemPermanentOrCritical: + { + TPckgBuf id; + aMessage.ReadL( 0, id ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id(), process, thread ) ); + + TBool ret = thread && ( thread->IsSystemPermanent() || thread->IsSystemCritical() ); + + TPckgBuf retBuf( ret ); + aMessage.WriteL( 1, retBuf ); + + break; + } + case EMemSpyClientServerOpEndThread: + { + TPckgBuf id; + aMessage.ReadL( 0, id ); + TPckgBuf type; + aMessage.ReadL( 1, type ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id(), process, thread ) ); + + if( thread ) + { + switch ( type() ) + { + case ETerminate: + { + thread->TerminateL(); + break; + } + case EPanic: + { + thread->PanicL(); + break; + } + case EKill: + { + thread->KillL(); + break; + } + } + } + break; + } + case EMemSpyClientServerOpSwitchToThread: + { + TInt wgCount; + RWsSession wsSession; + User::LeaveIfError( wsSession.Connect() ); + CleanupClosePushL( wsSession ); + User::LeaveIfError( wgCount = wsSession.NumWindowGroups() ); + RArray wgArray; + CleanupClosePushL( wgArray ); + User::LeaveIfError( wsSession.WindowGroupList( &wgArray ) ); + TApaTask task( wsSession ); + TBool brought( EFalse ); + TInt wgId( KErrNotFound ); + TThreadId threadId; + + TPckgBuf id; + aMessage.ReadL( 0, id ); + + // loop trough all window groups and see if a thread id matches + while( !brought && wgCount-- ) + { + wgId = wgArray[wgCount].iId; + User::LeaveIfError( wsSession.GetWindowGroupClientThreadId( wgId, threadId ) ); + if ( threadId == id() ) + { + CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC( wsSession, wgId ); + task.SetWgId( wgId ); + if ( !wgName->Hidden() && task.Exists() ) + { + task.BringToForeground(); + brought = ETrue; + } + CleanupStack::PopAndDestroy( wgName ); + } + } + TPckgBuf ret( brought ); + aMessage.WriteL( 1, ret ); + + break; + } + case EMemSpyClientServerOpGetInfoItemType: + { + + TPckgBuf index; + aMessage.ReadL( 0, index ); + TPckgBuf id; + aMessage.ReadL( 1, id); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; //not needed + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id(), process, thread ) ); + + CMemSpyThreadInfoContainer& threadInfoContainer = thread->InfoContainerForceSyncronousConstructionL(); + TMemSpyThreadInfoItemType retType = threadInfoContainer.Item( index() ).Type(); + + TPckgBuf ret( retType ); + aMessage.WriteL( 2, ret ); + + break; + } + case EMemSpyClientServerOpGetThreadInfoItemsCount: + { + TPckgBuf id; + aMessage.ReadL( 0, id ); + TPckgBuf type; + aMessage.ReadL( 1, type ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + + container.ProcessAndThreadByThreadId( id(), process, thread ); + + CMemSpyThreadInfoContainer& threadInfoContainer = thread->InfoContainerForceSyncronousConstructionL(); + + CMemSpyThreadInfoItemBase& threadInfoItemBase = threadInfoContainer.Item( type() ); + + TInt count = threadInfoItemBase.MdcaCount(); + TPckgBuf tempret( count ); + aMessage.WriteL( 2, tempret ); + + break; + } + case EMemSpyClientServerOpGetThreadInfoItems: + { + TPckgBuf count; + aMessage.ReadL( 0, count ); + TPckgBuf id; + aMessage.ReadL( 1, id ); + TPckgBuf type; + aMessage.ReadL( 2, type ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id() , process, thread ) ); + + CMemSpyThreadInfoContainer& threadInfoContainer = thread->InfoContainerForceSyncronousConstructionL(); + + CMemSpyThreadInfoItemBase& threadInfoItemBase = threadInfoContainer.Item( type() ); //get ThreadInfoItemBaseByType + + TInt itemCount = Min(count(), threadInfoItemBase.MdcaCount()); + + for( TInt i=0, offset = 0; i buffer(data); + aMessage.WriteL(3, buffer, offset); + } + aMessage.WriteL(0, count); + + break; + } + // --- KernelObjects related functions --- + case EMemSpyClientServerOpGetKernelObjectCount: + { + TInt iCount = EMemSpyDriverContainerTypeLast - EMemSpyDriverContainerTypeFirst; + TPckgBuf ret( iCount ); + aMessage.WriteL(0, ret); + break; + } + case EMemSpyClientServerOpGetKernelObjects: + { + TPckgBuf count; + aMessage.ReadL(0, count); + + CMemSpyEngineGenericKernelObjectContainer* model = iEngine.HelperKernelContainers().ObjectsAllL(); //contains all the objects + CleanupStack::PushL( model ); + + for( TInt i=0, offset = 0; iAt(i).Name().Mid(1)); + TInt tabPos = name.Locate('\t'); + if (tabPos != KErrNotFound) + name.Set(name.Left(tabPos)); + + data.iName.Copy(name); + data.iType = model->At(i).Type(); + data.iCount = model->At(i).Count(); + data.iSize = model->At(i).Count() * model->At(i).Count(); + + TPckgBuf buffer(data); + aMessage.WriteL(1, buffer, offset); + } + aMessage.WriteL(0, count); + CleanupStack::PopAndDestroy( model ); + break; + } + case EMemSpyClientServerOpGetKernelObjectItemCount: + { + TPckgBuf tempType; + aMessage.ReadL(1, tempType); //get type of kernel object + TMemSpyDriverContainerType type = tempType(); + + CMemSpyEngineHelperKernelContainers& kernelContainerManager = iEngine.HelperKernelContainers(); + CMemSpyEngineGenericKernelObjectList* iObjectList = kernelContainerManager.ObjectsForSpecificContainerL( type ); + CleanupStack::PushL( iObjectList ); + + TInt count = iObjectList->Count(); + TPckgBuf ret( count ); + aMessage.WriteL( 0, ret ); + + CleanupStack::PopAndDestroy( iObjectList ); + break; + } + case EMemSpyClientServerOpGetKernelObjectItems: + { + TPckgBuf count; + TPckgBuf tempType; + aMessage.ReadL( 0, count ); //get count of items + aMessage.ReadL(1, tempType); //get type of kernel object + TInt c = count(); + + CMemSpyEngineHelperKernelContainers& kernelContainerManager = iEngine.HelperKernelContainers(); + CMemSpyEngineGenericKernelObjectList* iObjectList = kernelContainerManager.ObjectsForSpecificContainerL( tempType() ); + CleanupStack::PushL( iObjectList ); + + for( TInt i=0, offset = 0; iAt( i ); + + TPckgBuf buffer(data); + aMessage.WriteL(2, buffer, offset); + } + + CleanupStack::PopAndDestroy( iObjectList ); + break; + } + + case EMemSpyClientServerOpOutputAllContainerContents: + { + CMemSpyEngineHelperKernelContainers& kernelContainerManager = iEngine.HelperKernelContainers(); + CMemSpyEngineGenericKernelObjectContainer* model = kernelContainerManager.ObjectsAllL(); + + model->OutputL( iEngine.Sink() ); + + break; + } + + case EMemSpyClientServerOpDumpKernelHeap: + { + iEngine.HelperHeap().OutputHeapDataKernelL(); + + break; + } + + case EMemSpyClientServerOpOutputInfoHandles: + { + TPckgBuf id; + aMessage.ReadL(0, id); + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id() , process, thread ) ); + + CMemSpyThreadInfoContainer& threadInfoContainer = thread->InfoContainerForceSyncronousConstructionL(); + + threadInfoContainer.PrintL(); + + break; + } + + case EMemSpyClientServerOpOutputAOList: + { + TPckgBuf id; + TPckgBuf type; + aMessage.ReadL(0, id); + aMessage.ReadL(1, type); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id() , process, thread ) ); + + CMemSpyThreadInfoContainer& threadInfoContainer = thread->InfoContainerForceSyncronousConstructionL(); + + CMemSpyThreadInfoItemBase* threadInfoItem = &threadInfoContainer.Item( type() ); + + CMemSpyThreadInfoActiveObjects* activeObjectArray = static_cast< CMemSpyThreadInfoActiveObjects* >( threadInfoItem ); + + // Begin a new data stream + _LIT( KMemSpyContext, "Active Object List - " ); + _LIT( KMemSpyFolder, "Active Objects" ); + iEngine.Sink().DataStreamBeginL( KMemSpyContext, KMemSpyFolder ); + + // Set prefix for overall listing + iEngine.Sink().OutputPrefixSetLC( KMemSpyContext ); + + // Create header + CMemSpyEngineActiveObjectArray::OutputDataColumnsL( iEngine ); + + // List items + const TInt count = activeObjectArray->Array().Count(); + for(TInt i=0; iArray().At( i ); + // + object.OutputDataL( iEngine ); + } + + // Tidy up + CleanupStack::PopAndDestroy(); // prefix + + // End data stream + iEngine.Sink().DataStreamEndL(); + + break; + } + + // --- Kernel Heap related functions --- + case EMemSpyClientServerOpGetHeap: + { + TMemSpyHeapInfo heapInfo; + iEngine.HelperHeap().GetHeapInfoKernelL( heapInfo ); + TMemSpyHeapData data = iEngine.HelperHeap().NewHeapRawInfo( heapInfo ); + + TPckgBuf buffer(data); + aMessage.WriteL(0, buffer); + + break; + } + + case EMemSpyClientServerOpGetMemoryTrackingCycleCount: + aMessage.WriteL(0, TPckgBuf(iEngine.HelperSysMemTracker().CompletedCycles().Count())); + break; + + case EMemSpyClientServerOpGetMemoryTrackingCycles: + { + const RPointerArray& list = iEngine.HelperSysMemTracker().CompletedCycles(); + + TPckgBuf a0; + aMessage.ReadL(0, a0); + TInt realCount = Min(a0(), list.Count()); + + for (TInt i=0, offset = 0; iCycleNumber(); + data.iCaption.Copy(list[i]->Caption().Left(KMaxFullName)); + data.iTime = list[i]->Time(); + data.iFreeMemory = list[i]->MemoryFree(); + data.iMemoryDelta = list[i]->MemoryDelta(); + data.iPreviousCycleDiff = list[i]->MemoryFreePreviousCycle(); + + TPckgBuf buffer(data); + aMessage.WriteL(1, buffer, offset); + } + + a0 = list.Count(); + aMessage.WriteL(0, a0); + + break; + } + case EMemSpyClientServerOpIsSwmtRunning: + { + TPckgBuf running(iEngine.HelperSysMemTracker().IsActive()); + aMessage.WriteL(0, running); + break; + } + + + case EMemSpyClientServerOpNotifyDeviceWideOperationProgress: + { + if (!Server().CurrentOperationTracker()) + { + User::Leave(KErrNotReady); + } + + Server().CurrentOperationTracker()->AddNotificationL(aMessage); + break; + } + + case EMemSpyClientServerOpCancelDeviceWideOperation: + if (!Server().CurrentOperationTracker()) + { + User::Leave(KErrNotReady); + } + + Server().CurrentOperationTracker()->Cancel(); + break; + } + } + +// --------------------------------------------------------- +// DoCmdServiceL( const RMessage2& aMessage ) +// --------------------------------------------------------- +// +void CMemSpyEngineSession::DoCmdServiceL( const RMessage2& aMessage ) { TInt error = KErrNone; @@ -382,16 +1115,31 @@ void CMemSpyEngineSession::HandleThreadAgnosticOpL( TInt aFunction, const RMessage2& aMessage ) { TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - START" ) ); + // if ( aFunction == EMemSpyClientServerOpHeapInfoCompact ) { TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpHeapInfoCompact") ); - iEngine.HelperHeap().OutputHeapInfoForDeviceL(); + if (aMessage.Function() & KMemSpyOpFlagsAsyncOperation) + { + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EEntireDeviceHeapInfoCompact, aMessage); + } + else + { + iEngine.HelperHeap().OutputHeapInfoForDeviceL(); + } } else if ( aFunction == EMemSpyClientServerOpStackInfoCompact ) { TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpStackInfoCompact") ); - iEngine.HelperStack().OutputStackInfoForDeviceL(); + if (aMessage.Function() & KMemSpyOpFlagsAsyncOperation) + { + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EEntireDeviceStackInfoCompact, aMessage); + } + else + { + iEngine.HelperStack().OutputStackInfoForDeviceL(); + } } else if ( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingTimerStart ) { @@ -481,12 +1229,31 @@ else if ( aFunction == EMemSpyClientServerOpSwitchOutputSinkTrace ) { TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSwitchOutputSinkTrace") ); - iEngine.InstallSinkL( ESinkTypeDebug ); + iEngine.InstallDebugSinkL(); } else if ( aFunction == EMemSpyClientServerOpSwitchOutputSinkFile ) { TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSwitchOutputSinkFile") ); - iEngine.InstallSinkL( ESinkTypeFile ); + // Read file name from message. + TFileName fileName; + RBuf buf; + buf.CleanupClosePushL(); + + TInt len = aMessage.GetDesLength( 0 ); + if ( len > 0 ) + { + buf.CreateL( len ); + aMessage.ReadL( 0, buf, 0 ); + + iEngine.InstallFileSinkL( buf ); + } + else + { + iEngine.InstallFileSinkL( KNullDesC ); + } + + CleanupStack::PopAndDestroy( &buf ); + } else if ( aFunction == EMemSpyClientServerOpEnumerateKernelContainer ) { @@ -517,6 +1284,46 @@ TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpDisableAknIconCache") ); iEngine.HelperRAM().SetAknIconCacheStatusL( EFalse ); } + else if ( aFunction == EMemSpyClientServerOpSummaryInfo ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSummaryInfo") ); + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EPerEntityGeneralSummary, aMessage); + } + else if ( aFunction == EMemSpyClientServerOpSummaryInfoDetailed ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSummaryInfoDetailed") ); + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EPerEntityGeneralDetailed, aMessage); + } + else if ( aFunction == EMemSpyClientServerOpHeapInfo ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpHeapInfo") ); + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EPerEntityHeapInfo, aMessage); + } + else if ( aFunction == EMemSpyClientServerOpHeapCellListing ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpHeapCellListing") ); + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EPerEntityHeapCellListing, aMessage); + } + else if ( aFunction == EMemSpyClientServerOpHeapData ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpHeapData") ); + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EPerEntityHeapData, aMessage); + } + else if ( aFunction == EMemSpyClientServerOpStackInfo ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpStackInfo") ); + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EPerEntityStackInfo, aMessage); + } + else if ( aFunction == EMemSpyClientServerOpStackDataUser ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpStackDataUser") ); + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EPerEntityStackDataUser, aMessage); + } + else if ( aFunction == EMemSpyClientServerOpStackDataKernel ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpStackDataKernel") ); + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EPerEntityStackDataKernel, aMessage); + } else { TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - [device-wide operation] => invoking UI") ); @@ -526,7 +1333,108 @@ TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - END" ) ); } +void CMemSpyEngineSession::StartDeviceWideOperationL(CMemSpyDeviceWideOperations::TOperation aOperation, const RMessage2& aMessage) + { + if (Server().CurrentOperationTracker()) + { + User::Leave(KErrInUse); + } + + Server().SetCurrentOperationTracker(CMemSpyDwOperationTracker::NewL(aOperation, aMessage, Server())); + } + + + + + +CMemSpyDwOperationTracker* CMemSpyDwOperationTracker::NewL(CMemSpyDeviceWideOperations::TOperation aOperation, + const RMessage2& aOperationMessage, CMemSpyEngineServer& aServer) + { + CMemSpyDwOperationTracker* self = new (ELeave) CMemSpyDwOperationTracker(aOperationMessage, aServer); + CleanupStack::PushL( self ); + self->ConstructL(aOperation); + CleanupStack::Pop( self ); + return self; + } + +CMemSpyDwOperationTracker::~CMemSpyDwOperationTracker() + { + delete iOperation; + delete iPendingNotifications; + } + +CMemSpyDwOperationTracker::CMemSpyDwOperationTracker(const RMessage2& aOperationMessage, CMemSpyEngineServer& aServer) : + iOperationMessage(aOperationMessage), + iServer(aServer), + iPendingNotifications(0), + iOperation(0), + iProgress(0) + { + } + + +void CMemSpyDwOperationTracker::ConstructL(CMemSpyDeviceWideOperations::TOperation aOperation) + { + iPendingNotifications = new (ELeave) CArrayFixFlat(3); + iOperation = CMemSpyDeviceWideOperations::NewL(iServer.Engine(), *this, aOperation); + } + +void CMemSpyDwOperationTracker::AddNotificationL(const RMessage2& aMessage) + { + iPendingNotifications->AppendL(aMessage); + } + +void CMemSpyDwOperationTracker::Cancel() + { + iOperation->Cancel(); + } + +void CMemSpyDwOperationTracker::HandleDeviceWideOperationEvent(TEvent aEvent, TInt aParam1, const TDesC& aParam2) + { + switch( aEvent ) + { + case MMemSpyDeviceWideOperationsObserver::EOperationCompleted: + case MMemSpyDeviceWideOperationsObserver::EOperationCancelled: + iServer.SetCurrentOperationTracker(0); + + for (TInt i=0; iCount(); i++) + { + iPendingNotifications->At(i).Complete(KErrCancel); + } + + if (iOperationMessage.Function() & KMemSpyOpFlagsAsyncOperation) + { + iOperationMessage.Complete( + aEvent == MMemSpyDeviceWideOperationsObserver::EOperationCompleted ? KErrNone : KErrCancel); + } + + iPendingNotifications->Reset(); + + delete this; + break; + + case MMemSpyDeviceWideOperationsObserver::EOperationProgressEnd: + { + iProgress += aParam1; + for (TInt i=0; iCount(); i++) + { + TInt err; + TRAP(err, iPendingNotifications->At(i).WriteL(0, TPckgBuf( iProgress * 100 / iOperation->TotalOperationSize() ))); + TRAP(err, iPendingNotifications->At(i).WriteL(1, aParam2)); + if (err != KErrNone) + { + // TODO: iPendingProgressNotifications->At(i).Panic() + } + iPendingNotifications->At(i).Complete(KErrNone); + } + iPendingNotifications->Reset(); + break; + } + + } + + }