crashanalysercmd/Libraries/Engine/CrashItemLib/Engine/CIEngine.cs
changeset 0 818e61de6cd1
equal deleted inserted replaced
-1:000000000000 0:818e61de6cd1
       
     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 using System;
       
    18 using System.Collections.Generic;
       
    19 using System.IO;
       
    20 using System.Threading;
       
    21 using SymbianDebugLib.Engine;
       
    22 using SymbianUtils;
       
    23 using SymbianUtils.Tracer;
       
    24 using SymbianUtils.Threading;
       
    25 using SymbianUtils.FileSystem;
       
    26 using CrashItemLib.Crash.Base;
       
    27 using CrashItemLib.Crash.Container;
       
    28 using CrashItemLib.Engine.Interfaces;
       
    29 using CrashItemLib.Engine.Operations;
       
    30 using CrashItemLib.Engine.Primer;
       
    31 using CrashItemLib.Engine.ProblemDetectors;
       
    32 using CrashItemLib.Engine.Sources;
       
    33 using CrashItemLib.PluginAPI;
       
    34 using CrashItemLib.Sink;
       
    35 
       
    36 namespace CrashItemLib.Engine
       
    37 {
       
    38     public class CIEngine : DisposableObject, IEnumerable<CIContainer>, ITracer
       
    39     {
       
    40         #region Enumerations
       
    41         public enum TState
       
    42         {
       
    43             // We've started to process the crash sources
       
    44             EStateProcessingStarted = 0,
       
    45 
       
    46             // Engine is idle & fully ready for display & output
       
    47             EStateProcessingComplete
       
    48         }
       
    49 
       
    50         public enum TSourceEvent
       
    51         {
       
    52             EEventSourceReady = 0,
       
    53             EEventSourceProgress,
       
    54             EEventSourceStateChanged
       
    55         }
       
    56 
       
    57         public enum TCrashEvent
       
    58         {
       
    59             EEventCrashAdded = 0,
       
    60             EEventCrashRemoved,
       
    61             EEventCrashRemovedAll
       
    62         }
       
    63         #endregion
       
    64 
       
    65         #region Delegates & events
       
    66         public delegate void CIEngineStateHandler( TState aEvent );
       
    67         public event CIEngineStateHandler StateChanged = delegate( TState aState ) { };
       
    68 
       
    69         public delegate void CIEngineSourceObserver( TSourceEvent aEvent, CIEngineSource aSource, object aParameter );
       
    70         public event CIEngineSourceObserver SourceObservers = delegate( TSourceEvent aEvent, CIEngineSource aSource, object aParameter ) { };
       
    71 
       
    72         public delegate void CIEngineCrashObserver( TCrashEvent aEvent, CIContainer aContainer );
       
    73         public event CIEngineCrashObserver CrashObservers;
       
    74 
       
    75         public delegate void CIExceptionHandler( Exception aException );
       
    76         public event CIExceptionHandler ExceptionHandlers = delegate( Exception aException ) { };
       
    77         #endregion
       
    78 
       
    79         #region Constructors
       
    80         public CIEngine( DbgEngine aDebugEngine, ICIEngineUI aUI )
       
    81         {
       
    82             iUI = aUI;
       
    83             iDebugEngine = aDebugEngine;
       
    84             //
       
    85             iPrimer = new CIEnginePrimer( this );
       
    86             iPlugins = new CFFPluginRegistry( this );
       
    87             iSinkManager = new CISinkManager( this );
       
    88             iSources = new CIEngineSourceCollection( this );
       
    89             iContainerIndex = new CIContainerIndex( this );
       
    90             iContainerCollection = new CIContainerCollection();
       
    91             iOperationManager = new CIEngineOperationManager( this );
       
    92             iProblemDetectorManager = new CIProblemDetectorManager( this );
       
    93         }
       
    94         #endregion
       
    95 
       
    96         #region API
       
    97         public void ClearAll()
       
    98         {
       
    99             lock ( iSources )
       
   100             {
       
   101                 iSources.Clear();
       
   102             }
       
   103             ClearCrashes();
       
   104         }
       
   105 
       
   106         public void ClearCrashes()
       
   107         {
       
   108             bool notify = true;
       
   109             lock ( iContainerCollection )
       
   110             {
       
   111                 notify = iContainerCollection.Count > 0;
       
   112                 iContainerCollection.Clear();
       
   113             }
       
   114             //
       
   115             if ( notify )
       
   116             {
       
   117                 OnContainerRemovedAll();
       
   118             }
       
   119         }
       
   120 
       
   121         public bool Prime( FileInfo aFile )
       
   122         {
       
   123             bool success = false;
       
   124             //
       
   125             try
       
   126             {
       
   127                 success = iPrimer.Prime( aFile );
       
   128             }
       
   129             catch ( Exception )
       
   130             {
       
   131             }
       
   132             //
       
   133             return success;
       
   134         }
       
   135 
       
   136         public bool Prime( DirectoryInfo aDirectory )
       
   137         {
       
   138             bool success = false;
       
   139             //
       
   140             try
       
   141             {
       
   142                 iPrimer.Prime( aDirectory );
       
   143                 success = true;
       
   144             }
       
   145             catch ( Exception )
       
   146             {
       
   147             }
       
   148             //
       
   149             return success;
       
   150         }
       
   151 
       
   152         public bool PrimeRecursive( DirectoryInfo aDirectory )
       
   153         {
       
   154             bool success = false;
       
   155             //
       
   156             try
       
   157             {
       
   158                 iPrimer.PrimeRecursive( aDirectory );
       
   159                 success = true;
       
   160             }
       
   161             catch ( Exception )
       
   162             {
       
   163             }
       
   164             //
       
   165             return success;
       
   166         }
       
   167 
       
   168         public void IdentifyCrashes( TSynchronicity aSynchronicity )
       
   169         {
       
   170             // If we must operate in synchronous mode, that is, we must not
       
   171             // return until the all the crash item containers are prepared,
       
   172             // then we created a blocking object that will be signalled when
       
   173             // all the asynchronous operations are complete.
       
   174             DestroyBlocker();
       
   175             if ( aSynchronicity == TSynchronicity.ESynchronous )
       
   176             {
       
   177                 iSynchronousBlocker = new ManualResetEvent( false );
       
   178             }
       
   179 
       
   180             // Next, we start processing the source files in order to create
       
   181             // crash containers.
       
   182             DestroySourceProcessor();
       
   183             iSourceProcessor = new CIEngineSourceProcessor( iSources );
       
   184             iSourceProcessor.EventHandler += new CIEngineSourceProcessor.ProcessorEventHandler( SourceProcessor_EventHandler );
       
   185             iSourceProcessor.Start( TSynchronicity.EAsynchronous );
       
   186 
       
   187             // Now we operate asynchronously. When the source processor has read
       
   188             // all of the CIEngineSource objects, it will trigger and event
       
   189             // callback (SourceProcessor_EventHandler) which will cause us to start
       
   190             // the serialized operation manager.
       
   191             //
       
   192             // When the serialized operation manager completes, it will again indicate
       
   193             // this via an event callback at which point we will trigger the manual
       
   194             // reset event (blocker) and therefore resume this main thread.
       
   195             if ( aSynchronicity == TSynchronicity.ESynchronous )
       
   196             {
       
   197                 // Now wait. 
       
   198                 using ( iSynchronousBlocker )
       
   199                 {
       
   200                     iSynchronousBlocker.WaitOne();
       
   201                 }
       
   202                 iSynchronousBlocker = null;
       
   203             }
       
   204         }
       
   205         #endregion
       
   206 
       
   207         #region Properties
       
   208         public int Count
       
   209         {
       
   210             get
       
   211             {
       
   212                 lock ( iContainerCollection )
       
   213                 {
       
   214                     return iContainerCollection.Count;
       
   215                 }
       
   216             }
       
   217         }
       
   218 
       
   219         public CIContainer this[ int aIndex ]
       
   220         {
       
   221             get
       
   222             {
       
   223                 lock ( iContainerCollection )
       
   224                 {
       
   225                     return iContainerCollection[ aIndex ];
       
   226                 }
       
   227             }
       
   228         }
       
   229 
       
   230         public DbgEngine DebugEngine
       
   231         {
       
   232             get { return iDebugEngine; }
       
   233         }
       
   234 
       
   235         public CISinkManager SinkManager
       
   236         {
       
   237             get { return iSinkManager; }
       
   238         }
       
   239 
       
   240         public CFFPluginRegistry PluginRegistry
       
   241         {
       
   242             get { return iPlugins; }
       
   243         }
       
   244 
       
   245         public CIEngineSourceCollection Sources
       
   246         {
       
   247             get { return iSources; }
       
   248         }
       
   249         #endregion
       
   250 
       
   251         #region Event handlers
       
   252         private void SourceProcessor_EventHandler( CIEngineSourceProcessor.TEvent aEvent )
       
   253         {
       
   254             this.Trace( "[CIEngine] SourceProcessor_EventHandler() - START - aEvent: {0}", aEvent );
       
   255             //
       
   256             if ( aEvent == CIEngineSourceProcessor.TEvent.EEventStarting )
       
   257             {
       
   258                 OnStateChanged( TState.EStateProcessingStarted );
       
   259                 ClearCrashes();
       
   260             }
       
   261             else if ( aEvent == CIEngineSourceProcessor.TEvent.EEventCompleted )
       
   262             {
       
   263                 DestroySourceProcessor();
       
   264                 //
       
   265                 DestroyIndexProcessor();
       
   266                 iIndexProcessor = new CIContainerIndexProcessor( iContainerIndex, this );
       
   267                 iIndexProcessor.EventHandler += new CIContainerIndexProcessor.ProcessorEventHandler( IndexProcessor_EventHandler );
       
   268                 iIndexProcessor.Start( TSynchronicity.EAsynchronous );
       
   269             }
       
   270             //
       
   271             this.Trace( "[CIEngine] SourceProcessor_EventHandler() - END - aEvent: {0}", aEvent );
       
   272         }
       
   273 
       
   274         private void IndexProcessor_EventHandler( CIContainerIndexProcessor.TEvent aEvent )
       
   275         {
       
   276             this.Trace( "[CIEngine] IndexProcessor_EventHandler() - START - aEvent: {0}", aEvent );
       
   277             //
       
   278             if ( aEvent == CIContainerIndexProcessor.TEvent.EEventStarting )
       
   279             {
       
   280             }
       
   281             else if ( aEvent == CIContainerIndexProcessor.TEvent.EEventCompleted )
       
   282             {
       
   283                 DestroyIndexProcessor();
       
   284    
       
   285                 // All the sources have been processed. Create any problem detectors.
       
   286                 iProblemDetectorManager.EventHandler += new MultiThreadedProcessor<CIProblemDetector>.ProcessorEventHandler( ProblemDetectorManager_EventHandler );
       
   287                 iProblemDetectorManager.Start( TSynchronicity.EAsynchronous );
       
   288             }
       
   289             //
       
   290             this.Trace( "[CIEngine] IndexProcessor_EventHandler() - END - aEvent: {0}", aEvent );
       
   291         }
       
   292 
       
   293         private void ProblemDetectorManager_EventHandler( MultiThreadedProcessor<CIProblemDetector>.TEvent aEvent )
       
   294         {
       
   295             this.Trace( "[CIEngine] ProblemDetectorManager_EventHandler() - START - aEvent: {0}", aEvent );
       
   296             //
       
   297             if ( aEvent == MultiThreadedProcessor<CIProblemDetector>.TEvent.EEventStarting )
       
   298             {
       
   299             }
       
   300             else if ( aEvent == MultiThreadedProcessor<CIProblemDetector>.TEvent.EEventCompleted )
       
   301             {
       
   302                 iProblemDetectorManager.EventHandler -= new MultiThreadedProcessor<CIProblemDetector>.ProcessorEventHandler( ProblemDetectorManager_EventHandler );
       
   303 
       
   304                 // Run any serialized operations
       
   305                 iOperationManager.StateHandler += new CIEngineOperationManager.QueueStateHandler( OperationManager_StateHandler );
       
   306                 iOperationManager.Start();
       
   307             }
       
   308             //
       
   309             this.Trace( "[CIEngine] ProblemDetectorManager_EventHandler() - END - aEvent: {0}", aEvent );
       
   310         }
       
   311      
       
   312         private void OperationManager_StateHandler( CIEngineOperationManager.TState aState )
       
   313         {
       
   314             this.Trace( "[CIEngine] OperationManager_StateHandler() - START - aState: {0}", aState );
       
   315             //
       
   316             if ( aState == SymbianUtils.SerializedOperations.SerializedOperationManager.TState.EStateOperationsCompleted )
       
   317             {
       
   318                 iOperationManager.StateHandler -= new CIEngineOperationManager.QueueStateHandler( OperationManager_StateHandler );
       
   319                 //
       
   320                 IdentifyCrashesComplete();
       
   321             }
       
   322             //
       
   323             this.Trace( "[CIEngine] OperationManager_StateHandler() - END - aState: {0}", aState );
       
   324         }
       
   325         #endregion
       
   326 
       
   327         #region Internal delegates
       
   328         private delegate void VoidHandler();
       
   329         #endregion
       
   330 
       
   331         #region Internal methods
       
   332         internal void Add( CIContainer aContainer )
       
   333         {
       
   334             string fileName = aContainer.Source.MasterFileName;
       
   335             if ( string.IsNullOrEmpty( fileName ) )
       
   336             {
       
   337                 throw new ArgumentException( "Container source file name cannot be empty" );
       
   338             }
       
   339             //
       
   340             lock ( iContainerCollection )
       
   341             {
       
   342                 iContainerCollection.Add( aContainer );
       
   343             }
       
   344             //
       
   345             if ( CrashObservers != null )
       
   346             {
       
   347                 CrashObservers( TCrashEvent.EEventCrashAdded, aContainer );
       
   348             }
       
   349         }
       
   350 
       
   351         internal int GetNextElementId()
       
   352         {
       
   353             return iIdProvider.GetNextId();
       
   354         }
       
   355         
       
   356         internal void QueueOperation( CIEngineOperation aOperation )
       
   357         {
       
   358             this.Trace( "[CIEngine] QueueOperation() - aOperation: {0} ({1})", aOperation, aOperation.GetType() );
       
   359             iOperationManager.Queue( aOperation );
       
   360         }
       
   361 
       
   362         internal void OnSourceStateChanged( CIEngineSource aSource )
       
   363         {
       
   364             this.Trace( "[CIEngine] OnSourceStateChanged() - START - aSource: {0}, aSource.IsReady: {1}, aSource.State: {2}", aSource.FileName, aSource.IsReady, aSource.State );
       
   365             
       
   366             SourceObservers( TSourceEvent.EEventSourceStateChanged, aSource, null );
       
   367             if ( aSource.IsReady )
       
   368             {
       
   369                 SourceObservers( TSourceEvent.EEventSourceReady, aSource, null );
       
   370             }
       
   371 
       
   372             this.Trace( "[CIEngine] OnSourceStateChanged() - END - aSource: {0}, aSource.IsReady: {1}, aSource.State: {2}", aSource.FileName, aSource.IsReady, aSource.State );
       
   373         }
       
   374 
       
   375         internal void OnSourceProgress( CIEngineSource aSource, int aProgress )
       
   376         {
       
   377             this.Trace( "[CIEngine] OnSourceProgress() - START - aSource: {0}, aSource.IsReady: {1}, aProgress: {2}", aSource.FileName, aSource.IsReady, aProgress );
       
   378 
       
   379             SourceObservers( TSourceEvent.EEventSourceProgress, aSource, aProgress );
       
   380 
       
   381             this.Trace( "[CIEngine] OnSourceProgress() - END - aSource: {0}, aSource.IsReady: {1}, aProgress: {2}", aSource.FileName, aSource.IsReady, aProgress );
       
   382         }
       
   383 
       
   384         internal void OnException( Exception aException )
       
   385         {
       
   386             this.Trace( "[CIEngine] OnException() - {0} / {1}", aException.Message, aException.StackTrace );
       
   387             ExceptionHandlers( aException );
       
   388         }
       
   389 
       
   390         internal void OnContainerRemovedAll()
       
   391         {
       
   392             if ( CrashObservers != null )
       
   393             {
       
   394                 CrashObservers( TCrashEvent.EEventCrashRemovedAll, null );
       
   395             }
       
   396         }
       
   397 
       
   398         private void Remove( CIContainer aContainer )
       
   399         {
       
   400             lock ( iContainerCollection )
       
   401             {
       
   402                 if ( iContainerCollection.Contains( aContainer ) )
       
   403                 {
       
   404                     iContainerCollection.Remove( aContainer );
       
   405                     if ( CrashObservers != null )
       
   406                     {
       
   407                         CrashObservers( TCrashEvent.EEventCrashRemoved, aContainer );
       
   408                     }
       
   409                 }
       
   410             }
       
   411         }
       
   412 
       
   413         private void OnStateChanged( TState aEvent )
       
   414         {
       
   415             this.Trace( "[CIEngine] OnStateChanged() - START - aEvent: {0}", aEvent );
       
   416             if ( StateChanged != null )
       
   417             {
       
   418                 StateChanged( aEvent );
       
   419             }
       
   420             this.Trace( "[CIEngine] OnStateChanged() - END - aEvent: {0}", aEvent );
       
   421         }
       
   422 
       
   423         private void IdentifyCrashesComplete()
       
   424         {
       
   425             this.Trace( "[CIEngine] IdentifyCrashesComplete()" );
       
   426             OnStateChanged( TState.EStateProcessingComplete );
       
   427             //
       
   428             ReleaseBlocker();
       
   429         }
       
   430 
       
   431         private void DestroyBlocker()
       
   432         {
       
   433             if ( iSynchronousBlocker != null )
       
   434             {
       
   435                 iSynchronousBlocker.Close();
       
   436                 iSynchronousBlocker = null;
       
   437             }
       
   438         }
       
   439 
       
   440         private void ReleaseBlocker()
       
   441         {
       
   442             if ( iSynchronousBlocker != null )
       
   443             {
       
   444                 iSynchronousBlocker.Set();
       
   445             }
       
   446         }
       
   447 
       
   448         private void DestroySourceProcessor()
       
   449         {
       
   450             if ( iSourceProcessor != null )
       
   451             {
       
   452                 iSourceProcessor.EventHandler -= new CIEngineSourceProcessor.ProcessorEventHandler( SourceProcessor_EventHandler );
       
   453                 iSourceProcessor.Dispose();
       
   454                 iSourceProcessor = null;
       
   455             }
       
   456         }
       
   457 
       
   458         private void DestroyIndexProcessor()
       
   459         {
       
   460             if ( iIndexProcessor != null )
       
   461             {
       
   462                 iIndexProcessor.EventHandler -= new CIContainerIndexProcessor.ProcessorEventHandler( IndexProcessor_EventHandler );
       
   463                 iIndexProcessor = null;
       
   464             }
       
   465         }
       
   466 
       
   467         private void DestroyProblemDetectorManager()
       
   468         {
       
   469             if ( iProblemDetectorManager != null )
       
   470             {
       
   471                 iProblemDetectorManager.EventHandler -= new MultiThreadedProcessor<CIProblemDetector>.ProcessorEventHandler( ProblemDetectorManager_EventHandler );
       
   472                 iProblemDetectorManager.Dispose();
       
   473             }
       
   474         }
       
   475 
       
   476         private void DestroyOperationManager()
       
   477         {
       
   478             if ( iOperationManager != null )
       
   479             {
       
   480                 iOperationManager.StateHandler -= new CIEngineOperationManager.QueueStateHandler( OperationManager_StateHandler );
       
   481                 iOperationManager.Dispose();
       
   482             }
       
   483         }
       
   484         #endregion
       
   485 
       
   486         #region Internal properties
       
   487         internal ICIEngineUI UI
       
   488         {
       
   489             get { return iUI; }
       
   490         }
       
   491         #endregion
       
   492 
       
   493         #region From System.Object
       
   494         #endregion
       
   495 
       
   496         #region From ITracer 
       
   497         public void Trace( string aMessage )
       
   498         {
       
   499             UI.CITrace( aMessage );
       
   500         }
       
   501 
       
   502         public void Trace( string aFormat, params object[] aParams )
       
   503         {
       
   504             UI.CITrace( aFormat, aParams );
       
   505         }
       
   506         #endregion
       
   507 
       
   508         #region From IEnumerable<CIContainer>
       
   509         public IEnumerator<CIContainer> GetEnumerator()
       
   510         {
       
   511             lock ( iContainerCollection )
       
   512             {
       
   513                 foreach ( CIContainer container in iContainerCollection )
       
   514                 {
       
   515                     yield return container;
       
   516                 }
       
   517             }
       
   518         }
       
   519 
       
   520         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
       
   521         {
       
   522             lock ( iContainerCollection )
       
   523             {
       
   524                 foreach ( CIContainer container in iContainerCollection )
       
   525                 {
       
   526                     yield return container;
       
   527                 }
       
   528             }
       
   529         }
       
   530         #endregion
       
   531 
       
   532         #region From DisposableObject
       
   533         protected override void CleanupManagedResources()
       
   534         {
       
   535             try
       
   536             {
       
   537                 base.CleanupManagedResources();
       
   538             }
       
   539             finally
       
   540             {
       
   541                 DestroyIndexProcessor();
       
   542                 DestroySourceProcessor();
       
   543                 DestroyProblemDetectorManager();
       
   544                 DestroyOperationManager();
       
   545                 DestroyBlocker();
       
   546             }
       
   547         }
       
   548         #endregion
       
   549 
       
   550         #region Data members
       
   551         private readonly DbgEngine iDebugEngine;
       
   552         private readonly ICIEngineUI iUI;
       
   553         private readonly CIEnginePrimer iPrimer;
       
   554         private readonly CISinkManager iSinkManager;
       
   555         private readonly CFFPluginRegistry iPlugins;
       
   556         private readonly CIEngineSourceCollection iSources;
       
   557         private readonly CIContainerCollection iContainerCollection;
       
   558         private readonly CIEngineOperationManager iOperationManager;
       
   559         private readonly CIProblemDetectorManager iProblemDetectorManager;
       
   560         private readonly CIContainerIndex iContainerIndex;
       
   561         private ManualResetEvent iSynchronousBlocker = null;
       
   562         private CIEngineSourceProcessor iSourceProcessor = null;
       
   563         private CIContainerIndexProcessor  iIndexProcessor = null;
       
   564         private CIElementIdProvider iIdProvider = new CIElementIdProvider();
       
   565 		#endregion
       
   566     }
       
   567 }