crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianImageLib/Common/Content/SIContent.cs
changeset 0 818e61de6cd1
--- /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
+    }
+}