crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianImageLib/Common/Content/SIContent.cs
changeset 0 818e61de6cd1
equal deleted inserted replaced
-1:000000000000 0:818e61de6cd1
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 * 
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 using System;
       
    18 using System.Collections.Generic;
       
    19 using System.Text;
       
    20 using System.IO;
       
    21 using System.ComponentModel;
       
    22 using System.Threading;
       
    23 using SymbianUtils;
       
    24 using SymbianUtils.Tracer;
       
    25 using SymbianUtils.PluginManager;
       
    26 using SymbianStructuresLib.Uids;
       
    27 using SymbianStructuresLib.Compression.Common;
       
    28 using SymbianImageLib.Common.Image;
       
    29 using SymbianImageLib.Common.Header;
       
    30 using SymbianImageLib.Common.Streams;
       
    31 using SymbianImageLib.Common.Factory;
       
    32 
       
    33 namespace SymbianImageLib.Common.Content
       
    34 {
       
    35     public abstract class SIContent : DisposableObject, ITracer
       
    36     {
       
    37         #region Enumerations
       
    38         public enum TDecompressionEvent
       
    39         {
       
    40             EEventDecompressionStarting = 0,
       
    41             EEventDecompressionProgress,
       
    42             EEventDecompressionComplete
       
    43         }
       
    44         #endregion
       
    45 
       
    46         #region Delegates & events
       
    47         public delegate void DecompressionEventHandler( TDecompressionEvent aEvent, SIContent aFile, object aData );
       
    48         public event DecompressionEventHandler DecompressionEvent;
       
    49         #endregion
       
    50 
       
    51         #region Constructors
       
    52         protected SIContent( SIImage aImage )
       
    53         {
       
    54             iImage = aImage;
       
    55         }
       
    56         #endregion
       
    57 
       
    58         #region Framework API
       
    59         public abstract TSymbianCompressionType CompressionType
       
    60         {
       
    61             get;
       
    62         }
       
    63 
       
    64         public abstract string FileName
       
    65         {
       
    66             get;
       
    67         }
       
    68 
       
    69         public abstract uint FileSize
       
    70         {
       
    71             get;
       
    72         }
       
    73 
       
    74         public abstract uint ContentSize
       
    75         {
       
    76             get;
       
    77         }
       
    78 
       
    79         public virtual bool IsRelocationSupported
       
    80         {
       
    81             get { return true; }
       
    82         }
       
    83 
       
    84         public virtual TCheckedUid Uid
       
    85         {
       
    86             get { return new TCheckedUid(); }
       
    87         }
       
    88 
       
    89         public virtual byte[] GetAllData()
       
    90         {
       
    91             return new byte[ 0 ];
       
    92         }
       
    93 
       
    94         public virtual uint ProvideDataUInt32( uint aAddress )
       
    95         {
       
    96             uint ret = 0;
       
    97             //
       
    98             if ( IsContentPrepared == false )
       
    99             {
       
   100                 // Cannot provide data if we've not prepared it yet
       
   101             }
       
   102             else if ( iDecompressionException == false )
       
   103             {
       
   104                 WaitForAsyncOperationCompletion();
       
   105                 uint resolvedAddress = FixupAddress( aAddress );
       
   106                 ret = DoProvideDataUInt32( resolvedAddress );
       
   107             }
       
   108             //
       
   109             return ret;
       
   110         }
       
   111 
       
   112         public virtual ushort ProvideDataUInt16( uint aAddress )
       
   113         {
       
   114             ushort ret = 0;
       
   115             //
       
   116             if ( IsContentPrepared == false )
       
   117             {
       
   118                 // Cannot provide data if we've not prepared it yet
       
   119             }
       
   120             else if ( iDecompressionException == false )
       
   121             {
       
   122                 WaitForAsyncOperationCompletion();
       
   123                 uint resolvedAddress = FixupAddress( aAddress );
       
   124                 ret = DoProvideDataUInt16( resolvedAddress );
       
   125             }
       
   126             //
       
   127             return ret;
       
   128         }
       
   129 
       
   130         public virtual bool IsCode
       
   131         {
       
   132             get { return true; }
       
   133         }
       
   134 
       
   135         protected virtual void OnRelocationAddressChanged( uint aOld, uint aNew )
       
   136         {
       
   137         }
       
   138 
       
   139         protected virtual void DoDecompress()
       
   140         {
       
   141         }
       
   142 
       
   143         protected virtual uint DoProvideDataUInt32( uint aTranslatedAddress )
       
   144         {
       
   145             throw new NotImplementedException();
       
   146         }
       
   147 
       
   148         protected virtual ushort DoProvideDataUInt16( uint aTranslatedAddress )
       
   149         {
       
   150             throw new NotImplementedException();
       
   151         }
       
   152 
       
   153         protected abstract bool GetIsContentPrepared();
       
   154         #endregion
       
   155 
       
   156         #region API
       
   157         public void PrepareContent( TSynchronicity aSynchronicity )
       
   158         {
       
   159             if ( CompressionType == TSymbianCompressionType.ENone )
       
   160             {
       
   161                 // No content preparation required, so just indicate completion
       
   162                 // immediately.
       
   163                 ReportDecompressionEvent( TDecompressionEvent.EEventDecompressionStarting );
       
   164                 ReportDecompressionEvent( TDecompressionEvent.EEventDecompressionComplete );
       
   165             }
       
   166             else
       
   167             {
       
   168                 switch ( aSynchronicity )
       
   169                 {
       
   170                 case TSynchronicity.ESynchronous:
       
   171                     RunDecompressor();
       
   172                     break;
       
   173                 case TSynchronicity.EAsynchronous:
       
   174                     // Must take the lock to either create or destroy waiter
       
   175                     lock ( iWaiterSyncRoot )
       
   176                     {
       
   177                         if ( iWaiter == null )
       
   178                         {
       
   179                             iWaiter = new AutoResetEvent( false );
       
   180                             ThreadPool.QueueUserWorkItem( new WaitCallback( RunDecompressionInBackgroundThread ), null );
       
   181                             break;
       
   182                         }
       
   183                         else
       
   184                         {
       
   185                             // Wait is active, so we are presumably busy...
       
   186                             throw new Exception( "Content is already in preparation" );
       
   187                         }
       
   188                     }
       
   189                 }
       
   190             }
       
   191         }
       
   192  
       
   193         public uint RelocationAddress
       
   194         {
       
   195             get { return iRelocationAddress; }
       
   196             set
       
   197             {
       
   198                 if ( value != iRelocationAddress )
       
   199                 {
       
   200                     uint old = iRelocationAddress;
       
   201                     iRelocationAddress = value;
       
   202                     OnRelocationAddressChanged( old, iRelocationAddress );
       
   203                 }
       
   204             }
       
   205         }
       
   206 
       
   207         public virtual bool IsContentPrepared
       
   208         {
       
   209             get
       
   210             {
       
   211                 bool ret = true;
       
   212                 //
       
   213                 if ( CompressionType != TSymbianCompressionType.ENone )
       
   214                 {
       
   215                     ret = GetIsContentPrepared();
       
   216                 }
       
   217                 //
       
   218                 return ret;
       
   219             }
       
   220         }
       
   221         #endregion
       
   222 
       
   223         #region Properties
       
   224         public SIImage Image
       
   225         {
       
   226             get { return iImage; }
       
   227         }
       
   228         
       
   229         public SIHeader ImageHeader
       
   230         {
       
   231             get { return iImage.Header; }
       
   232         }
       
   233 
       
   234         internal SIStream ImageStream
       
   235         {
       
   236             get 
       
   237             {
       
   238                 return iImage.Stream; 
       
   239             }
       
   240             set { iImage.Stream = value; }
       
   241         }
       
   242         #endregion
       
   243 
       
   244         #region Event handlers
       
   245         private void RunDecompressionInBackgroundThread( object aNotUsed )
       
   246         {
       
   247             System.Diagnostics.Debug.Assert( iWaiter != null );
       
   248 
       
   249             // Call derived class to do decompression. Must not throw.
       
   250             RunDecompressor();
       
   251 
       
   252             // Must do this last so that anybody that is waiting for code to become
       
   253             // ready is resumed.
       
   254             //
       
   255             // Also, we might have been disposed of as a result of the "completion" callback
       
   256             // so in that case, we will have already set the auto-reset-event during the cleanup.
       
   257             if ( iWaiter != null )
       
   258             {
       
   259                 iWaiter.Set();
       
   260             }
       
   261         }
       
   262         #endregion
       
   263 
       
   264         #region Internal methods
       
   265         protected void ReportDecompressionEvent( TDecompressionEvent aEvent )
       
   266         {
       
   267             ReportDecompressionEvent( aEvent, null );
       
   268         }
       
   269 
       
   270         protected void ReportDecompressionEvent( TDecompressionEvent aEvent, object aData )
       
   271         {
       
   272             if ( DecompressionEvent != null )
       
   273             {
       
   274                 DecompressionEvent( aEvent, this, aData );
       
   275             }
       
   276         }
       
   277 
       
   278         private void RunDecompressor()
       
   279         {
       
   280             Trace( "[SIImageContent] RunDecompressor() - START - this: " + FileName );
       
   281             ReportDecompressionEvent( TDecompressionEvent.EEventDecompressionStarting );
       
   282             //
       
   283             try
       
   284             {
       
   285                 DoDecompress();
       
   286             }
       
   287             catch ( Exception e )
       
   288             {
       
   289                 Trace( "[SIImageContent] RunDecompressor() - Exception - this: {0}, message: {1}", this.FileName, e.Message );
       
   290                 Trace( "[SIImageContent] RunDecompressor() - Exception - this: {0}, stack  : {1}", this.FileName, e.StackTrace );
       
   291                 iDecompressionException = true;
       
   292             }
       
   293 
       
   294             // Doing this might cause the disposal of the object
       
   295             ReportDecompressionEvent( TDecompressionEvent.EEventDecompressionComplete );
       
   296             Trace( "[SIImageContent] RunDecompressor() - END - this: " + FileName );
       
   297         }
       
   298 
       
   299         private void WaitForAsyncOperationCompletion()
       
   300         {
       
   301             // If the worker doesn't exist then we've already completed the operation
       
   302             if ( iWaiter != null )
       
   303             {
       
   304                 // Just wait on the auto-reset event. If it's already been signalled, then
       
   305                 // we will continue immediately.
       
   306                 iWaiter.WaitOne();
       
   307 
       
   308                 // Must take the lock to either create or destroy waiter
       
   309                 lock ( iWaiterSyncRoot )
       
   310                 {
       
   311                     iWaiter.Close();
       
   312                     iWaiter = null;
       
   313                 }
       
   314             }
       
   315         }
       
   316 
       
   317         private uint FixupAddress( uint aAddress )
       
   318         {
       
   319             uint ret = aAddress - iRelocationAddress;
       
   320             return ret;
       
   321         }
       
   322         #endregion
       
   323 
       
   324         #region From ITracer
       
   325         public void Trace( string aMessage )
       
   326         {
       
   327             iImage.Trace( aMessage );
       
   328         }
       
   329 
       
   330         public void Trace( string aFormat, params object[] aParams )
       
   331         {
       
   332             iImage.Trace( aFormat, aParams );
       
   333         }
       
   334         #endregion
       
   335 
       
   336         #region From DisposableObject
       
   337         protected override void CleanupManagedResources()
       
   338         {
       
   339             try
       
   340             {
       
   341                 base.CleanupManagedResources();
       
   342             }
       
   343             finally
       
   344             {
       
   345                 iImage.Remove( this );
       
   346                 //
       
   347                 if ( iWaiter != null )
       
   348                 {
       
   349                     iWaiter.Set();
       
   350                     iWaiter.Close();
       
   351                     iWaiter = null;
       
   352                 }
       
   353             }
       
   354         }
       
   355         #endregion
       
   356 
       
   357         #region From System.Object
       
   358         public override string ToString()
       
   359         {
       
   360             return FileName;
       
   361         }
       
   362 
       
   363         public override int GetHashCode()
       
   364         {
       
   365             return FileName.GetHashCode();
       
   366         }
       
   367         #endregion
       
   368 
       
   369         #region Data members
       
   370         private readonly SIImage iImage;
       
   371         private uint iRelocationAddress = 0;
       
   372         private bool iDecompressionException = false;
       
   373         private AutoResetEvent iWaiter = null;
       
   374         private object iWaiterSyncRoot = new object();
       
   375         #endregion
       
   376     }
       
   377 }