diff -r 000000000000 -r 818e61de6cd1 crashanalysercmd/Libraries/Engine/CrashItemLib/Engine/Sources/Types/CIEngineSourceReaderTrace.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crashanalysercmd/Libraries/Engine/CrashItemLib/Engine/Sources/Types/CIEngineSourceReaderTrace.cs Thu Feb 11 15:50:58 2010 +0200 @@ -0,0 +1,302 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; +using SymbianUtils; +using CrashItemLib.PluginAPI; +using CrashItemLib.Crash.Source; +using CrashItemLib.Crash.Container; + +namespace CrashItemLib.Engine.Sources.Types +{ + internal sealed class CIEngineSourceReaderTrace : CIEngineSourceReader + { + #region Constructors + public CIEngineSourceReaderTrace( CIEngineSource aSource, CFFSource[] aPluginSources ) + : base( aSource ) + { + iPluginSources.AddRange( aPluginSources ); + } + #endregion + + #region From CIEngineSourceReader + public override CIEngineSource.TState Read() + { + CIEngineSource.TState ret = CIEngineSource.TState.EStateReadyCorrupt; + + // Listen to container creation events in all plugin reader objects + foreach ( CFFSource source in iPluginSources ) + { + CFFReader reader = source.Reader; + reader.Observer += new CFFReader.ReaderObserver( CFFReader_Observer ); + reader.ExceptionHandler += new CFFReader.ReaderExceptionHandler( CFFReader_ExceptionHandler ); + } + // + try + { + CIEngineTraceReader traceReader = new CIEngineTraceReader( this ); + traceReader.Read( TSynchronicity.ESynchronous ); + } + finally + { + ret = CalculateFinalState(); + + // Stop listening to container creation events in all plugin reader objects + foreach ( CFFSource source in iPluginSources ) + { + CFFReader reader = source.Reader; + reader.Observer -= new CFFReader.ReaderObserver( CFFReader_Observer ); + reader.ExceptionHandler -= new CFFReader.ReaderExceptionHandler( CFFReader_ExceptionHandler ); + } + } + // + return ret; + } + + public override CFFSource.TReaderOperationType OpType + { + get { return CFFSource.TReaderOperationType.EReaderOpTypeTrace; } + } + #endregion + + #region API + #endregion + + #region Event handlers + private void CFFReader_Observer( CFFReader.TEvent aEvent, CFFReader aReader, object aContext ) + { + base.Trace( "[CIEngineSourceReaderTrace] CFFReader_Observer() - START - aEvent: " + aEvent + ", file: " + base.Source.FileName ); + + // This method is called for both native and trace based events + if ( aEvent == CFFReader.TEvent.EReadingContainerCreated ) + { + CIContainer container = aContext as CIContainer; + if ( container != null ) + { + base.SaveCrash( container ); + } + } + else if ( aEvent == CFFReader.TEvent.EReadingProgress ) + { + int progress = ( aContext != null && aContext is int ) ? (int) aContext : 0; + base.Source.OnSourceReadingProgress( progress ); + } + + base.Trace( "[CIEngineSourceReaderTrace] CFFReader_Observer() - END - aEvent: " + aEvent + ", file: " + base.Source.FileName ); + } + + private void CFFReader_ExceptionHandler( Exception aException, CFFReader aReader ) + { + base.AddException( aException ); + } + #endregion + + #region Multiplexing methods + internal void OnTraceReadInit() + { + lock ( iPluginSources ) + { + foreach ( CFFSource entry in iPluginSources ) + { + entry.Reader.OnTraceReadInit(); + } + } + } + + internal void OnTraceReadComplete() + { + lock ( iPluginSources ) + { + foreach ( CFFSource entry in iPluginSources ) + { + entry.Reader.OnTraceReadComplete(); + } + } + } + + internal void OnTraceReadOffer( CFFTraceLine aLine ) + { + lock ( iPluginSources ) + { + foreach ( CFFSource entry in iPluginSources ) + { + CFFTraceLine line = new CFFTraceLine( aLine.Line, aLine.LineNumber, entry ); + entry.Reader.OnTraceReadOffer( line ); + } + } + } + + internal void OnTraceReadException( Exception aException ) + { + base.AddException( aException ); + } + + internal void OnTraceReaderProgress( int aProgress ) + { + base.Source.OnSourceReadingProgress( aProgress ); + } + #endregion + + #region Internal methods + private CIEngineSource.TState CalculateFinalState() + { + CIEngineSource.TState ret = CIEngineSource.TState.EStateReadyCorrupt; + + // For trace-based operations we'll potentially be firing each trace + // line at multiple readers, in which case we only mark the file as + // corrupt if no readers completed successfully. + int countCorrupt = 0; + int countReady = 0; + int countContainers = base.CrashItemCount; + + // Count number of ready vs corrupt readers + foreach ( CFFSource source in iPluginSources ) + { + CFFReader reader = source.Reader; + CFFReader.TState readerState = reader.State; + // + switch ( readerState ) + { + case CFFReader.TState.EStateCorrupt: + ++countCorrupt; + break; + case CFFReader.TState.EStateReady: + ++countReady; + break; + default: + case CFFReader.TState.EStateProcessing: + case CFFReader.TState.EStateUninitialised: + SymbianUtils.SymDebug.SymDebugger.Assert( false ); + break; + } + } + + // If we created at least one container, then we did still manage to create + // some kind of crash output irrespective of how many of the readers indicated + // the source was corrupt. In that case, the underlying source file is treated + // as valid. + base.Trace( "[CIEngineSourceReaderTrace] CalculateFinalState() - total: {0}, ready: {1}, corrupt: {2}", countContainers, countReady, countCorrupt ); + if ( countContainers > 0 ) + { + ret = CIEngineSource.TState.EStateReady; + } + else + { + // We didn't manage to create any crash items at all from this source + // file. + if ( countCorrupt > 0 ) + { + // At least one reader indicated that the source file was corrupt, + // and since no other reader could create any kind of valid output + // we'll treat the source file as entirely corrupt. + ret = CIEngineSource.TState.EStateReadyCorrupt; + } + else + { + // No crash container created, but nobody said the file was corrupt + // either. It's just a "no items" file. + ret = CIEngineSource.TState.EStateReadyNoItems; + } + + } + + base.Trace( "[CIEngineSourceReaderTrace] CalculateFinalState() - END - ret: {0}, file: {1}", ret, base.Source.FileName ); + return ret; + } + #endregion + + #region Internal class - actual trace file reader + internal class CIEngineTraceReader : AsyncTextFileReader + { + #region Constructors + public CIEngineTraceReader( CIEngineSourceReaderTrace aMultiplexer ) + : base( aMultiplexer.Source.FileName ) + { + iMultiplexer = aMultiplexer; + } + #endregion + + #region API + public void Read( TSynchronicity aSynchronicity ) + { + base.StartRead( aSynchronicity ); + } + #endregion + + #region From AsyncTextFileReader + protected override void HandleReadStarted() + { + try + { + base.HandleReadStarted(); + } + finally + { + iMultiplexer.OnTraceReadInit(); + } + } + + protected override void HandleReadCompleted() + { + try + { + base.HandleReadCompleted(); + } + finally + { + iMultiplexer.OnTraceReadComplete(); + } + } + + protected override void HandleFilteredLine( string aLine ) + { + CFFTraceLine line = new CFFTraceLine( aLine, LineNumber, null ); + iMultiplexer.OnTraceReadOffer( line ); + } + + protected override void HandleReadException( Exception aException ) + { + try + { + base.HandleReadException( aException ); + } + finally + { + iMultiplexer.OnTraceReadException( aException ); + } + } + + protected override void OnProgressChanged( int aProgress ) + { + iMultiplexer.OnTraceReaderProgress( aProgress ); + } + #endregion + + #region Data members + private readonly CIEngineSourceReaderTrace iMultiplexer; + #endregion + } + #endregion + + #region Data members + private List iPluginSources = new List(); + #endregion + } +}