crashanalysercmd/Libraries/Engine/CrashItemLib/PluginAPI/FW/CFFReader.cs
author Jussi Ryoma <ext-jussi.s.ryoma@nokia.com>
Fri, 27 Aug 2010 12:21:46 +0300
changeset 3 045ade241ef5
parent 0 818e61de6cd1
permissions -rw-r--r--
Version 1.0.13. The most important changes are: -detailed defect hash added -panic descriptions updated -release build is working -simple command line usage added

/*
* 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.IO;
using System.Collections.Generic;
using System.Text;
using SymbianUtils;
using SymbianDebugLib.Engine;
using CrashItemLib.Crash;
using CrashItemLib.Engine;

namespace CrashItemLib.PluginAPI
{
	public abstract class CFFReader
	{
        #region Enumerations
        public enum TState
        {
            EStateUninitialised = 0,
            EStateProcessing,
            EStateReady,
            EStateCorrupt
        }
        #endregion

        #region Delegates & events
		public enum TEvent
		{
			EReadingStarted = 0,
			EReadingProgress,
            EReadingContainerCreated,
			EReadingComplete,
		}

		public delegate void ReaderObserver( TEvent aEvent, CFFReader aReader, object aContext );
        public event ReaderObserver Observer;

        public delegate void ReaderExceptionHandler( Exception aException, CFFReader aReader );
        public event ReaderExceptionHandler ExceptionHandler;
		#endregion

		#region Constructors
		protected CFFReader( CFFPlugin aEngine, CFFSource aDescriptor )
		{
            iPlugin = aEngine;
            iDescriptor = aDescriptor;
		}
		#endregion

		#region API - abstract
        /// <summary>
        /// Called when Crash Analyser wants this plugin to read a
        /// native, i.e. format-specific crash file (i.e. not a trace file) 
        /// synchronously.
        /// </summary>
        public virtual void NativeReadInit()
        {
        }

        /// <summary>
        /// Called when Crash Analyser is going to start to send
        /// trace lines (that it will read on behalf of the plugin)
        /// that should be processed in order to identify embedded
        /// traces.
        /// 
        /// This method will only be called if the plugin claims to have
        /// some confidence in reading trace data.
        /// </summary>
        public virtual void TraceReadInit()
        {
        }

        /// <summary>
        /// Receive an individual trace line and process it if relevant
        /// </summary>
        /// <param name="aLine"></param>
        public virtual bool TraceReadOffer( CFFTraceLine aLine )
        {
            // Nothing to do
            return false;
        }

        /// <summary>
        /// Called when all trace lines have been delivered
        /// </summary>
        public virtual void TraceReadComplete()
        {
        }
		#endregion

        #region API - framework
        protected byte[] RawData
        {
            get { return Descriptor.RawData; }
        }

        protected void RawDataAdd()
        {
            // Save entire file
            RawDataClear();
            RawDataAdd( Descriptor.MasterFile );
        }

        protected void RawDataAdd( FileInfo aFile )
        {
            byte[] bytes = File.ReadAllBytes( aFile.FullName );
            RawDataAdd( bytes );
        }

        protected void RawDataClear()
        {
            Descriptor.RawDataClear();
        }

        protected void RawDataAdd( byte[] aRawData )
        {
            Descriptor.RawDataAdd( aRawData );
        }
        #endregion

        #region Properties
        public TState State
        {
            get
            {
                lock ( this )
                {
                    return iState;
                }
            }
            set
            {
                lock ( this )
                {
                    iState = value;
                }
            }
        }

        public CFFPlugin Plugin
        {
            get { return iPlugin; }
        }

        public CFFSource Descriptor
        {
            get { return iDescriptor; }
        }

        public CIEngine CIEngine
		{
            get { return Plugin.DataProvider.Engine; }
		}
		#endregion

		#region Internal methods
		protected void NotifyEvent( TEvent aEvent )
		{
            NotifyEvent( aEvent, null );
		}

        protected void NotifyEvent( TEvent aEvent, object aContext )
        {
            // We must notify about "reading started" and "reading complete" only
            // once.
            //
            // When the plugin sends the "reading started" event, we must transition
            // to 'EStateProcessing.'
            //
            // When the plugin sends the "reading complete" event, we must transition
            // to 'EStateReady' except if there was an exception during processing,
            // in which case we remain as 'EStateCorrupt.'
            //
            // NB: NotifyException makes the transition to EStateCorrupt.
            //
            TState oldState = State;
            //
            bool notify = false;
            switch ( aEvent )
            {
            case TEvent.EReadingContainerCreated:
                notify = true;
                break;
            case TEvent.EReadingStarted:
                State = TState.EStateProcessing;
                notify = ( State != oldState );
                break;
            case TEvent.EReadingProgress:
                notify = true;
                break;
            case TEvent.EReadingComplete:
                if ( State == TState.EStateCorrupt )
                {
                    // There was an exception during processing. Do not
                    // change to 'ready' state in this situation.
                    // 
                    // However, we must still notify about the completion event!
                    notify = true;
                }
                else
                {
                    State = TState.EStateReady;
                    notify = ( State != oldState );
                }
                break;
            default:
                throw new NotSupportedException();
            }
            
            if ( notify )
            {
                if ( Observer != null )
                {
                    Observer( aEvent, this, aContext );
                }
            }
        }

        protected void NotifyException( Exception aException )
        {
            State = TState.EStateCorrupt;
            //
            if ( ExceptionHandler != null )
            {
                ExceptionHandler( aException, this );
            }
        }
		#endregion

        #region Internal methods - called by CIEngineSource to carry out operations
        internal void OnNativeReadInit()
        {
            // Indicate reading started
            NotifyEvent( TEvent.EReadingStarted );
            try
            {
                NativeReadInit();
            }
            catch ( Exception e )
            {
                NotifyException( e );
                NotifyEvent( TEvent.EReadingComplete );
            }
        }

        internal void OnTraceReadInit()
        {
            // Indicate reading started
            NotifyEvent( TEvent.EReadingStarted );
            try
            {
                TraceReadInit();
            }
            catch ( Exception e )
            {
                NotifyException( e );
                NotifyEvent( TEvent.EReadingComplete );
            }
        }

        internal void OnTraceReadOffer( CFFTraceLine aLine )
        {
            try
            {
                bool consumed = TraceReadOffer( aLine );
                if ( consumed )
                {
                    RawDataAdd( aLine.ToBinary() );
                }
            }
            catch ( Exception e )
            {
                NotifyException( e );
            }
        }

        internal void OnTraceReadComplete()
        {
            try
            {
                TraceReadComplete();
            }
            catch ( Exception e )
            {
                NotifyException( e );
                NotifyEvent( TEvent.EReadingComplete );
            }
        }
        #endregion

		#region Data members
        private TState iState = TState.EStateUninitialised;
        private readonly CFFPlugin iPlugin;
        private readonly CFFSource iDescriptor;
		#endregion
	}
}