diff -r 000000000000 -r 818e61de6cd1 crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianSymbolLib/SourceManagement/Source/SymSource.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianSymbolLib/SourceManagement/Source/SymSource.cs Thu Feb 11 15:50:58 2010 +0200 @@ -0,0 +1,398 @@ +/* +* Copyright (c) 2004-2008 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 SymbianUtils; +using SymbianUtils.Range; +using SymbianStructuresLib.Debug.Symbols; +using SymbianStructuresLib.Debug.Symbols.Interfaces; +using SymbianStructuresLib.CodeSegments; +using SymbianStructuresLib.Debug.Common.FileName; +using SymbianSymbolLib.SourceManagement.Provisioning; + +namespace SymbianSymbolLib.SourceManagement.Source +{ + public class SymSource : DisposableObject, IEnumerable, ISymbolCollectionRelocationHandler + { + #region Delegates & events + public delegate void EventHandlerFunction( TEvent aEvent, SymSource aSource, object aData ); + public event EventHandlerFunction EventHandler; + #endregion + + #region Enumerations + public enum TEvent + { + EReadingStarted = 0, + EReadingProgress, + EReadingComplete + } + + public enum TTimeToRead + { + EReadWhenPriming = 0, + EReadWhenNeeded // i.e. relocated + } + #endregion + + #region Constructors + public SymSource( string aURI, SymSourceProvider aProvider ) + { + iURI = aURI; + iProvider = aProvider; + } + + public SymSource( string aURI, SymSourceProvider aProvider, SymbolCollection aCollection ) + : this( aURI, aProvider ) + { + Add( aCollection ); + } + #endregion + + #region API + public virtual void Read( TSynchronicity aSynchronicity ) + { + iProvider.ReadSource( this, aSynchronicity ); + } + + public virtual void Add( SymbolCollection aCollection ) + { + // We want to be told if the collection changes it's relocation state. + aCollection.RelocationStatusChanged += new SymbolCollection.RelocationStatusChangeHandler( Collection_RelocationStatusChanged ); + + lock ( iCollectionsAll ) + { + iCollectionsAll.Add( aCollection ); + } + + CategoriseCollection( aCollection ); + } + + public virtual void Remove( SymbolCollection aCollection ) + { + aCollection.RelocationStatusChanged -= new SymbolCollection.RelocationStatusChangeHandler( Collection_RelocationStatusChanged ); + // + lock ( iCollectionsAll ) + { + iCollectionsAll.Remove( aCollection ); + } + lock ( iAlwaysActivatedCollections ) + { + iAlwaysActivatedCollections.Remove( aCollection ); + } + } + + public virtual bool Contains( uint aAddress ) + { + lock ( iAlwaysActivatedCollections ) + { + return iAlwaysActivatedCollections.Contains( aAddress ); + } + } + + public virtual Symbol Lookup( uint aAddress, out SymbolCollection aCollection ) + { + lock ( iAlwaysActivatedCollections ) + { + aCollection = null; + // + Symbol ret = iAlwaysActivatedCollections.Lookup( aAddress, out aCollection ); + return ret; + } + } + + protected virtual void OnAddedToCollection( SymSourceCollection aCollection ) + { + ++iReferenceCount; + } + + protected virtual void OnRemovedFromCollection( SymSourceCollection aCollection ) + { + if ( --iReferenceCount <= 0 ) + { + this.Dispose(); + } + } + + protected virtual void OnPrepareForRelocation( SymbolCollection aCollection, uint aOldBase, uint aNewBase ) + { + // If we read our data during priming, then we don't need to do anything... otherwise, we should + // read the data now. + if ( TimeToRead == TTimeToRead.EReadWhenNeeded ) + { + this.Read( TSynchronicity.ESynchronous ); + } + } + #endregion + + #region API - framework + public void ReportEvent( TEvent aEvent ) + { + if ( aEvent == TEvent.EReadingComplete ) + { + iAlwaysActivatedCollections.BuildLookupCache(); + } + + ReportEvent( aEvent, null ); + } + + public void ReportEvent( TEvent aEvent, object aData ) + { + if ( EventHandler != null ) + { + EventHandler( aEvent, this, aData ); + } + } + #endregion + + #region Event handlers + private void Collection_RelocationStatusChanged( SymbolCollection aCollection ) + { + CategoriseCollection( aCollection ); + } + #endregion + + #region Properties + public int Count + { + get + { + lock ( iCollectionsAll ) + { + return iCollectionsAll.Count; + } + } + } + + public string URI + { + get + { + lock ( iURI ) + { + return iURI; + } + } + set + { + lock ( iURI ) + { + iURI = value; + } + } + + } + + public string FileName + { + get { return iProvider.GetFileName( this ); } + } + + public TTimeToRead TimeToRead + { + get { return iTimeToRead; } + set + { + iTimeToRead = value; + } + } + + public SymSourceProvider Provider + { + get + { + lock ( iProvider ) + { + return iProvider; + } + } + } + + public SymbolCollection this[ int aIndex ] + { + get + { + lock ( iCollectionsAll ) + { + return iCollectionsAll[ aIndex ]; + } + } + } + + public virtual SymbolCollection this[ CodeSegDefinition aCodeSegment ] + { + get + { + lock ( iCollectionsAll ) + { + SymbolCollection ret = iCollectionsAll[ aCodeSegment ]; + return ret; + } + } + } + + public virtual SymbolCollection this[ PlatformFileName aFileName ] + { + get + { + lock ( iCollectionsAll ) + { + SymbolCollection ret = iCollectionsAll[ aFileName ]; + return ret; + } + } + } + #endregion + + #region Internal methods + internal int CountActivated + { + get + { + lock ( iAlwaysActivatedCollections ) + { + return iAlwaysActivatedCollections.Count; + } + } + } + + internal void AddedToCollection( SymSourceCollection aCollection ) + { + OnAddedToCollection( aCollection ); + } + + internal void RemovedFromCollection( SymSourceCollection aCollection ) + { + OnRemovedFromCollection( aCollection ); + } + + private void CategoriseCollection( SymbolCollection aCollection ) + { + // Reset state + lock ( iAlwaysActivatedCollections ) + { + iAlwaysActivatedCollections.Remove( aCollection ); + aCollection.IfaceRelocationHandler = null; + } + + // Collections which do not move from their pre-determined base address + // are transparently "activated" which means that they will be queried + // automatically during symbolic look up. + if ( aCollection.IsFixed ) + { + lock ( iAlwaysActivatedCollections ) + { + iAlwaysActivatedCollections.Add( aCollection ); + } + } + else + { + aCollection.IfaceRelocationHandler = this; + } + } + #endregion + + #region From ISymbolCollectionRelocationHandler + public void PrepareForRelocation( SymbolCollection aCollection, uint aOldBase, uint aNewBase ) + { + OnPrepareForRelocation( aCollection, aOldBase, aNewBase ); + } + #endregion + + #region From IEnumerable + public IEnumerator GetEnumerator() + { + lock ( iCollectionsAll ) + { + foreach ( SymbolCollection col in iCollectionsAll ) + { + yield return col; + } + } + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + lock ( iCollectionsAll ) + { + foreach ( SymbolCollection col in iCollectionsAll ) + { + yield return col; + } + } + } + #endregion + + #region From DisposableObject + protected override void CleanupManagedResources() + { + try + { + base.CleanupManagedResources(); + } + finally + { + int count = iCollectionsAll.Count; + for ( int i = count - 1; i >= 0; i-- ) + { + SymbolCollection col = iCollectionsAll[ i ]; + Remove( col ); + col.Dispose(); + } + + // These should both be empty in any case + iCollectionsAll.Clear(); + iAlwaysActivatedCollections.Clear(); + } + } + #endregion + + #region From System.Object + public override string ToString() + { + return URI; + } + + public override int GetHashCode() + { + return URI.GetHashCode(); + } + + public override bool Equals( object aObject ) + { + if ( aObject is SymSource ) + { + SymSource other = (SymSource) aObject; + bool ret = ( string.Compare( other.URI, this.URI, StringComparison.CurrentCultureIgnoreCase ) == 0 ); + return ret; + } + // + return base.Equals( aObject ); + } + #endregion + + #region Data members + private readonly SymSourceProvider iProvider; + private string iURI = string.Empty; + private int iReferenceCount = 0; + private TTimeToRead iTimeToRead = TTimeToRead.EReadWhenPriming; + private SymbolCollectionList iCollectionsAll = new SymbolCollectionList(); + private SymbolCollectionList iAlwaysActivatedCollections = new SymbolCollectionList(); + #endregion + } +}