crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianImageLib/Common/Content/SIContent.cs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianImageLib/Common/Content/SIContent.cs Thu Feb 11 15:50:58 2010 +0200
@@ -0,0 +1,377 @@
+/*
+* 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 System.IO;
+using System.ComponentModel;
+using System.Threading;
+using SymbianUtils;
+using SymbianUtils.Tracer;
+using SymbianUtils.PluginManager;
+using SymbianStructuresLib.Uids;
+using SymbianStructuresLib.Compression.Common;
+using SymbianImageLib.Common.Image;
+using SymbianImageLib.Common.Header;
+using SymbianImageLib.Common.Streams;
+using SymbianImageLib.Common.Factory;
+
+namespace SymbianImageLib.Common.Content
+{
+ public abstract class SIContent : DisposableObject, ITracer
+ {
+ #region Enumerations
+ public enum TDecompressionEvent
+ {
+ EEventDecompressionStarting = 0,
+ EEventDecompressionProgress,
+ EEventDecompressionComplete
+ }
+ #endregion
+
+ #region Delegates & events
+ public delegate void DecompressionEventHandler( TDecompressionEvent aEvent, SIContent aFile, object aData );
+ public event DecompressionEventHandler DecompressionEvent;
+ #endregion
+
+ #region Constructors
+ protected SIContent( SIImage aImage )
+ {
+ iImage = aImage;
+ }
+ #endregion
+
+ #region Framework API
+ public abstract TSymbianCompressionType CompressionType
+ {
+ get;
+ }
+
+ public abstract string FileName
+ {
+ get;
+ }
+
+ public abstract uint FileSize
+ {
+ get;
+ }
+
+ public abstract uint ContentSize
+ {
+ get;
+ }
+
+ public virtual bool IsRelocationSupported
+ {
+ get { return true; }
+ }
+
+ public virtual TCheckedUid Uid
+ {
+ get { return new TCheckedUid(); }
+ }
+
+ public virtual byte[] GetAllData()
+ {
+ return new byte[ 0 ];
+ }
+
+ public virtual uint ProvideDataUInt32( uint aAddress )
+ {
+ uint ret = 0;
+ //
+ if ( IsContentPrepared == false )
+ {
+ // Cannot provide data if we've not prepared it yet
+ }
+ else if ( iDecompressionException == false )
+ {
+ WaitForAsyncOperationCompletion();
+ uint resolvedAddress = FixupAddress( aAddress );
+ ret = DoProvideDataUInt32( resolvedAddress );
+ }
+ //
+ return ret;
+ }
+
+ public virtual ushort ProvideDataUInt16( uint aAddress )
+ {
+ ushort ret = 0;
+ //
+ if ( IsContentPrepared == false )
+ {
+ // Cannot provide data if we've not prepared it yet
+ }
+ else if ( iDecompressionException == false )
+ {
+ WaitForAsyncOperationCompletion();
+ uint resolvedAddress = FixupAddress( aAddress );
+ ret = DoProvideDataUInt16( resolvedAddress );
+ }
+ //
+ return ret;
+ }
+
+ public virtual bool IsCode
+ {
+ get { return true; }
+ }
+
+ protected virtual void OnRelocationAddressChanged( uint aOld, uint aNew )
+ {
+ }
+
+ protected virtual void DoDecompress()
+ {
+ }
+
+ protected virtual uint DoProvideDataUInt32( uint aTranslatedAddress )
+ {
+ throw new NotImplementedException();
+ }
+
+ protected virtual ushort DoProvideDataUInt16( uint aTranslatedAddress )
+ {
+ throw new NotImplementedException();
+ }
+
+ protected abstract bool GetIsContentPrepared();
+ #endregion
+
+ #region API
+ public void PrepareContent( TSynchronicity aSynchronicity )
+ {
+ if ( CompressionType == TSymbianCompressionType.ENone )
+ {
+ // No content preparation required, so just indicate completion
+ // immediately.
+ ReportDecompressionEvent( TDecompressionEvent.EEventDecompressionStarting );
+ ReportDecompressionEvent( TDecompressionEvent.EEventDecompressionComplete );
+ }
+ else
+ {
+ switch ( aSynchronicity )
+ {
+ case TSynchronicity.ESynchronous:
+ RunDecompressor();
+ break;
+ case TSynchronicity.EAsynchronous:
+ // Must take the lock to either create or destroy waiter
+ lock ( iWaiterSyncRoot )
+ {
+ if ( iWaiter == null )
+ {
+ iWaiter = new AutoResetEvent( false );
+ ThreadPool.QueueUserWorkItem( new WaitCallback( RunDecompressionInBackgroundThread ), null );
+ break;
+ }
+ else
+ {
+ // Wait is active, so we are presumably busy...
+ throw new Exception( "Content is already in preparation" );
+ }
+ }
+ }
+ }
+ }
+
+ public uint RelocationAddress
+ {
+ get { return iRelocationAddress; }
+ set
+ {
+ if ( value != iRelocationAddress )
+ {
+ uint old = iRelocationAddress;
+ iRelocationAddress = value;
+ OnRelocationAddressChanged( old, iRelocationAddress );
+ }
+ }
+ }
+
+ public virtual bool IsContentPrepared
+ {
+ get
+ {
+ bool ret = true;
+ //
+ if ( CompressionType != TSymbianCompressionType.ENone )
+ {
+ ret = GetIsContentPrepared();
+ }
+ //
+ return ret;
+ }
+ }
+ #endregion
+
+ #region Properties
+ public SIImage Image
+ {
+ get { return iImage; }
+ }
+
+ public SIHeader ImageHeader
+ {
+ get { return iImage.Header; }
+ }
+
+ internal SIStream ImageStream
+ {
+ get
+ {
+ return iImage.Stream;
+ }
+ set { iImage.Stream = value; }
+ }
+ #endregion
+
+ #region Event handlers
+ private void RunDecompressionInBackgroundThread( object aNotUsed )
+ {
+ System.Diagnostics.Debug.Assert( iWaiter != null );
+
+ // Call derived class to do decompression. Must not throw.
+ RunDecompressor();
+
+ // Must do this last so that anybody that is waiting for code to become
+ // ready is resumed.
+ //
+ // Also, we might have been disposed of as a result of the "completion" callback
+ // so in that case, we will have already set the auto-reset-event during the cleanup.
+ if ( iWaiter != null )
+ {
+ iWaiter.Set();
+ }
+ }
+ #endregion
+
+ #region Internal methods
+ protected void ReportDecompressionEvent( TDecompressionEvent aEvent )
+ {
+ ReportDecompressionEvent( aEvent, null );
+ }
+
+ protected void ReportDecompressionEvent( TDecompressionEvent aEvent, object aData )
+ {
+ if ( DecompressionEvent != null )
+ {
+ DecompressionEvent( aEvent, this, aData );
+ }
+ }
+
+ private void RunDecompressor()
+ {
+ Trace( "[SIImageContent] RunDecompressor() - START - this: " + FileName );
+ ReportDecompressionEvent( TDecompressionEvent.EEventDecompressionStarting );
+ //
+ try
+ {
+ DoDecompress();
+ }
+ catch ( Exception e )
+ {
+ Trace( "[SIImageContent] RunDecompressor() - Exception - this: {0}, message: {1}", this.FileName, e.Message );
+ Trace( "[SIImageContent] RunDecompressor() - Exception - this: {0}, stack : {1}", this.FileName, e.StackTrace );
+ iDecompressionException = true;
+ }
+
+ // Doing this might cause the disposal of the object
+ ReportDecompressionEvent( TDecompressionEvent.EEventDecompressionComplete );
+ Trace( "[SIImageContent] RunDecompressor() - END - this: " + FileName );
+ }
+
+ private void WaitForAsyncOperationCompletion()
+ {
+ // If the worker doesn't exist then we've already completed the operation
+ if ( iWaiter != null )
+ {
+ // Just wait on the auto-reset event. If it's already been signalled, then
+ // we will continue immediately.
+ iWaiter.WaitOne();
+
+ // Must take the lock to either create or destroy waiter
+ lock ( iWaiterSyncRoot )
+ {
+ iWaiter.Close();
+ iWaiter = null;
+ }
+ }
+ }
+
+ private uint FixupAddress( uint aAddress )
+ {
+ uint ret = aAddress - iRelocationAddress;
+ return ret;
+ }
+ #endregion
+
+ #region From ITracer
+ public void Trace( string aMessage )
+ {
+ iImage.Trace( aMessage );
+ }
+
+ public void Trace( string aFormat, params object[] aParams )
+ {
+ iImage.Trace( aFormat, aParams );
+ }
+ #endregion
+
+ #region From DisposableObject
+ protected override void CleanupManagedResources()
+ {
+ try
+ {
+ base.CleanupManagedResources();
+ }
+ finally
+ {
+ iImage.Remove( this );
+ //
+ if ( iWaiter != null )
+ {
+ iWaiter.Set();
+ iWaiter.Close();
+ iWaiter = null;
+ }
+ }
+ }
+ #endregion
+
+ #region From System.Object
+ public override string ToString()
+ {
+ return FileName;
+ }
+
+ public override int GetHashCode()
+ {
+ return FileName.GetHashCode();
+ }
+ #endregion
+
+ #region Data members
+ private readonly SIImage iImage;
+ private uint iRelocationAddress = 0;
+ private bool iDecompressionException = false;
+ private AutoResetEvent iWaiter = null;
+ private object iWaiterSyncRoot = new object();
+ #endregion
+ }
+}