memspy/Engine/Source/ThreadAndProcess/MemSpyEngineObjectContainer.cpp
changeset 0 a03f92240627
child 20 ca8a1b6995f6
equal deleted inserted replaced
-1:000000000000 0:a03f92240627
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 #include <memspy/engine/memspyengineobjectcontainer.h>
       
    19 
       
    20 // System includes
       
    21 #include <e32svr.h>
       
    22 
       
    23 // Driver includes
       
    24 #include <memspy/driver/memspydriverclient.h>
       
    25 
       
    26 // User includes
       
    27 #include <memspy/engine/memspyengine.h>
       
    28 #include <memspy/engine/memspyengineutils.h>
       
    29 #include <memspy/engine/memspyengineobjectprocess.h>
       
    30 #include <memspy/engine/memspyengineobjectthread.h>
       
    31 #include <memspy/engine/memspyenginehelperheap.h>
       
    32 #include <memspy/engine/memspyenginehelperstack.h>
       
    33 #include <memspy/engine/memspyenginehelpercodesegment.h>
       
    34 
       
    35 // Literal constants
       
    36 _LIT(KProcessFilter, "*");
       
    37 _LIT(KEKernProcessName, "ekern");
       
    38 
       
    39 
       
    40 CMemSpyEngineObjectContainer::CMemSpyEngineObjectContainer( CMemSpyEngine& aEngine )
       
    41 :   iEngine( aEngine )
       
    42     {
       
    43 	/*
       
    44     TFindProcess procFinder( KProcessFilter );
       
    45     TFullName nextMatch;
       
    46     //
       
    47     while( procFinder.Next( nextMatch ) == KErrNone )
       
    48         {
       
    49         _LIT(KProcListing, "%S");
       
    50         RDebug::Print(KProcListing, &nextMatch);
       
    51 
       
    52 
       
    53         _LIT(KFindMask, "*");
       
    54         nextMatch += KFindMask;
       
    55         //
       
    56         TFindThread threadFinder( nextMatch );
       
    57         //
       
    58         while( threadFinder.Next( nextMatch ) == KErrNone )
       
    59             {
       
    60             _LIT(KThreadListing, "+--- %S");
       
    61             RDebug::Print(KThreadListing, &nextMatch);
       
    62             }
       
    63         }
       
    64 	*/
       
    65     }
       
    66 
       
    67 
       
    68 CMemSpyEngineObjectContainer::~CMemSpyEngineObjectContainer()
       
    69     {
       
    70     DestroyProcesses( iGarbage );
       
    71     DestroyProcesses( iProcesses );
       
    72     delete iUndertaker;
       
    73     delete iMidwife;
       
    74     delete iIdleNotifyContainerChanged;
       
    75     }
       
    76 
       
    77 
       
    78 void CMemSpyEngineObjectContainer::ConstructL( const TDesC& aFilter )
       
    79     {
       
    80     iUndertaker = CMemSpyEngineUndertaker::NewL( iEngine.Driver() );
       
    81     iUndertaker->AddObserverL( *this );
       
    82     //
       
    83     iMidwife = CMemSpyEngineMidwife::NewL( iEngine.Driver() );
       
    84     iMidwife->AddObserverL( *this );
       
    85     //
       
    86     iIdleNotifyContainerChanged = CIdle::NewL( CActive::EPriorityIdle );
       
    87     //
       
    88     RefreshL( aFilter );
       
    89     }
       
    90 
       
    91 
       
    92 CMemSpyEngineObjectContainer* CMemSpyEngineObjectContainer::NewL( CMemSpyEngine& aEngine )
       
    93     {
       
    94     return NewL( KProcessFilter, aEngine );
       
    95     }
       
    96 
       
    97 
       
    98 CMemSpyEngineObjectContainer* CMemSpyEngineObjectContainer::NewL( const TDesC& aFilter, CMemSpyEngine& aEngine )
       
    99     {
       
   100     CMemSpyEngineObjectContainer* self = new(ELeave) CMemSpyEngineObjectContainer( aEngine );
       
   101     CleanupStack::PushL( self );
       
   102     self->ConstructL( aFilter );
       
   103     CleanupStack::Pop( self );
       
   104     return self;
       
   105     }
       
   106 
       
   107 
       
   108 EXPORT_C TInt CMemSpyEngineObjectContainer::Count() const
       
   109     {
       
   110     return iProcesses.Count();
       
   111     }
       
   112 
       
   113 
       
   114 EXPORT_C TInt CMemSpyEngineObjectContainer::CountAll() const
       
   115     {
       
   116     TInt ret = 0;
       
   117     //
       
   118     const TInt count = iProcesses.Count();
       
   119     for( TInt i=0; i<count; i++ )
       
   120         {
       
   121         CMemSpyProcess* process = iProcesses[ i ];
       
   122         ret += process->Count();
       
   123         }
       
   124     //
       
   125     return ret;
       
   126     }
       
   127 
       
   128 
       
   129 EXPORT_C void CMemSpyEngineObjectContainer::RefreshL()
       
   130     {
       
   131     RefreshL( KProcessFilter );
       
   132     }
       
   133 
       
   134 
       
   135 EXPORT_C void CMemSpyEngineObjectContainer::RefreshL( const TDesC& aFilter )
       
   136     {
       
   137     LocateProcessesL( aFilter );
       
   138     }
       
   139 
       
   140 
       
   141 EXPORT_C CMemSpyProcess& CMemSpyEngineObjectContainer::At( TInt aIndex ) const
       
   142     {
       
   143     CMemSpyProcess* ret = iProcesses[ aIndex ];
       
   144     return *ret;
       
   145     }
       
   146 
       
   147 
       
   148 EXPORT_C CMemSpyProcess& CMemSpyEngineObjectContainer::ProcessByIdL( TProcessId aId ) const
       
   149     {
       
   150     CMemSpyProcess* ret = NULL;
       
   151     //
       
   152     const TInt count = iProcesses.Count();
       
   153     for( TInt i=0; i<count; i++ )
       
   154         {
       
   155         CMemSpyProcess* process = iProcesses[ i ];
       
   156         if  ( process->Id() == aId )
       
   157             {
       
   158             ret = process;
       
   159             break;
       
   160             }
       
   161         }
       
   162     //
       
   163     if  ( ret == NULL )
       
   164         {
       
   165         User::Leave( KErrNotFound );
       
   166         }
       
   167     //
       
   168     return *ret;
       
   169     }
       
   170 
       
   171 
       
   172 EXPORT_C TInt CMemSpyEngineObjectContainer::ProcessIndexById( TProcessId aId ) const
       
   173     {
       
   174     TInt index = KErrNotFound;
       
   175     //
       
   176     const TInt count = iProcesses.Count();
       
   177     for( TInt i=0; i<count; i++ )
       
   178         {
       
   179         const CMemSpyProcess* process = iProcesses[ i ];
       
   180         if  ( process->Id() == aId )
       
   181             {
       
   182             index = i;
       
   183             break;
       
   184             }
       
   185         }
       
   186     //
       
   187     return index;
       
   188     }
       
   189 
       
   190 
       
   191 EXPORT_C TInt CMemSpyEngineObjectContainer::ProcessAndThreadByThreadId( TThreadId aTid, CMemSpyProcess*& aProcess, CMemSpyThread*& aThread ) const
       
   192     {
       
   193     aProcess = NULL;
       
   194     aThread = NULL;
       
   195     TInt error = KErrNotFound;
       
   196     //
       
   197     const TInt count = iProcesses.Count();
       
   198     for( TInt i=0; i<count; i++ )
       
   199         {
       
   200         CMemSpyProcess* process = iProcesses[ i ];
       
   201 
       
   202         // Check whether this process contains the thread we are looking for...
       
   203         const TInt index = process->ThreadIndexById( aTid );
       
   204         if  ( index >= 0 )
       
   205             {
       
   206             // Found it
       
   207             aProcess = process;
       
   208             aThread = &process->At( index );
       
   209             error = KErrNone;
       
   210             break;
       
   211             }
       
   212         }
       
   213     //
       
   214     if  ( error == KErrNotFound )
       
   215         {
       
   216         CMemSpyEngineObjectContainer* self = const_cast< CMemSpyEngineObjectContainer* >( this );
       
   217         TRAP( error, self->TryToCreateProcessAndThreadL( aTid, aProcess, aThread ) );
       
   218         }
       
   219     //
       
   220     return error;
       
   221     }
       
   222 
       
   223 
       
   224 EXPORT_C TInt CMemSpyEngineObjectContainer::ProcessAndThreadByFullName( const TDesC& aFullName, CMemSpyProcess*& aProcess, CMemSpyThread*& aThread ) const
       
   225     {
       
   226     aProcess = NULL;
       
   227     aThread = NULL;
       
   228     TInt error = KErrNotFound;
       
   229     //
       
   230     const TInt count = iProcesses.Count();
       
   231     for( TInt i=0; i<count && aThread == NULL; i++ )
       
   232         {
       
   233         CMemSpyProcess& process = *iProcesses[ i ];
       
   234         const TInt threadCount = process.Count();
       
   235         //
       
   236         for(TInt j=0; j<threadCount; j++)
       
   237             {
       
   238             CMemSpyThread& thread = process.At( j );
       
   239             const TFullName threadName( thread.FullName() );
       
   240             //
       
   241             if  ( threadName.CompareF( aFullName ) == 0 )
       
   242                 {
       
   243                 // Found it
       
   244                 aProcess = &process;
       
   245                 aThread = &thread;
       
   246                 error = KErrNone;
       
   247                 break;
       
   248                 }
       
   249             }
       
   250 
       
   251         }
       
   252     //
       
   253     if  ( error == KErrNotFound )
       
   254         {
       
   255         // NB: cannot use driver API as we must open thread by name, and that only supports opening
       
   256         // by id.
       
   257         RThread thread;
       
   258         error = thread.Open( aFullName );
       
   259         if ( error == KErrNone )
       
   260             {
       
   261             const TThreadId threadId = thread.Id();
       
   262             thread.Close();
       
   263 
       
   264             CMemSpyEngineObjectContainer* self = const_cast< CMemSpyEngineObjectContainer* >( this );
       
   265             TRAP( error, self->TryToCreateProcessAndThreadL( threadId, aProcess, aThread ) );
       
   266             }
       
   267         }
       
   268     //
       
   269     return error;
       
   270     }
       
   271 
       
   272 
       
   273 EXPORT_C TInt CMemSpyEngineObjectContainer::ProcessAndThreadByPartialName( const TDesC& aPartialName, CMemSpyProcess*& aProcess, CMemSpyThread*& aThread ) const
       
   274     {
       
   275     aProcess = NULL;
       
   276     aThread = NULL;
       
   277     TInt error = KErrNotFound;
       
   278     //
       
   279     const TInt count = iProcesses.Count();
       
   280     for( TInt i=0; i<count && aThread == NULL; i++ )
       
   281         {
       
   282         CMemSpyProcess& process = *iProcesses[ i ];
       
   283         const TInt threadCount = process.Count();
       
   284         //
       
   285         for(TInt j=0; j<threadCount; j++)
       
   286             {
       
   287             CMemSpyThread& thread = process.At( j );
       
   288             const TFullName threadName( thread.FullName() );
       
   289             //
       
   290             if  ( threadName.FindF( aPartialName ) >= 0 )
       
   291                 {
       
   292                 // Found it
       
   293                 aProcess = &process;
       
   294                 aThread = &thread;
       
   295                 error = KErrNone;
       
   296                 break;
       
   297                 }
       
   298             }
       
   299 
       
   300         }
       
   301     //
       
   302     return error;
       
   303     }
       
   304 
       
   305 
       
   306 EXPORT_C TBool CMemSpyEngineObjectContainer::IsAlive( TProcessId aPid ) const
       
   307     {
       
   308     const TInt processIndex = ProcessIndexById( aPid );
       
   309     return ( processIndex >= 0 );
       
   310     }
       
   311 
       
   312 
       
   313 EXPORT_C TBool CMemSpyEngineObjectContainer::IsAlive( TProcessId aPid, TThreadId aTid ) const
       
   314     {
       
   315     TBool isAlive = IsAlive( aPid );
       
   316     if  ( isAlive )
       
   317         {
       
   318         const TInt processIndex = ProcessIndexById( aPid );
       
   319         const CMemSpyProcess& process = At( processIndex );
       
   320 
       
   321         // Check whether the thread is alive
       
   322         isAlive = ( process.ThreadIndexById( aTid ) >= 0 );
       
   323         }
       
   324     //
       
   325     return isAlive;
       
   326     }
       
   327 
       
   328 
       
   329 EXPORT_C TInt CMemSpyEngineObjectContainer::MdcaCount() const
       
   330     {
       
   331     return iProcesses.Count();
       
   332     }
       
   333 
       
   334 
       
   335 EXPORT_C TPtrC CMemSpyEngineObjectContainer::MdcaPoint(TInt aIndex) const
       
   336     {
       
   337     const CMemSpyProcess* process = iProcesses[ aIndex ];
       
   338     return TPtrC( process->NameForListBox() );
       
   339     }
       
   340 
       
   341 
       
   342 void CMemSpyEngineObjectContainer::LocateProcessesL( const TDesC& aFilter )
       
   343     {
       
   344 #ifdef _DEBUG
       
   345     RDebug::Printf( "CMemSpyEngineObjectContainer::LocateProcessesL() - START" );
       
   346 #endif
       
   347     DestroyProcesses( iProcesses );
       
   348     //
       
   349     const TProcessId myProcessId = RProcess().Id();
       
   350 	//
       
   351     TFindProcess finder( aFilter );
       
   352     TFullName nextMatch;
       
   353     //
       
   354     while( finder.Next( nextMatch ) == KErrNone )
       
   355         {
       
   356         if  ( nextMatch.FindF(KEKernProcessName) == KErrNotFound )
       
   357             {
       
   358 #ifdef _DEBUG
       
   359             RDebug::Print(_L( "CMemSpyEngineObjectContainer::LocateProcessesL() - found Proc: %S"), &nextMatch );
       
   360 #endif
       
   361 
       
   362             RProcess p;
       
   363             const TInt r = p.Open( nextMatch );
       
   364             TProcessId processId( KNullProcessId );
       
   365             if ( r == KErrNone )
       
   366                 {
       
   367                 processId = p.Id();
       
   368                 }
       
   369             p.Close();
       
   370 
       
   371 #ifdef _DEBUG
       
   372             RDebug::Printf( "CMemSpyEngineObjectContainer::LocateProcessesL() - open err: %d", r );
       
   373 #endif
       
   374 
       
   375             if  ( r == KErrNone )
       
   376                 {
       
   377                 if  ( processId != myProcessId )
       
   378                     {
       
   379                     TRAPD( err, CreateProcessL( processId ) );
       
   380 #ifdef _DEBUG
       
   381                     RDebug::Printf( "CMemSpyEngineObjectContainer::LocateProcessesL() - CreateProcessL err: %d", err );
       
   382 #endif
       
   383                     err = err;
       
   384                     }
       
   385                 }
       
   386             }
       
   387         }
       
   388     //
       
   389     SortByName();
       
   390 
       
   391 #ifdef _DEBUG
       
   392     RDebug::Printf( "CMemSpyEngineObjectContainer::LocateProcessesL() - END" );
       
   393 #endif
       
   394     }
       
   395 
       
   396 
       
   397 CMemSpyProcess* CMemSpyEngineObjectContainer::CreateProcessL( const TProcessId& aId )
       
   398     {
       
   399 #ifdef _DEBUG
       
   400 	RDebug::Printf( "[MemSpy] CMemSpyEngineObjectContainer::CreateProcessL() - START - pid: 0x%04x", (TUint) aId );
       
   401 #endif
       
   402 
       
   403     CMemSpyProcess* processObj = CMemSpyProcess::NewLC( aId, iEngine );
       
   404     const TPtrC pName( processObj->Name() );
       
   405 
       
   406     if  ( pName.FindF( KEKernProcessName ) == KErrNotFound )
       
   407         {
       
   408         if  ( processObj->Count() == 0 )
       
   409             {
       
   410             // Calls delete
       
   411 #ifdef _DEBUG
       
   412 	        RDebug::Printf( "[MemSpy] CMemSpyEngineObjectContainer::CreateProcessL() - process has no threads... deleting it!" );
       
   413 #endif
       
   414             processObj->Close();
       
   415             processObj = NULL;
       
   416             }
       
   417         else
       
   418             {
       
   419             // Make sure we don't add duplicate processes...
       
   420             AppendL( processObj );
       
   421             }
       
   422         }
       
   423     else
       
   424         {
       
   425         // We don't support kernel-side threads
       
   426 #ifdef _DEBUG
       
   427         RDebug::Printf( "[MemSpy] CMemSpyEngineObjectContainer::CreateProcessL() - kernel process... deleting it!" );
       
   428 #endif
       
   429         processObj->Close();
       
   430         processObj = NULL;
       
   431         }
       
   432 
       
   433     CleanupStack::Pop();
       
   434 
       
   435 #ifdef _DEBUG
       
   436     RDebug::Printf( "[MemSpy] CMemSpyEngineObjectContainer::CreateProcessL() - END - pid: 0x%04x, processObj: 0x%08x", (TUint) aId, processObj );
       
   437 #endif
       
   438     return processObj;
       
   439     }
       
   440 
       
   441 
       
   442 void CMemSpyEngineObjectContainer::DestroyProcesses( RArray< CMemSpyProcess* >& aList )
       
   443     {
       
   444     while( aList.Count() ) 
       
   445         {
       
   446         CMemSpyProcess* process = aList[ 0 ];
       
   447         aList.Remove( 0 );
       
   448         process->Close();
       
   449         }
       
   450 
       
   451     aList.Close();
       
   452     }
       
   453 
       
   454 
       
   455 void CMemSpyEngineObjectContainer::TryToCreateProcessAndThreadL( const TThreadId& aTid, CMemSpyProcess*& aProcess, CMemSpyThread*& aThread )
       
   456     {
       
   457 #ifdef _DEBUG
       
   458     RDebug::Printf( "[MemSpy] CMemSpyEngineObjectContainer::TryToCreateProcessAndThreadL(1) - START - aTid: 0x%04x", (TUint) aTid );
       
   459 #endif
       
   460 
       
   461     // Must open thread and process in order to get process id.
       
   462     RThread thread;
       
   463     User::LeaveIfError( iEngine.Driver().OpenThread( aTid, thread ) );
       
   464     CleanupClosePushL( thread );
       
   465     RProcess process;
       
   466     User::LeaveIfError( thread.Process( process ) );
       
   467     const TProcessId processId = process.Id();
       
   468     process.Close();
       
   469 
       
   470     // Call overload
       
   471     TryToCreateProcessAndThreadL( thread, aProcess, aThread );
       
   472 
       
   473     CleanupStack::PopAndDestroy( &thread );
       
   474 
       
   475 #ifdef _DEBUG
       
   476     RDebug::Printf( "[MemSpy] CMemSpyEngineObjectContainer::TryToCreateProcessAndThreadL(1) - END - aTid: 0x%04x", (TUint) aTid );
       
   477 #endif
       
   478     }
       
   479 
       
   480 
       
   481 void CMemSpyEngineObjectContainer::TryToCreateProcessAndThreadL( const RThread& aRThread, CMemSpyProcess*& aProcess, CMemSpyThread*& aThread )
       
   482     {
       
   483 #ifdef _DEBUG
       
   484     RDebug::Printf( "[MemSpy] CMemSpyEngineObjectContainer::TryToCreateProcessAndThreadL(2) - START - aTid: 0x%04x", (TUint) aRThread.Id() );
       
   485 #endif
       
   486 
       
   487     // Full name of process
       
   488     TFullName* name = new(ELeave) TFullName();
       
   489     CleanupStack::PushL( name );
       
   490 
       
   491     // Must open thread and process in order to get process id.
       
   492     RProcess process;
       
   493     User::LeaveIfError( aRThread.Process( process ) );
       
   494     process.FullName( *name );
       
   495     const TProcessId processId = process.Id();
       
   496     process.Close();
       
   497 
       
   498     const TBool isKernel = ( name->FindF( KEKernProcessName ) >= KErrNone );
       
   499 
       
   500 #ifdef _DEBUG
       
   501     RDebug::Print( _L("[MemSpy] CMemSpyEngineObjectContainer::TryToCreateProcessAndThreadL(2) - pid: 0x%04x, name: %S"), (TUint) processId, name );
       
   502 #endif
       
   503 
       
   504     CleanupStack::PopAndDestroy( name );
       
   505 
       
   506     // See if we have already created a process for this process id...
       
   507     CMemSpyProcess* processObj = NULL;
       
   508     const TInt procIndex = ProcessIndexById( processId );
       
   509 
       
   510 #ifdef _DEBUG
       
   511     RDebug::Print( _L("[MemSpy] CMemSpyEngineObjectContainer::TryToCreateProcessAndThreadL(2) - pid: 0x%04x, index: %d"), (TUint) processId, procIndex );
       
   512 #endif
       
   513 
       
   514     if  ( isKernel )
       
   515         {
       
   516 #ifdef _DEBUG
       
   517         RDebug::Printf( "[MemSpy] CMemSpyEngineObjectContainer::TryToCreateProcessAndThreadL(2) - caller requested a kernel thread/process..." );
       
   518 #endif
       
   519         __ASSERT_ALWAYS( procIndex == KErrNotFound, MemSpyEngineUtils::Panic( EMemSpyEnginePanicEncounteredKernelUnexpectedly ) );
       
   520 
       
   521 #ifdef _DEBUG
       
   522         RDebug::Printf( "[MemSpy] CMemSpyEngineObjectContainer::TryToCreateProcessAndThreadL(2) - leaving with KErrNotSupported" );
       
   523 #endif
       
   524         User::Leave( KErrNotSupported );
       
   525         }
       
   526     else if ( aRThread.Id() == RThread().Id() )
       
   527         {
       
   528         TRACE( RDebug::Printf( "[MemSpy] CMemSpyEngineObjectContainer::TryToCreateProcessAndThreadL(2) - trying to create MemSpy -> leaving with KErrNotSupported" ) );
       
   529         User::Leave( KErrNotSupported );
       
   530         }
       
   531     else
       
   532         {
       
   533         if  ( procIndex >= 0 )
       
   534             {
       
   535             // Existing process, but new thread?
       
   536             processObj = iProcesses[ procIndex ];
       
   537 
       
   538             // Make new thread
       
   539             processObj->HandleThreadIsBornL( aRThread.Id() );
       
   540             }
       
   541         else
       
   542             {
       
   543             // Must also create a new process. This should, in theory, ensure
       
   544             // the thread is also created.
       
   545             processObj = CMemSpyProcess::NewLC( processId, iEngine );
       
   546             if  ( processObj->Count() == 0 )
       
   547                 {
       
   548                 // No threads, discard process and leave
       
   549                 User::Leave( KErrNotFound );
       
   550                 }
       
   551             else
       
   552                 {
       
   553                 // Save process
       
   554                 AppendL( processObj );
       
   555                 }
       
   556 
       
   557             // Tidy up
       
   558             CleanupStack::Pop();
       
   559             }
       
   560 
       
   561         // Check to see if the process contains the specified thread (it should do, since we just found
       
   562         // the process using it).
       
   563         CMemSpyThread& threadObj = processObj->ThreadByIdL( aRThread.Id() );
       
   564 
       
   565         // We're done now.
       
   566         aProcess = processObj;
       
   567         aThread = &threadObj;
       
   568 
       
   569         // Update sort order
       
   570         Resort();
       
   571 
       
   572         // Signal UI        
       
   573         AsyncNotifyUiOfContainerChanges();
       
   574         }
       
   575 
       
   576 #ifdef _DEBUG
       
   577     RDebug::Printf( "[MemSpy] CMemSpyEngineObjectContainer::TryToCreateProcessAndThreadL(2) - END - aTid: 0x%04x, pid: 0x%04x", (TUint) aRThread.Id(), (TUint) processId );
       
   578 #endif
       
   579     }
       
   580 
       
   581 
       
   582 void CMemSpyEngineObjectContainer::Resort()
       
   583     {
       
   584     switch( iSortType )
       
   585         {
       
   586     case ESortById:
       
   587         {
       
   588         TLinearOrder< CMemSpyProcess* > comparer( CompareById );
       
   589         iProcesses.Sort( comparer );
       
   590         }
       
   591         break;
       
   592     default:
       
   593     case ESortByName:
       
   594         {
       
   595         TLinearOrder< CMemSpyProcess* > comparer( CompareByName );
       
   596         iProcesses.Sort( comparer );
       
   597         }
       
   598         break;
       
   599     case ESortByThreadCount:
       
   600         {
       
   601         TLinearOrder< CMemSpyProcess* > comparer( CompareByThreadCount );
       
   602         iProcesses.Sort( comparer );
       
   603         }
       
   604         break;
       
   605     case ESortByCodeSegs:
       
   606         {
       
   607         TLinearOrder< CMemSpyProcess* > comparer( CompareByCodeSegs );
       
   608         iProcesses.Sort( comparer );
       
   609         }
       
   610         break;
       
   611     case ESortByHeapUsage:
       
   612         {
       
   613         TLinearOrder< CMemSpyProcess* > comparer( CompareByHeapUsage );
       
   614         iProcesses.Sort( comparer );
       
   615         }
       
   616         break;
       
   617     case ESortByStackUsage:
       
   618         {
       
   619         TLinearOrder< CMemSpyProcess* > comparer( CompareByStackUsage );
       
   620         iProcesses.Sort( comparer );
       
   621         }
       
   622         break;
       
   623         }
       
   624     }
       
   625 
       
   626 
       
   627 EXPORT_C void CMemSpyEngineObjectContainer::SortById()
       
   628     {
       
   629     iSortType = ESortById;
       
   630     Resort();
       
   631     }
       
   632 
       
   633 
       
   634 EXPORT_C void CMemSpyEngineObjectContainer::SortByName()
       
   635     {
       
   636     iSortType = ESortByName;
       
   637     Resort();
       
   638     }
       
   639 
       
   640 
       
   641 EXPORT_C void CMemSpyEngineObjectContainer::SortByThreadCount()
       
   642     {
       
   643     iSortType = ESortByThreadCount;
       
   644     Resort();
       
   645     }
       
   646 
       
   647 
       
   648 EXPORT_C void CMemSpyEngineObjectContainer::SortByCodeSegs()
       
   649     {
       
   650     iSortType = ESortByCodeSegs;
       
   651     Resort();
       
   652     }
       
   653 
       
   654 
       
   655 EXPORT_C void CMemSpyEngineObjectContainer::SortByHeapUsage()
       
   656     {
       
   657     iSortType = ESortByHeapUsage;
       
   658     Resort();
       
   659     }
       
   660 
       
   661 
       
   662 EXPORT_C void CMemSpyEngineObjectContainer::SortByStackUsage()
       
   663     {
       
   664     iSortType = ESortByStackUsage;
       
   665     Resort();
       
   666     }
       
   667 
       
   668 
       
   669 void CMemSpyEngineObjectContainer::Remove( CMemSpyProcess& aProcess )
       
   670     {
       
   671     const TInt index = ProcessIndexById( aProcess.Id() );
       
   672     if ( index >= 0 )
       
   673         {
       
   674         iProcesses.Remove( index );
       
   675         }
       
   676     }
       
   677     
       
   678     
       
   679 void CMemSpyEngineObjectContainer::AppendL( CMemSpyProcess* aProcess )
       
   680     {
       
   681     const TInt error = iProcesses.Append( aProcess );
       
   682     User::LeaveIfError( error );    
       
   683     }
       
   684 
       
   685 
       
   686 TInt CMemSpyEngineObjectContainer::CompareById( CMemSpyProcess* const & aLeft, CMemSpyProcess* const & aRight )
       
   687     {
       
   688     TInt ret = 1;
       
   689     //
       
   690     if  ( aLeft->Id() < aRight->Id() )
       
   691         {
       
   692         ret = -1;
       
   693         }
       
   694     else if ( aLeft->Id() == aRight->Id() )
       
   695         {
       
   696         ret = 0;
       
   697         }
       
   698     //
       
   699     return ret;
       
   700     }
       
   701 
       
   702 
       
   703 TInt CMemSpyEngineObjectContainer::CompareByThreadCount( CMemSpyProcess* const & aLeft, CMemSpyProcess* const & aRight )
       
   704     {
       
   705     TInt ret = -1;
       
   706     //
       
   707     if  ( aLeft->Count() < aRight->Count() )
       
   708         {
       
   709         ret = 1;
       
   710         }
       
   711     else if ( aLeft->Count() == aRight->Count() )
       
   712         {
       
   713         // Sort by name when thread counts are the same
       
   714         ret = aLeft->Name().CompareF( aRight->Name() );
       
   715         }
       
   716     //
       
   717     return ret;
       
   718     }
       
   719 
       
   720 
       
   721 TInt CMemSpyEngineObjectContainer::CompareByName( CMemSpyProcess* const & aLeft, CMemSpyProcess* const & aRight )
       
   722     {
       
   723     return aLeft->Name().CompareF( aRight->Name() );
       
   724     }
       
   725 
       
   726 
       
   727 TInt CMemSpyEngineObjectContainer::CompareByCodeSegs( CMemSpyProcess* const & aLeft, CMemSpyProcess* const & aRight )
       
   728     {
       
   729     CMemSpyEngine& engine = aLeft->Engine();
       
   730     CMemSpyEngineHelperCodeSegment& helper = engine.HelperCodeSegment();
       
   731     //
       
   732     TInt leftCount = 0;
       
   733     TInt rightCount = 0;
       
   734     //
       
   735     TRAP_IGNORE( 
       
   736         CMemSpyEngineCodeSegList* leftList = helper.CodeSegmentListL( aLeft->Id() );
       
   737         leftCount = leftList->Count();
       
   738         delete leftList;
       
   739         //
       
   740         CMemSpyEngineCodeSegList* rightList = helper.CodeSegmentListL( aRight->Id() );
       
   741         rightCount = rightList->Count();
       
   742         delete rightList;
       
   743         );
       
   744     //
       
   745     TInt ret = -1;
       
   746     //
       
   747     if  ( leftCount < rightCount )
       
   748         {
       
   749         ret = 1;
       
   750         }
       
   751     else if ( leftCount == rightCount )
       
   752         {
       
   753         ret = 0;
       
   754         }
       
   755     //
       
   756     return ret;
       
   757     }
       
   758 
       
   759 
       
   760 TInt CMemSpyEngineObjectContainer::CompareByHeapUsage( CMemSpyProcess* const & aLeft, CMemSpyProcess* const & aRight )
       
   761     {
       
   762     CMemSpyEngine& engine = aLeft->Engine();
       
   763     CMemSpyEngineHelperHeap& helper = engine.HelperHeap();
       
   764     //
       
   765     TInt leftSize = 0;
       
   766     TInt rightSize = 0;
       
   767     //
       
   768     TRAP_IGNORE( 
       
   769         RArray< TMemSpyHeapInfo > leftInfos;
       
   770         CleanupClosePushL( leftInfos );
       
   771         helper.GetHeapInfoUserL( *aLeft, leftInfos );
       
   772         const TInt leftCount = leftInfos.Count();
       
   773         for( TInt i=0; i<leftCount; i++ )
       
   774             {
       
   775             const TMemSpyHeapInfo& info = leftInfos[ i ];
       
   776             if ( info.Type() == TMemSpyHeapInfo::ETypeRHeap )
       
   777                 {
       
   778                 leftSize += (TInt) info.AsRHeap().ObjectData().Size();
       
   779                 }
       
   780             }
       
   781         CleanupStack::PopAndDestroy( &leftInfos );
       
   782         );
       
   783     //
       
   784     TRAP_IGNORE( 
       
   785         RArray< TMemSpyHeapInfo > rightInfos;
       
   786         CleanupClosePushL( rightInfos );
       
   787         helper.GetHeapInfoUserL( *aRight, rightInfos );
       
   788         const TInt rightCount = rightInfos.Count();
       
   789         for( TInt i=0; i<rightCount; i++ )
       
   790             {
       
   791             const TMemSpyHeapInfo& info = rightInfos[ i ];
       
   792             if ( info.Type() == TMemSpyHeapInfo::ETypeRHeap )
       
   793                 {
       
   794                 rightSize += (TInt) info.AsRHeap().ObjectData().Size();
       
   795                 }
       
   796             }
       
   797         CleanupStack::PopAndDestroy( &rightInfos );
       
   798         );
       
   799     //
       
   800     TInt ret = -1;
       
   801     //
       
   802     if  ( leftSize < rightSize )
       
   803         {
       
   804         ret = 1;
       
   805         }
       
   806     else if ( leftSize == rightSize )
       
   807         {
       
   808         ret = 0;
       
   809         }
       
   810     //
       
   811     return ret;
       
   812     }
       
   813 
       
   814 
       
   815 TInt CMemSpyEngineObjectContainer::CompareByStackUsage( CMemSpyProcess* const & aLeft, CMemSpyProcess* const & aRight )
       
   816     {
       
   817     CMemSpyEngine& engine = aLeft->Engine();
       
   818     CMemSpyEngineHelperStack& helper = engine.HelperStack();
       
   819     //
       
   820     const TInt leftCount = helper.CalculateStackSizes( *aLeft );
       
   821     const TInt rightCount = helper.CalculateStackSizes( *aRight );
       
   822     //
       
   823     TInt ret = -1;
       
   824     //
       
   825     if  ( leftCount < rightCount )
       
   826         {
       
   827         ret = 1;
       
   828         }
       
   829     else if ( leftCount == rightCount )
       
   830         {
       
   831         ret = 0;
       
   832         }
       
   833     //
       
   834     return ret;
       
   835     }
       
   836 
       
   837 
       
   838 TBool CMemSpyEngineObjectContainer::MoveToGarbageL( const TProcessId& aId )
       
   839     {
       
   840     const TInt pos = ProcessIndexById( aId );
       
   841 
       
   842     if  ( pos >= 0 )
       
   843         {
       
   844         CMemSpyProcess* proc = iProcesses[ pos ];
       
   845 
       
   846 #ifdef _DEBUG
       
   847         const TPtrC pName( proc->Name() );
       
   848         RDebug::Print( _L("[MemSpy] CMemSpyEngineObjectContainer::MoveToGarbageL() - pid: 0x%04x, proc: 0x%08x, pos: %d, id: 0x%04x, name: %S"), (TUint) aId, proc, pos, (TUint) proc->Id(), &pName );
       
   849 #endif
       
   850 
       
   851         User::LeaveIfError( iGarbage.Append( proc ) );
       
   852         iProcesses.Remove( pos );
       
   853         }
       
   854 	else
       
   855         {
       
   856 #ifdef _DEBUG
       
   857         RDebug::Printf( "[MemSpy] CMemSpyEngineObjectContainer::MoveToGarbageL() - pid: 0x%04x, pos: KErrNotFound", (TUint) aId );
       
   858 #endif
       
   859         }
       
   860         
       
   861     return ( pos >= 0 );
       
   862     }
       
   863 
       
   864 
       
   865 
       
   866 
       
   867 
       
   868 
       
   869 
       
   870 
       
   871 
       
   872 
       
   873 
       
   874 
       
   875 
       
   876 
       
   877 
       
   878 
       
   879 
       
   880 
       
   881 void CMemSpyEngineObjectContainer::ThreadIsDeadL( const TThreadId& aId, const RThread& aThread )
       
   882     {
       
   883     // Try to find the thread in question...
       
   884     CMemSpyProcess* process = NULL;
       
   885     CMemSpyThread* thread = NULL;
       
   886     //
       
   887     const TInt err = ProcessAndThreadByThreadId( aId, process, thread );
       
   888     if  ( err == KErrNone && thread )
       
   889         {
       
   890         // This will force the thread to detect if it is dead or not...
       
   891         thread->SetDeadL( aThread );
       
   892 
       
   893         // Signal UI        
       
   894         AsyncNotifyUiOfContainerChanges();
       
   895         }
       
   896     }
       
   897     
       
   898 
       
   899 void CMemSpyEngineObjectContainer::ProcessIsDeadL( const TProcessId& aId, const RProcess& aProcess )
       
   900     {
       
   901     const TInt index = ProcessIndexById( aId );
       
   902     if  ( index >= 0 )
       
   903         {
       
   904         CMemSpyProcess* process = iProcesses[ index ];
       
   905         process->SetDeadL( aProcess );
       
   906 
       
   907         // Signal UI        
       
   908         AsyncNotifyUiOfContainerChanges();
       
   909         }
       
   910     }
       
   911 
       
   912 
       
   913 void CMemSpyEngineObjectContainer::ThreadIsBornL( const TThreadId& /*aId*/, const RThread& aThread )
       
   914     {
       
   915     if  ( aThread.Handle() != KNullHandle )
       
   916         {
       
   917         // The thread and process objects that will be created (or found, if they already exist).
       
   918         CMemSpyProcess* process = NULL;
       
   919         CMemSpyThread* thread = NULL;
       
   920 
       
   921         // Create the objects if needed
       
   922         TryToCreateProcessAndThreadL( aThread, process, thread );
       
   923         }
       
   924     }
       
   925 
       
   926 
       
   927 void CMemSpyEngineObjectContainer::ProcessIsBornL( const TProcessId& aId, const RProcess& /*aProcess*/ )
       
   928     {
       
   929 #ifdef _DEBUG
       
   930     RDebug::Printf( "[MemSpy] CMemSpyEngineObjectContainer::ProcessIsBornL() - START - pid: 0x%04x", (TUint) aId );
       
   931 #endif
       
   932     (void) aId;
       
   933 
       
   934     // This gets handled by the new thread creation. When the first thread in the process
       
   935     // is created, we'll also prepare a new process object.
       
   936 
       
   937 #ifdef _DEBUG
       
   938 	RDebug::Printf( "[MemSpy] CMemSpyEngineObjectContainer::ProcessIsBornL() - END - pid: 0x%04x", (TUint) aId );
       
   939 #endif
       
   940     }
       
   941     
       
   942 
       
   943 void CMemSpyEngineObjectContainer::AsyncNotifyUiOfContainerChanges()
       
   944     {
       
   945     iIdleNotifyContainerChanged->Cancel();
       
   946     iIdleNotifyContainerChanged->Start( TCallBack( NotifyUiOfContainerChanges, this ) );
       
   947     }
       
   948 
       
   949 
       
   950 TBool CMemSpyEngineObjectContainer::NotifyUiOfContainerChanges( TAny* aSelf )
       
   951     {
       
   952     CMemSpyEngineObjectContainer* self = reinterpret_cast< CMemSpyEngineObjectContainer* >( aSelf );
       
   953     TRAP_IGNORE( self->iEngine.NotifyContainerChangeL() );
       
   954     return EFalse;
       
   955     }
       
   956 
       
   957 
       
   958