diff -r 0d72cc2a29a3 -r 7259cf1302ad memspy/Engine/Source/ClientServer/MemSpyEngineServer.cpp --- a/memspy/Engine/Source/ClientServer/MemSpyEngineServer.cpp Wed Jun 23 19:59:05 2010 +0300 +++ b/memspy/Engine/Source/ClientServer/MemSpyEngineServer.cpp Tue Jul 06 16:05:13 2010 +0300 @@ -42,12 +42,39 @@ #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 ) @@ -63,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(); } @@ -88,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(); + } + } + + + @@ -129,6 +188,8 @@ #endif delete iClientThreadName; + + Server().DropSession(iIsCliRequest); } @@ -147,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 ) { @@ -171,7 +239,11 @@ { 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 ) ); } @@ -190,7 +262,6 @@ else DoCmdServiceL(aMessage); } - // --------------------------------------------------------- // DoUiServiceL( const RMessage2& aMessage ) // --------------------------------------------------------- @@ -216,8 +287,15 @@ { CMemSpyProcess& process = iEngine.Container().At(i); TMemSpyProcessData data; + data.iIsDead = process.IsDead(); data.iId = process.Id(); - data.iName.Copy(process.Name()); + data.iName.Copy(process.Name().Left(KMaxFullName)); + data.iThreadCount = process.Count(); + data.iPriority = process.Priority(); + data.iExitType = process.ExitType(); + data.iExitReason = process.ExitReason(); + data.iExitCategory = process.ExitCategory(); + data.iSID = process.SID(); TPckgBuf buffer(data); aMessage.WriteL(1, buffer, offset); @@ -225,7 +303,7 @@ a0 = list.Count(); aMessage.WriteL(0, a0); - + break; } case EMemSpyClienServerOpGetProcessIdByName: @@ -262,8 +340,6 @@ CMemSpyEngineObjectContainer& container = iEngine.Container(); CMemSpyProcess& process = container.ProcessByIdL( id() ); - process.Open(); - if ( process.IsSystemPermanent() || process.IsSystemCritical() ) { ret = ETrue; @@ -357,9 +433,7 @@ TPckgBuf pid; aMessage.ReadL(1, pid); CMemSpyProcess& process = iEngine.Container().ProcessByIdL(pid()); - process.Open(); aMessage.WriteL(0, TPckgBuf(process.Count())); - process.Close(); break; } case EMemSpyClientServerOpGetThreads: @@ -368,33 +442,27 @@ aMessage.ReadL(2, pid); CMemSpyProcess& list = iEngine.Container().ProcessByIdL(pid()); - list.Open(); 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); - - thread.Close(); } a0 = list.Count(); aMessage.WriteL(0, a0); - - list.Close(); - + break; } case EMemSpyClientServerOpSetThreadPriority: @@ -410,15 +478,12 @@ if (thread) { - thread->Open(); - thread->SetPriorityL(static_cast(priority())); - thread->Close(); + thread->SetPriorityL(static_cast(priority())); } break; } case EMemSpyClientServerOpThreadSystemPermanentOrCritical: { - TBool ret = EFalse; TPckgBuf id; aMessage.ReadL( 0, id ); @@ -427,16 +492,8 @@ CMemSpyThread* thread = NULL; User::LeaveIfError( container.ProcessAndThreadByThreadId( id(), process, thread ) ); - if ( thread ) - { - thread->Open(); - - if ( thread->IsSystemPermanent() || thread->IsSystemCritical() ) - { - ret = ETrue; - } - thread->Close(); - } + TBool ret = thread && ( thread->IsSystemPermanent() || thread->IsSystemCritical() ); + TPckgBuf retBuf( ret ); aMessage.WriteL( 1, retBuf ); @@ -519,6 +576,7 @@ } case EMemSpyClientServerOpGetInfoItemType: { + TPckgBuf index; aMessage.ReadL( 0, index ); TPckgBuf id; @@ -529,22 +587,16 @@ CMemSpyThread* thread = NULL; User::LeaveIfError( container.ProcessAndThreadByThreadId( id(), process, thread ) ); - thread->Open(); - process->Open(); - CMemSpyThreadInfoContainer& threadInfoContainer = thread->InfoContainerForceSyncronousConstructionL(); TMemSpyThreadInfoItemType retType = threadInfoContainer.Item( index() ).Type(); TPckgBuf ret( retType ); aMessage.WriteL( 2, ret ); - thread->Close(); - process->Close(); - break; } case EMemSpyClientServerOpGetThreadInfoItemsCount: - { + { TPckgBuf id; aMessage.ReadL( 0, id ); TPckgBuf type; @@ -556,9 +608,6 @@ container.ProcessAndThreadByThreadId( id(), process, thread ); - thread->Open(); - process->Open(); - CMemSpyThreadInfoContainer& threadInfoContainer = thread->InfoContainerForceSyncronousConstructionL(); CMemSpyThreadInfoItemBase& threadInfoItemBase = threadInfoContainer.Item( type() ); @@ -566,10 +615,7 @@ TInt count = threadInfoItemBase.MdcaCount(); TPckgBuf tempret( count ); aMessage.WriteL( 2, tempret ); - - thread->Close(); - process->Close(); - + break; } case EMemSpyClientServerOpGetThreadInfoItems: @@ -586,15 +632,12 @@ CMemSpyThread* thread = NULL; User::LeaveIfError( container.ProcessAndThreadByThreadId( id() , process, thread ) ); - process->Open(); - thread->Open(); - 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); - - thread->Close(); - process->Close(); + aMessage.WriteL(0, count); break; } @@ -651,7 +691,7 @@ 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); } @@ -683,7 +723,7 @@ 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 ); @@ -701,6 +741,87 @@ 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: { @@ -713,6 +834,66 @@ 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; } } @@ -934,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 ) { @@ -1033,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 ) { @@ -1069,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") ); @@ -1078,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; + } + + } + + }