crashanalysercmd/Libraries/Engine/CrashItemLib/Crash/Container/CIContainerIndexProcessor.cs
author Matti Laitinen <matti.t.laitinen@nokia.com>
Thu, 11 Feb 2010 15:50:58 +0200
changeset 0 818e61de6cd1
permissions -rw-r--r--
Add initial version of Crash Analyser cmdline under EPL

/*
* 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.Threading;
using SymbianUtils;
using SymbianDebugLib.Engine;
using SymbianDebugLib.Entity.Configurations;
using CrashItemLib.Engine;
using System;
using CrashItemLib.Crash.Messages;

namespace CrashItemLib.Crash.Container
{
    internal class CIContainerIndexProcessor
    {
        #region Enumerations
        public enum TEvent
        {
            EEventStarting = 0,
            EEventCompleted
        }
        #endregion

        #region Delegates & events
        public delegate void ProcessorEventHandler( TEvent aEvent );
        public event ProcessorEventHandler EventHandler = delegate { };
        #endregion

        #region Constructors
        public CIContainerIndexProcessor( CIContainerIndex aIndex, CIEngine aEngine )
        {
            iIndex = aIndex;
            iEngine = aEngine;
        }
        #endregion

        #region API
        public void Start( TSynchronicity aSynchronicity )
        {
            if ( aSynchronicity == TSynchronicity.EAsynchronous )
            {
                ThreadPool.QueueUserWorkItem( new WaitCallback( RunWorker ) );
            }
            else
            {
                RunWorker();
            }
        }
        #endregion
        
        #region Properties
        #endregion

        #region Internal methods
        private void RunWorker()
        {            
            RunWorker(null);
        }

        private void RunWorker( object aNotUsed )
        {
            iEngine.Trace( "[CIContainerIndexProcessor] RunWorker() - START - index groupings: {0}", iIndex.Count );

            EventHandler( TEvent.EEventStarting );

            DbgEngine debugEngine = iEngine.DebugEngine;
            bool needToPrimeDebugEngine = debugEngine.MetaDataConfig.IsConfigurationDataAvailable;
            iEngine.Trace( "[CIContainerIndexProcessor] RunWorker() - needToPrimeDebugEngine: {0}", needToPrimeDebugEngine );

            // Process the index "buckets" until all are exhausted.
            for ( CIContainerCollection collection = iIndex.DequeueNextContainer(); collection != null; collection = iIndex.DequeueNextContainer() )
            {
                try
                {
                    if ( collection.Count > 0 )
                    {
                        // Get the rom serial number - all containers in the collection share a common serial
                        uint serialNumber = CIContainerIndex.GetRomChecksum( collection[ 0 ] );
                        iEngine.Trace( "[CIContainerIndexProcessor] RunWorker() - {0} containers for rom checksum: 0x{1:x8}", collection.Count, serialNumber );

                        // Prepare debug engine meta-data as needed.
                        if ( needToPrimeDebugEngine )
                        {
                            DbgEntityConfigIdentifier identifier = new DbgEntityConfigIdentifier( serialNumber );

                            iEngine.Trace( "[CIContainerIndexProcessor] RunWorker() - synchronously switching debug meta-data config..." );
                            debugEngine.ConfigManager.SwitchConfigurationSynchronously( identifier );
                            iEngine.Trace( "[CIContainerIndexProcessor] RunWorker() - switch complete." );
                        }

                        // Process the list of crash item containers in separate threads until all are handled.
                        // This is quite a heavyweight operation since it also potentially primes the debug engine with
                        // the needed symbols and then finalizes every associated crash container.
                        // However, we run this in a separate thread so it will not block the UI.
                        iEngine.Trace( "[CIContainerIndexProcessor] RunWorker() - running finalizer for {0} items with rom checksum: 0x{1:x8}", collection.Count, serialNumber );

                        // We wait until the finalizer is finished, but we're running in a worker thread so this is OK.
                        CIContainerFinalizer finalizer = new CIContainerFinalizer( collection, iEngine );
                        finalizer.Start( SymbianUtils.TSynchronicity.ESynchronous );

                        iEngine.Trace( "[CIContainerIndexProcessor] RunWorker() - finalization complete for {0} items with rom checksum: 0x{1:x8}", collection.Count, serialNumber );
                    }
                }                       
                catch (Exception e)
                {
                    iEngine.Trace("Error: RunWorker() hit an unexpected exception!");

                    foreach (CIContainer container in collection)
                    {
                        CIMessageError error = new CIMessageError(container, "RunWorker failed");
                        error.AddLine("Unexpected exception encountered during container processing - analysis has failed!");
                        container.Messages.Add(error);
                    }
                }
            }
            iEngine.Trace( "[CIContainerIndexProcessor] RunWorker() - Notifying about completion..." );

            EventHandler( TEvent.EEventCompleted );

            iEngine.Trace( "[CIContainerIndexProcessor] RunWorker() - END" );
        }
        #endregion

        #region Data members
        private readonly CIContainerIndex iIndex;
        private readonly CIEngine iEngine;
        #endregion
    }
}