crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianStackLib/Algorithms/StackAlgorithmManager.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.Text;
       
    20 using SymbianDebugLib.Engine;
       
    21 using SymbianStackLib.Data.Output.Entry;
       
    22 using SymbianStackLib.Engine;
       
    23 using SymbianStackLib.Interfaces;
       
    24 using SymbianUtils;
       
    25 using SymbianUtils.PluginManager;
       
    26 using SymbianUtils.Range;
       
    27 
       
    28 namespace SymbianStackLib.Algorithms
       
    29 {
       
    30     internal sealed class StackAlgorithmManager : DisposableObject, IStackAlgorithmObserver, IStackAlgorithmManager
       
    31     {
       
    32         #region Delegates & events
       
    33         public enum TEvent
       
    34         {
       
    35             EAlgorithmStarted = 0,
       
    36             EAlgorithmProgress,
       
    37             EAlgorithmComplete
       
    38         }
       
    39 
       
    40         public delegate void AlgorithmEventHandler( StackAlgorithmManager aAlgManager, TEvent aEvent );
       
    41         public event AlgorithmEventHandler EventHandler;
       
    42 
       
    43         public delegate void AlgorithmExceptionHandler( StackAlgorithmManager aAlgManager, Exception aException );
       
    44         public event AlgorithmExceptionHandler ExceptionHandler;
       
    45         #endregion
       
    46 
       
    47         #region Constructors
       
    48         public StackAlgorithmManager( StackEngine aEngine )
       
    49 		{
       
    50             iEngine = aEngine;
       
    51             
       
    52             // Make the view name based upon the stack address range
       
    53             AddressRange range = aEngine.AddressInfo.Range;
       
    54             StringBuilder viewName = new StringBuilder();
       
    55             viewName.AppendFormat( "StackReconstructor_{0}_{1}", range, DateTime.Now.Ticks );
       
    56             iView = iEngine.DebugEngine.CreateView( viewName.ToString(), iEngine.CodeSegments );
       
    57         }
       
    58 		#endregion
       
    59 
       
    60 		#region API
       
    61         public void Reconstruct( TSynchronicity aSynchronicity )
       
    62         {
       
    63             iSynchronicity = aSynchronicity;
       
    64             try
       
    65             {
       
    66                 PrepareForExecution();
       
    67                 ExecuteHeadAlgorithm();
       
    68             }
       
    69             catch ( Exception e )
       
    70             {
       
    71                 // The only reason an exception should occur is if none of the algorithms indicate that
       
    72                 // they are ready to process stack data (probably because symbols were not provided). 
       
    73                 //
       
    74                 // In this situation, we must report the exception to our event handler
       
    75                 if ( ExceptionHandler != null && EventHandler != null )
       
    76                 {
       
    77                     // Make sure we sent the 'start' and 'end' events as well - we cannot send
       
    78                     // these events twice so it's okay to try to send them (will be ignored if
       
    79                     // already sent).
       
    80                     ReportEvent( TEvent.EAlgorithmStarted );
       
    81                     
       
    82                     // Now report the exception
       
    83                     ExceptionHandler( this, e );
       
    84 
       
    85                     // Indicate completion since we're not going to be able to do anything anymore
       
    86                     ReportEvent( TEvent.EAlgorithmComplete );
       
    87                 }
       
    88                 else
       
    89                 {
       
    90                     // No exception handler so just rethrow...
       
    91                     throw e;
       
    92                 }
       
    93             }
       
    94         }
       
    95 		#endregion
       
    96 
       
    97 		#region Properties
       
    98         public int Progress
       
    99         {
       
   100             get
       
   101             {
       
   102                 // Scale the progress back to a fraction of the total
       
   103                 lock ( this )
       
   104                 {
       
   105                     int totalProgressSoFar = iProgressValueCompleted + iProgressValueCurrent;
       
   106                     float prog = ( (float) totalProgressSoFar ) / ( (float) iProgressValueMax );
       
   107                     prog *= 100.0f;
       
   108                     return (int) prog;
       
   109                 }
       
   110             }
       
   111         }
       
   112         #endregion
       
   113 
       
   114         #region From IStackAlgorithmObserver
       
   115         public void StackBuildingStarted( StackAlgorithm aAlg )
       
   116         {
       
   117             Trace( "[SBAlgManager] StackBuildingStarted() - aAlg: {0}", aAlg );
       
   118             ReportEvent( TEvent.EAlgorithmStarted );
       
   119         }
       
   120 
       
   121         public void StackBuldingProgress( StackAlgorithm aAlg, int aPercent )
       
   122         {
       
   123             Trace( "[SBAlgManager] StackBuldingProgress() - aAlg: {0}, aPercent: {1}", aAlg, aPercent );
       
   124             lock ( this )
       
   125             {
       
   126                 iProgressValueCurrent = aPercent;
       
   127             }
       
   128             //
       
   129             ReportEvent( TEvent.EAlgorithmProgress );
       
   130         }
       
   131 
       
   132         public void StackBuildingComplete( StackAlgorithm aAlg )
       
   133         {
       
   134             // If the algorithm is still queued then everything went okay. If not, then we
       
   135             // had an exception and we should therefore ignore the completion as the algorithm
       
   136             // terminated unexpectedly.
       
   137             bool stillExists = iExecutionQueue.Contains( aAlg );
       
   138             Trace( "[SBAlgManager] StackBuildingComplete() - aAlg: {0}, stillExists: {1}", aAlg, stillExists );
       
   139             if ( stillExists )
       
   140             {
       
   141                 iExecutionQueue.Clear();
       
   142                 ReportEvent( TEvent.EAlgorithmComplete );
       
   143             }
       
   144         }
       
   145 
       
   146         public void StackBuildingElementConstructed( StackAlgorithm aAlg, StackOutputEntry aEntry )
       
   147         {
       
   148             lock ( this )
       
   149             {
       
   150                 iEngine.DataOutput.InsertAsFirstEntry( aEntry );
       
   151             }
       
   152         }
       
   153 
       
   154         public void StackBuildingException( StackAlgorithm aAlg, Exception aException )
       
   155         {
       
   156             Trace( "[SBAlgManager] STACK ALG EXCEPTION: " + aException.Message );
       
   157             Trace( "[SBAlgManager] {0}", aException.StackTrace );
       
   158 
       
   159             StackAlgorithm alg = CurrentAlgorithm;
       
   160 
       
   161             // If we're executing using the fallback entry, then we're in trouble. 
       
   162             // There is nothing we can do besides report the problem upwards.
       
   163             if ( iExecutionQueue.Count == 1 )
       
   164             {
       
   165                 if ( ExceptionHandler != null )
       
   166                 {
       
   167                     ExceptionHandler( this, aException );
       
   168                 }
       
   169             }
       
   170             else
       
   171             {
       
   172                 // Report event
       
   173                 string message = string.Format( LibResources.StackAlgorithmManager_FailedAlgorithmWarning + System.Environment.NewLine + "{1}", 
       
   174                                                 alg.Name, aException.Message.ToString() 
       
   175                                                 );
       
   176                 iEngine.ReportMessage( StackEngine.TMessageType.ETypeWarning, message );
       
   177 
       
   178                 // The primary algorithm has failed, let's roll back to the secondary
       
   179                 // by dumping the primary algorithm and starting again.
       
   180                 iExecutionQueue.Dequeue();
       
   181                 iEngine.DataOutput.Clear();
       
   182 
       
   183                 // Reset progress.
       
   184                 iProgressValueCompleted += 100;
       
   185                 iProgressValueCurrent = 0;
       
   186 
       
   187                 // Start next algorithm...
       
   188                 ExecuteHeadAlgorithm();
       
   189             }
       
   190         }
       
   191         #endregion
       
   192 
       
   193         #region From IStackAlgorithmManager
       
   194         public StackEngine Engine
       
   195         {
       
   196             get { return iEngine; }
       
   197         }
       
   198 
       
   199         public DbgEngineView DebugEngineView
       
   200         {
       
   201             get { return iView; }
       
   202         }
       
   203 
       
   204         public void Trace( string aMessage )
       
   205         {
       
   206             iEngine.Trace( aMessage );
       
   207         }
       
   208 
       
   209         public void Trace( string aFormat, params object[] aParams )
       
   210         {
       
   211             iEngine.Trace( aFormat, aParams );
       
   212         }
       
   213         #endregion
       
   214 
       
   215         #region From DisposableObject
       
   216         protected override void CleanupManagedResources()
       
   217         {
       
   218             try
       
   219             {
       
   220                 base.CleanupManagedResources();
       
   221             }
       
   222             finally
       
   223             {
       
   224                 if ( iMasterAlgorithmTable != null )
       
   225                 {
       
   226                     iMasterAlgorithmTable.Dispose();
       
   227                     iMasterAlgorithmTable = null;
       
   228                 }
       
   229                 
       
   230                 if ( iView != null )
       
   231                 {
       
   232                     iView.Dispose();
       
   233                     iView = null;
       
   234                 }
       
   235             }
       
   236         }
       
   237         #endregion
       
   238 
       
   239         #region Internal properties
       
   240         private StackAlgorithm CurrentAlgorithm
       
   241         {
       
   242             get
       
   243             {
       
   244                 if ( iExecutionQueue.Count == 0 )
       
   245                 {
       
   246                     throw new Exception( "No stack algorithms available" );
       
   247                 }
       
   248                 //
       
   249                 return iExecutionQueue.Peek();
       
   250             }
       
   251         }
       
   252 		#endregion
       
   253 
       
   254         #region Internal methods
       
   255         private void PrepareForExecution()
       
   256         {
       
   257             Trace( "[SBAlgManager] PrepareForExecution() - START" );
       
   258 
       
   259             // Validate address info
       
   260             iEngine.AddressInfo.Validate();
       
   261 
       
   262             // Clear data output
       
   263             iEngine.DataOutput.Clear();
       
   264 
       
   265             // Reset master list
       
   266             IStackAlgorithmManager manager = (IStackAlgorithmManager) this;
       
   267             IStackAlgorithmObserver observer = (IStackAlgorithmObserver) this;
       
   268             iMasterAlgorithmTable.Load( new object[] { manager, observer } );
       
   269             SortAlgorithms();
       
   270 
       
   271             // Build list of algorithms we'll try to use
       
   272             PrepareExecutionQueue();
       
   273 
       
   274             // Work out maximum progress value for this operation
       
   275             int numberOfPendingAlgs = iExecutionQueue.Count;
       
   276             iProgressValueMax = numberOfPendingAlgs * 100;
       
   277 
       
   278             // Reset current progress
       
   279             iProgressValueCurrent = 0;
       
   280             iProgressValueCompleted = 0;
       
   281 
       
   282             Trace( "[SBAlgManager] PrepareForExecution() - END" );
       
   283         }
       
   284 
       
   285         private void PrepareExecutionQueue()
       
   286         {
       
   287             iExecutionQueue.Clear();
       
   288             
       
   289             // Find most appropriate algorithm...
       
   290             StackAlgorithm primary = FindPrimaryAlgorithm();
       
   291             if ( primary != null )
       
   292             {
       
   293                 iExecutionQueue.Enqueue( primary );
       
   294 
       
   295                 // Find backup algorithms
       
   296                 EnqueueBackupAlgorithms( primary );
       
   297             }
       
   298             else
       
   299             {
       
   300                 throw new Exception( "No valid stack algorithms available" );
       
   301             }
       
   302         }
       
   303 
       
   304         private StackAlgorithm FindPrimaryAlgorithm()
       
   305         {
       
   306             StackAlgorithm ret = null;
       
   307             //
       
   308             foreach ( StackAlgorithm alg in iMasterAlgorithmTable )
       
   309             {
       
   310                 if ( alg.IsAvailable() )
       
   311                 {
       
   312                     ret = alg;
       
   313                     break;
       
   314                 }
       
   315             }
       
   316             //
       
   317             Trace( "[SBAlgManager] FindPrimaryAlgorithm() - ret: {0}", ret );
       
   318             return ret;
       
   319         }
       
   320 
       
   321         private void EnqueueBackupAlgorithms( StackAlgorithm aExclude )
       
   322         {
       
   323             foreach ( StackAlgorithm alg in iMasterAlgorithmTable )
       
   324             {
       
   325                 string name = alg.Name;
       
   326                 bool available = alg.IsAvailable();
       
   327                 Trace( "[SBAlgManager] EnqueueBackupAlgorithms() - name: {0}, available: {1}", name, available );
       
   328 
       
   329                 if ( available && name != aExclude.Name )
       
   330                 {
       
   331                     iExecutionQueue.Enqueue( alg );
       
   332                 }
       
   333             }
       
   334         }
       
   335 
       
   336         private void ExecuteHeadAlgorithm()
       
   337         {
       
   338             Trace( "[SBAlgManager] ExecuteHeadAlgorithm() - iSynchronicity: {0}", iSynchronicity );
       
   339             StackAlgorithm alg = CurrentAlgorithm;
       
   340             alg.BuildStack( iSynchronicity );
       
   341         }
       
   342 
       
   343         private void SortAlgorithms()
       
   344         {
       
   345             Comparison<StackAlgorithm> sorter = delegate( StackAlgorithm aLeft, StackAlgorithm aRight )
       
   346             {
       
   347                 int ret = 1;
       
   348                 //
       
   349                 if ( aLeft == null )
       
   350                 {
       
   351                     ret = -1;
       
   352                 }
       
   353                 else if ( aRight == null )
       
   354                 {
       
   355                 }
       
   356                 else
       
   357                 {
       
   358                     ret = aLeft.Priority.CompareTo( aRight.Priority );
       
   359                 }
       
   360                 //
       
   361                 return ret;
       
   362             };
       
   363             iMasterAlgorithmTable.Sort( sorter );
       
   364         }
       
   365 
       
   366         private void ReportEvent( TEvent aEvent )
       
   367         {
       
   368             // Ensure we only report significant events once
       
   369             if ( EventHandler != null )
       
   370             {
       
   371                 switch ( aEvent )
       
   372                 {
       
   373                 case TEvent.EAlgorithmStarted:
       
   374                     if ( ( iFlags & TFlags.EFlagsReportedStarted ) != TFlags.EFlagsReportedStarted )
       
   375                     {
       
   376                         iFlags |= TFlags.EFlagsReportedStarted;
       
   377                         EventHandler( this, aEvent );
       
   378                     }
       
   379                     break;
       
   380                 case TEvent.EAlgorithmComplete:
       
   381                     if ( ( iFlags & TFlags.EFlagsReportedComplete ) != TFlags.EFlagsReportedComplete )
       
   382                     {
       
   383                         iFlags |= TFlags.EFlagsReportedComplete;
       
   384                         EventHandler( this, aEvent );
       
   385                     }
       
   386                     break;
       
   387                 default:
       
   388                     EventHandler( this, aEvent );
       
   389                     break;
       
   390                 }
       
   391             }
       
   392         }
       
   393         #endregion
       
   394 
       
   395         #region Internal enumerations
       
   396         [Flags]
       
   397         private enum TFlags
       
   398         {
       
   399             EFlagsNone = 0,
       
   400             EFlagsReportedStarted = 1,
       
   401             EFlagsReportedComplete = 2
       
   402         }
       
   403         #endregion
       
   404 
       
   405         #region Data members
       
   406         private readonly StackEngine iEngine;
       
   407         private DbgEngineView iView;
       
   408         private PluginManager<StackAlgorithm> iMasterAlgorithmTable = new PluginManager<StackAlgorithm>( 2 );
       
   409         
       
   410         // Transient variables
       
   411         private TSynchronicity iSynchronicity = TSynchronicity.EAsynchronous;
       
   412         private Queue<StackAlgorithm> iExecutionQueue = new Queue<StackAlgorithm>();
       
   413         private int iProgressValueMax = 0;
       
   414         private int iProgressValueCompleted = 0;
       
   415         private int iProgressValueCurrent = 0;
       
   416         private TFlags iFlags = TFlags.EFlagsNone;
       
   417         #endregion
       
   418     }
       
   419 }