crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianStackLib/Algorithms/StackAlgorithmManager.cs
changeset 0 818e61de6cd1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianStackLib/Algorithms/StackAlgorithmManager.cs	Thu Feb 11 15:50:58 2010 +0200
@@ -0,0 +1,419 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+* 
+* Description:
+*
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using SymbianDebugLib.Engine;
+using SymbianStackLib.Data.Output.Entry;
+using SymbianStackLib.Engine;
+using SymbianStackLib.Interfaces;
+using SymbianUtils;
+using SymbianUtils.PluginManager;
+using SymbianUtils.Range;
+
+namespace SymbianStackLib.Algorithms
+{
+    internal sealed class StackAlgorithmManager : DisposableObject, IStackAlgorithmObserver, IStackAlgorithmManager
+    {
+        #region Delegates & events
+        public enum TEvent
+        {
+            EAlgorithmStarted = 0,
+            EAlgorithmProgress,
+            EAlgorithmComplete
+        }
+
+        public delegate void AlgorithmEventHandler( StackAlgorithmManager aAlgManager, TEvent aEvent );
+        public event AlgorithmEventHandler EventHandler;
+
+        public delegate void AlgorithmExceptionHandler( StackAlgorithmManager aAlgManager, Exception aException );
+        public event AlgorithmExceptionHandler ExceptionHandler;
+        #endregion
+
+        #region Constructors
+        public StackAlgorithmManager( StackEngine aEngine )
+		{
+            iEngine = aEngine;
+            
+            // Make the view name based upon the stack address range
+            AddressRange range = aEngine.AddressInfo.Range;
+            StringBuilder viewName = new StringBuilder();
+            viewName.AppendFormat( "StackReconstructor_{0}_{1}", range, DateTime.Now.Ticks );
+            iView = iEngine.DebugEngine.CreateView( viewName.ToString(), iEngine.CodeSegments );
+        }
+		#endregion
+
+		#region API
+        public void Reconstruct( TSynchronicity aSynchronicity )
+        {
+            iSynchronicity = aSynchronicity;
+            try
+            {
+                PrepareForExecution();
+                ExecuteHeadAlgorithm();
+            }
+            catch ( Exception e )
+            {
+                // The only reason an exception should occur is if none of the algorithms indicate that
+                // they are ready to process stack data (probably because symbols were not provided). 
+                //
+                // In this situation, we must report the exception to our event handler
+                if ( ExceptionHandler != null && EventHandler != null )
+                {
+                    // Make sure we sent the 'start' and 'end' events as well - we cannot send
+                    // these events twice so it's okay to try to send them (will be ignored if
+                    // already sent).
+                    ReportEvent( TEvent.EAlgorithmStarted );
+                    
+                    // Now report the exception
+                    ExceptionHandler( this, e );
+
+                    // Indicate completion since we're not going to be able to do anything anymore
+                    ReportEvent( TEvent.EAlgorithmComplete );
+                }
+                else
+                {
+                    // No exception handler so just rethrow...
+                    throw e;
+                }
+            }
+        }
+		#endregion
+
+		#region Properties
+        public int Progress
+        {
+            get
+            {
+                // Scale the progress back to a fraction of the total
+                lock ( this )
+                {
+                    int totalProgressSoFar = iProgressValueCompleted + iProgressValueCurrent;
+                    float prog = ( (float) totalProgressSoFar ) / ( (float) iProgressValueMax );
+                    prog *= 100.0f;
+                    return (int) prog;
+                }
+            }
+        }
+        #endregion
+
+        #region From IStackAlgorithmObserver
+        public void StackBuildingStarted( StackAlgorithm aAlg )
+        {
+            Trace( "[SBAlgManager] StackBuildingStarted() - aAlg: {0}", aAlg );
+            ReportEvent( TEvent.EAlgorithmStarted );
+        }
+
+        public void StackBuldingProgress( StackAlgorithm aAlg, int aPercent )
+        {
+            Trace( "[SBAlgManager] StackBuldingProgress() - aAlg: {0}, aPercent: {1}", aAlg, aPercent );
+            lock ( this )
+            {
+                iProgressValueCurrent = aPercent;
+            }
+            //
+            ReportEvent( TEvent.EAlgorithmProgress );
+        }
+
+        public void StackBuildingComplete( StackAlgorithm aAlg )
+        {
+            // If the algorithm is still queued then everything went okay. If not, then we
+            // had an exception and we should therefore ignore the completion as the algorithm
+            // terminated unexpectedly.
+            bool stillExists = iExecutionQueue.Contains( aAlg );
+            Trace( "[SBAlgManager] StackBuildingComplete() - aAlg: {0}, stillExists: {1}", aAlg, stillExists );
+            if ( stillExists )
+            {
+                iExecutionQueue.Clear();
+                ReportEvent( TEvent.EAlgorithmComplete );
+            }
+        }
+
+        public void StackBuildingElementConstructed( StackAlgorithm aAlg, StackOutputEntry aEntry )
+        {
+            lock ( this )
+            {
+                iEngine.DataOutput.InsertAsFirstEntry( aEntry );
+            }
+        }
+
+        public void StackBuildingException( StackAlgorithm aAlg, Exception aException )
+        {
+            Trace( "[SBAlgManager] STACK ALG EXCEPTION: " + aException.Message );
+            Trace( "[SBAlgManager] {0}", aException.StackTrace );
+
+            StackAlgorithm alg = CurrentAlgorithm;
+
+            // If we're executing using the fallback entry, then we're in trouble. 
+            // There is nothing we can do besides report the problem upwards.
+            if ( iExecutionQueue.Count == 1 )
+            {
+                if ( ExceptionHandler != null )
+                {
+                    ExceptionHandler( this, aException );
+                }
+            }
+            else
+            {
+                // Report event
+                string message = string.Format( LibResources.StackAlgorithmManager_FailedAlgorithmWarning + System.Environment.NewLine + "{1}", 
+                                                alg.Name, aException.Message.ToString() 
+                                                );
+                iEngine.ReportMessage( StackEngine.TMessageType.ETypeWarning, message );
+
+                // The primary algorithm has failed, let's roll back to the secondary
+                // by dumping the primary algorithm and starting again.
+                iExecutionQueue.Dequeue();
+                iEngine.DataOutput.Clear();
+
+                // Reset progress.
+                iProgressValueCompleted += 100;
+                iProgressValueCurrent = 0;
+
+                // Start next algorithm...
+                ExecuteHeadAlgorithm();
+            }
+        }
+        #endregion
+
+        #region From IStackAlgorithmManager
+        public StackEngine Engine
+        {
+            get { return iEngine; }
+        }
+
+        public DbgEngineView DebugEngineView
+        {
+            get { return iView; }
+        }
+
+        public void Trace( string aMessage )
+        {
+            iEngine.Trace( aMessage );
+        }
+
+        public void Trace( string aFormat, params object[] aParams )
+        {
+            iEngine.Trace( aFormat, aParams );
+        }
+        #endregion
+
+        #region From DisposableObject
+        protected override void CleanupManagedResources()
+        {
+            try
+            {
+                base.CleanupManagedResources();
+            }
+            finally
+            {
+                if ( iMasterAlgorithmTable != null )
+                {
+                    iMasterAlgorithmTable.Dispose();
+                    iMasterAlgorithmTable = null;
+                }
+                
+                if ( iView != null )
+                {
+                    iView.Dispose();
+                    iView = null;
+                }
+            }
+        }
+        #endregion
+
+        #region Internal properties
+        private StackAlgorithm CurrentAlgorithm
+        {
+            get
+            {
+                if ( iExecutionQueue.Count == 0 )
+                {
+                    throw new Exception( "No stack algorithms available" );
+                }
+                //
+                return iExecutionQueue.Peek();
+            }
+        }
+		#endregion
+
+        #region Internal methods
+        private void PrepareForExecution()
+        {
+            Trace( "[SBAlgManager] PrepareForExecution() - START" );
+
+            // Validate address info
+            iEngine.AddressInfo.Validate();
+
+            // Clear data output
+            iEngine.DataOutput.Clear();
+
+            // Reset master list
+            IStackAlgorithmManager manager = (IStackAlgorithmManager) this;
+            IStackAlgorithmObserver observer = (IStackAlgorithmObserver) this;
+            iMasterAlgorithmTable.Load( new object[] { manager, observer } );
+            SortAlgorithms();
+
+            // Build list of algorithms we'll try to use
+            PrepareExecutionQueue();
+
+            // Work out maximum progress value for this operation
+            int numberOfPendingAlgs = iExecutionQueue.Count;
+            iProgressValueMax = numberOfPendingAlgs * 100;
+
+            // Reset current progress
+            iProgressValueCurrent = 0;
+            iProgressValueCompleted = 0;
+
+            Trace( "[SBAlgManager] PrepareForExecution() - END" );
+        }
+
+        private void PrepareExecutionQueue()
+        {
+            iExecutionQueue.Clear();
+            
+            // Find most appropriate algorithm...
+            StackAlgorithm primary = FindPrimaryAlgorithm();
+            if ( primary != null )
+            {
+                iExecutionQueue.Enqueue( primary );
+
+                // Find backup algorithms
+                EnqueueBackupAlgorithms( primary );
+            }
+            else
+            {
+                throw new Exception( "No valid stack algorithms available" );
+            }
+        }
+
+        private StackAlgorithm FindPrimaryAlgorithm()
+        {
+            StackAlgorithm ret = null;
+            //
+            foreach ( StackAlgorithm alg in iMasterAlgorithmTable )
+            {
+                if ( alg.IsAvailable() )
+                {
+                    ret = alg;
+                    break;
+                }
+            }
+            //
+            Trace( "[SBAlgManager] FindPrimaryAlgorithm() - ret: {0}", ret );
+            return ret;
+        }
+
+        private void EnqueueBackupAlgorithms( StackAlgorithm aExclude )
+        {
+            foreach ( StackAlgorithm alg in iMasterAlgorithmTable )
+            {
+                string name = alg.Name;
+                bool available = alg.IsAvailable();
+                Trace( "[SBAlgManager] EnqueueBackupAlgorithms() - name: {0}, available: {1}", name, available );
+
+                if ( available && name != aExclude.Name )
+                {
+                    iExecutionQueue.Enqueue( alg );
+                }
+            }
+        }
+
+        private void ExecuteHeadAlgorithm()
+        {
+            Trace( "[SBAlgManager] ExecuteHeadAlgorithm() - iSynchronicity: {0}", iSynchronicity );
+            StackAlgorithm alg = CurrentAlgorithm;
+            alg.BuildStack( iSynchronicity );
+        }
+
+        private void SortAlgorithms()
+        {
+            Comparison<StackAlgorithm> sorter = delegate( StackAlgorithm aLeft, StackAlgorithm aRight )
+            {
+                int ret = 1;
+                //
+                if ( aLeft == null )
+                {
+                    ret = -1;
+                }
+                else if ( aRight == null )
+                {
+                }
+                else
+                {
+                    ret = aLeft.Priority.CompareTo( aRight.Priority );
+                }
+                //
+                return ret;
+            };
+            iMasterAlgorithmTable.Sort( sorter );
+        }
+
+        private void ReportEvent( TEvent aEvent )
+        {
+            // Ensure we only report significant events once
+            if ( EventHandler != null )
+            {
+                switch ( aEvent )
+                {
+                case TEvent.EAlgorithmStarted:
+                    if ( ( iFlags & TFlags.EFlagsReportedStarted ) != TFlags.EFlagsReportedStarted )
+                    {
+                        iFlags |= TFlags.EFlagsReportedStarted;
+                        EventHandler( this, aEvent );
+                    }
+                    break;
+                case TEvent.EAlgorithmComplete:
+                    if ( ( iFlags & TFlags.EFlagsReportedComplete ) != TFlags.EFlagsReportedComplete )
+                    {
+                        iFlags |= TFlags.EFlagsReportedComplete;
+                        EventHandler( this, aEvent );
+                    }
+                    break;
+                default:
+                    EventHandler( this, aEvent );
+                    break;
+                }
+            }
+        }
+        #endregion
+
+        #region Internal enumerations
+        [Flags]
+        private enum TFlags
+        {
+            EFlagsNone = 0,
+            EFlagsReportedStarted = 1,
+            EFlagsReportedComplete = 2
+        }
+        #endregion
+
+        #region Data members
+        private readonly StackEngine iEngine;
+        private DbgEngineView iView;
+        private PluginManager<StackAlgorithm> iMasterAlgorithmTable = new PluginManager<StackAlgorithm>( 2 );
+        
+        // Transient variables
+        private TSynchronicity iSynchronicity = TSynchronicity.EAsynchronous;
+        private Queue<StackAlgorithm> iExecutionQueue = new Queue<StackAlgorithm>();
+        private int iProgressValueMax = 0;
+        private int iProgressValueCompleted = 0;
+        private int iProgressValueCurrent = 0;
+        private TFlags iFlags = TFlags.EFlagsNone;
+        #endregion
+    }
+}