crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianStructuresLib/Debug/Symbols/Symbols/SymbolCollectionList.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.IO;
       
    19 using System.Text;
       
    20 using System.Threading;
       
    21 using System.Collections.Generic;
       
    22 using SymbianUtils;
       
    23 using SymbianUtils.Range;
       
    24 using SymbianStructuresLib.CodeSegments;
       
    25 using SymbianStructuresLib.Debug.Common.FileName;
       
    26 
       
    27 namespace SymbianStructuresLib.Debug.Symbols
       
    28 {
       
    29     public class SymbolCollectionList : IEnumerable<SymbolCollection>
       
    30     {
       
    31         #region Constructors
       
    32         public SymbolCollectionList()
       
    33         {
       
    34         }
       
    35         #endregion
       
    36 
       
    37         #region API
       
    38         public void Clear()
       
    39         {
       
    40             lock ( iCollections )
       
    41             {
       
    42                 iCollections.Clear();
       
    43             }
       
    44             lock ( iLookupCache )
       
    45             {
       
    46                 iLookupCache.Clear();
       
    47             }
       
    48             lock ( iFileNameDictionary )
       
    49             {
       
    50                 iFileNameDictionary.Clear();
       
    51             }
       
    52         }
       
    53 
       
    54         public void Add( SymbolCollection aCollection )
       
    55         {
       
    56             // Check not already added
       
    57             PlatformFileName name = aCollection.FileName;
       
    58             lock ( iFileNameDictionary )
       
    59             {
       
    60                 if ( iFileNameDictionary.ContainsKey( name ) )
       
    61                 {
       
    62                     throw new ArgumentException( string.Format( "Collection \'{0}\' already exists", name ) );
       
    63                 }
       
    64             }
       
    65 
       
    66             // Add to file name dictionary
       
    67             iFileNameDictionary.Add( name, aCollection );
       
    68 
       
    69             // Add to non-optimised collection
       
    70             iCollections.Add( aCollection );
       
    71         }
       
    72 
       
    73         public void AddAndBuildCache( SymbolCollection aCollection )
       
    74         {
       
    75             Add( aCollection );
       
    76             UpdateCacheForCollection( aCollection );
       
    77         }
       
    78 
       
    79         public void Remove( SymbolCollection aCollection )
       
    80         {
       
    81             Predicate<SymbolCollection> predicate = delegate( SymbolCollection collection )
       
    82             {
       
    83                 return collection.Equals( aCollection );
       
    84             };
       
    85             //
       
    86             lock ( iCollections )
       
    87             {
       
    88                 iCollections.RemoveAll( predicate );
       
    89             }
       
    90             //
       
    91             RemoveFromCache( aCollection );
       
    92         }
       
    93 
       
    94         public void RemoveUntagged()
       
    95         {
       
    96             Predicate<SymbolCollection> predicate = delegate( SymbolCollection collection )
       
    97             {
       
    98                 return collection.Tagged == false;
       
    99             };
       
   100             //
       
   101             lock ( iCollections )
       
   102             {
       
   103                 iCollections.RemoveAll( predicate );
       
   104             }
       
   105 
       
   106             // MRU can be left intact since implicitly it should only contained tagged
       
   107             // collections
       
   108         }
       
   109 
       
   110         public void Serialize( Stream aStream )
       
   111         {
       
   112             using ( StreamWriter writer = new StreamWriter( aStream ) )
       
   113             {
       
   114                 Action<SymbolCollection> action = delegate( SymbolCollection collection )
       
   115                 {
       
   116                     if ( collection.Tagged )
       
   117                     {
       
   118                         collection.Serialize( writer );
       
   119                     }
       
   120                 };
       
   121                 //
       
   122                 lock ( this )
       
   123                 {
       
   124                     iCollections.ForEach( action );
       
   125                 }
       
   126             }
       
   127         }
       
   128 
       
   129         public bool Contains( uint aAddress )
       
   130         {
       
   131             WaitForLookupCache();
       
   132             //
       
   133             bool ret = false;
       
   134             //
       
   135             AddressCollectionPair temp = new AddressCollectionPair( new AddressRange( aAddress, aAddress ), null );
       
   136             AddressCollectionPairComparer comparer = new AddressCollectionPairComparer();
       
   137             //
       
   138             lock ( iLookupCache )
       
   139             {
       
   140                 int pos = iLookupCache.BinarySearch( temp, comparer );
       
   141                 ret = ( pos >= 0 );
       
   142             }
       
   143             //
       
   144             return ret;
       
   145         }
       
   146 
       
   147         public bool Contains( SymbolCollection aCollection )
       
   148         {
       
   149             bool ret = false;
       
   150 
       
   151             // Check not already added
       
   152             PlatformFileName name = aCollection.FileName;
       
   153             lock ( iFileNameDictionary )
       
   154             {
       
   155                 ret = iFileNameDictionary.ContainsKey( name );
       
   156             }
       
   157             //
       
   158             return ret;
       
   159         }
       
   160 
       
   161         public Symbol Lookup( uint aAddress, out SymbolCollection aCollection )
       
   162         {
       
   163             WaitForLookupCache();
       
   164             //
       
   165             Symbol ret = null;
       
   166             aCollection = null;
       
   167             //
       
   168             AddressCollectionPair temp = new AddressCollectionPair( new AddressRange( aAddress, aAddress ), null );
       
   169             AddressCollectionPairComparer comparer = new AddressCollectionPairComparer();
       
   170             //
       
   171             lock ( iLookupCache )
       
   172             {
       
   173                 int pos = iLookupCache.BinarySearch( temp, comparer );
       
   174                 if ( pos >= 0 )
       
   175                 {
       
   176                     temp = iLookupCache[ pos ];
       
   177                     aCollection = temp.Collection;
       
   178                     ret = aCollection[ aAddress ];
       
   179                 }
       
   180             }
       
   181             //
       
   182             return ret;
       
   183         }
       
   184 
       
   185         public void SortByCollectionAddress()
       
   186         {
       
   187             Comparison<SymbolCollection> comparer = delegate( SymbolCollection aCol1, SymbolCollection aCol2 )
       
   188             {
       
   189                 int ret = aCol1.BaseAddress.CompareTo( aCol2.BaseAddress );
       
   190                 return ret;
       
   191             };
       
   192             //
       
   193             iCollections.Sort( comparer );
       
   194         }
       
   195 
       
   196         public void BuildLookupCache()
       
   197         {
       
   198             WaitForLookupCache();
       
   199             //
       
   200             lock ( iLookupCache )
       
   201             {
       
   202                 iLookupCache.Clear();
       
   203             }
       
   204             
       
   205             // Build the cache in a separate thread.
       
   206             // Must take the lock to either create or destroy waiter.
       
   207             lock ( iWaiterSyncRoot )
       
   208             {
       
   209                 if ( iLookUpCacheWaiter == null )
       
   210                 {
       
   211                     iLookUpCacheWaiter = new AutoResetEvent( false );
       
   212                     ThreadPool.QueueUserWorkItem( new WaitCallback( BackgroundThreadBuildLookupCache ), null );
       
   213                 }
       
   214             }
       
   215         }
       
   216         #endregion
       
   217 
       
   218         #region Properties
       
   219         public int Count
       
   220         {
       
   221             get
       
   222             {
       
   223                 lock ( iCollections )
       
   224                 {
       
   225                     return iCollections.Count;
       
   226                 }
       
   227             }
       
   228         }
       
   229 
       
   230         public bool IsEmpty
       
   231         {
       
   232             get { return Count == 0; } 
       
   233         }
       
   234 
       
   235         public bool Tagged
       
   236         {
       
   237             set
       
   238             {
       
   239                 lock ( this )
       
   240                 {
       
   241                     Action<SymbolCollection> action = delegate( SymbolCollection collection )
       
   242                     {
       
   243                         collection.Tagged = value;
       
   244                     };
       
   245                     iCollections.ForEach( action );
       
   246                 }
       
   247             }
       
   248         }
       
   249 
       
   250         public object Tag
       
   251         {
       
   252             get { return iTag; }
       
   253             set
       
   254             {
       
   255                 iTag = value;
       
   256             }
       
   257         }
       
   258 
       
   259         public SymbolCollection this[ int aIndex ]
       
   260         {
       
   261             get
       
   262             {
       
   263                 lock ( iCollections )
       
   264                 {
       
   265                     return iCollections[ aIndex ];
       
   266                 }
       
   267             }
       
   268         }
       
   269 
       
   270         public SymbolCollection this[ PlatformFileName aFileName ]
       
   271         {
       
   272             get
       
   273             {
       
   274                 Predicate<SymbolCollection> predicate = delegate( SymbolCollection collection )
       
   275                 {
       
   276                     bool same = collection.FileName.Equals( aFileName );
       
   277                     return same;
       
   278                 };
       
   279                 //
       
   280                 SymbolCollection ret = null;
       
   281                 //
       
   282                 lock ( iCollections )
       
   283                 {
       
   284                     ret = iCollections.Find( predicate );
       
   285                 }
       
   286                 //
       
   287                 return ret;
       
   288             }
       
   289         }
       
   290 
       
   291         public SymbolCollection this[ CodeSegDefinition aCodeSegment ]
       
   292         {
       
   293             get
       
   294             {
       
   295                 Predicate<SymbolCollection> predicate = delegate( SymbolCollection collection )
       
   296                 {
       
   297                     bool same = collection.IsMatchingCodeSegment( aCodeSegment );
       
   298                     return same;
       
   299                 };
       
   300                 //
       
   301                 SymbolCollection ret = null;
       
   302                 //
       
   303                 lock ( iCollections )
       
   304                 {
       
   305                     ret = iCollections.Find( predicate );
       
   306                 }
       
   307                 //
       
   308                 return ret;
       
   309             }
       
   310         }
       
   311         #endregion
       
   312 
       
   313         #region From IEnumerable<SymbolCollection>
       
   314         IEnumerator<SymbolCollection> IEnumerable<SymbolCollection>.GetEnumerator()
       
   315         {
       
   316             foreach ( SymbolCollection col in iCollections )
       
   317             {
       
   318                 yield return col;
       
   319             }
       
   320         }
       
   321 
       
   322         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
       
   323         {
       
   324             foreach ( SymbolCollection col in iCollections )
       
   325             {
       
   326                 yield return col;
       
   327             }
       
   328         }
       
   329         #endregion
       
   330 
       
   331         #region Internal methods
       
   332         private void WaitForLookupCache()
       
   333         {
       
   334             if ( iLookUpCacheWaiter != null )
       
   335             {
       
   336                 // Wait for the cache to become ready
       
   337                 iLookUpCacheWaiter.WaitOne();
       
   338 
       
   339                 // Must take the lock to either create or destroy waiter
       
   340                 lock ( iWaiterSyncRoot )
       
   341                 {
       
   342                     iLookUpCacheWaiter.Close();
       
   343                     iLookUpCacheWaiter = null;
       
   344                 }
       
   345             }
       
   346         }
       
   347 
       
   348         private void RemoveFromCache( SymbolCollection aCollection )
       
   349         {
       
   350             // Must wait if it's being built already
       
   351             WaitForLookupCache();
       
   352 
       
   353             // Must take the lock to either create or destroy waiter
       
   354             lock ( iWaiterSyncRoot )
       
   355             {
       
   356                 System.Diagnostics.Debug.Assert( iLookUpCacheWaiter == null );
       
   357                 //
       
   358                 iLookUpCacheWaiter = new AutoResetEvent( false );
       
   359                 ThreadPool.QueueUserWorkItem( new WaitCallback( BackgroundThreadRemoveFromCache ), aCollection );
       
   360             }
       
   361         }
       
   362 
       
   363         private void BackgroundThreadBuildLookupCache( object aNotUsed )
       
   364         {
       
   365             System.Diagnostics.Debug.Assert( iLookUpCacheWaiter != null );
       
   366 
       
   367             // This comparer will help us sort the ranges
       
   368             AddressCollectionPairComparer comparer = new AddressCollectionPairComparer();
       
   369 
       
   370             // Make sorted list entries
       
   371             lock ( iCollections )
       
   372             {
       
   373                 int colCount = iCollections.Count;
       
   374                 for ( int colIndex = 0; colIndex < colCount; colIndex++ )
       
   375                 {
       
   376                     SymbolCollection collection = iCollections[ colIndex ];
       
   377                     //
       
   378                     UpdateCacheForCollection( collection );
       
   379                 }
       
   380             }
       
   381 
       
   382             // Done building cache
       
   383             iLookUpCacheWaiter.Set();
       
   384         }
       
   385 
       
   386         private void BackgroundThreadRemoveFromCache( object aCollection )
       
   387         {
       
   388             System.Diagnostics.Debug.Assert( iLookUpCacheWaiter != null );
       
   389             SymbolCollection collection = (SymbolCollection) aCollection;
       
   390             //
       
   391             Predicate<AddressCollectionPair> predicate = delegate( AddressCollectionPair pair )
       
   392             {
       
   393                 bool match = ( pair.Collection == collection );
       
   394                 return match;
       
   395             };
       
   396             //
       
   397             lock ( iLookupCache )
       
   398             {
       
   399                 AddressCollectionPair temp = new AddressCollectionPair( new AddressRange(), collection );
       
   400                 iLookupCache.RemoveAll( predicate );
       
   401             }
       
   402             //
       
   403             iLookUpCacheWaiter.Set();
       
   404         }
       
   405 
       
   406         private void UpdateCacheForCollection( SymbolCollection aCollection )
       
   407         {
       
   408             bool isEmpty = aCollection.IsEmptyApartFromDefaultSymbol;
       
   409             if ( isEmpty == false )
       
   410             {
       
   411                 AddressRangeCollection ranges = aCollection.AddressRangeCollection;
       
   412                 if ( ranges != null )
       
   413                 {
       
   414                     // This comparer will help us sort the ranges
       
   415                     AddressCollectionPairComparer comparer = new AddressCollectionPairComparer();
       
   416 
       
   417                     int rangeCount = ranges.Count;
       
   418                     for ( int rangeIndex = 0; rangeIndex < rangeCount; rangeIndex++ )
       
   419                     {
       
   420                         AddressRange range = ranges[ rangeIndex ];
       
   421                         AddressCollectionPair pair = new AddressCollectionPair( range, aCollection );
       
   422                         //
       
   423                         lock ( iLookupCache )
       
   424                         {
       
   425                             int pos = iLookupCache.BinarySearch( pair, comparer );
       
   426                             if ( pos >= 0 )
       
   427                             {
       
   428                                 AddressCollectionPair overlapsWith = iLookupCache[ pos ];
       
   429                                 System.Diagnostics.Debug.WriteLine( string.Format( "Collection {0} [{1}] overlaps with existing collection: {2} [{3}]", pair.Collection.FileName, pair.Range, overlapsWith.Collection, overlapsWith.Range ) );
       
   430                             }
       
   431                             else
       
   432                             {
       
   433                                 pos = ~pos;
       
   434                                 iLookupCache.Insert( pos, pair );
       
   435                             }
       
   436                         }
       
   437                     }
       
   438                 }
       
   439             }
       
   440         }
       
   441         #endregion
       
   442 
       
   443         #region Internal classes
       
   444         private class AddressCollectionPair
       
   445         {
       
   446             #region Constructors
       
   447             public AddressCollectionPair( AddressRange aRange, SymbolCollection aCollection )
       
   448             {
       
   449                 iRange = aRange;
       
   450                 iCollection = aCollection;
       
   451             }
       
   452             #endregion
       
   453 
       
   454             #region Properties
       
   455             public AddressRange Range
       
   456             {
       
   457                 get { return iRange; }
       
   458             }
       
   459 
       
   460             public SymbolCollection Collection
       
   461             {
       
   462                 get { return iCollection; }
       
   463             }
       
   464             #endregion
       
   465 
       
   466             #region From System.Object
       
   467             public override string ToString()
       
   468             {
       
   469                 string ret = string.Format( "{0} {1}", iRange, iCollection.FileName.FileNameInDevice );
       
   470                 return ret;
       
   471             }
       
   472             #endregion
       
   473 
       
   474             #region Data members
       
   475             private readonly AddressRange iRange;
       
   476             private readonly SymbolCollection iCollection;
       
   477             #endregion
       
   478         }
       
   479 
       
   480         private class AddressCollectionPairComparer : IComparer<AddressCollectionPair>
       
   481         {
       
   482             public int Compare( AddressCollectionPair aLeft, AddressCollectionPair aRight )
       
   483             {
       
   484                 int ret = -1;
       
   485                 //
       
   486                 AddressRange lr = aLeft.Range;
       
   487                 AddressRange rr = aRight.Range;
       
   488                 //
       
   489                 if ( lr.Contains( rr ) || rr.Contains( lr ) )
       
   490                 {
       
   491                     ret = 0;
       
   492                 }
       
   493                 else
       
   494                 {
       
   495                     ret = lr.CompareTo( rr );
       
   496                 }
       
   497                 //
       
   498                 return ret;
       
   499             }
       
   500         }
       
   501         #endregion
       
   502 
       
   503         #region Data members
       
   504         private object iTag = null;
       
   505         private object iWaiterSyncRoot = new object();
       
   506         private AutoResetEvent iLookUpCacheWaiter = null;
       
   507         private List<SymbolCollection> iCollections = new List<SymbolCollection>();
       
   508         private List<AddressCollectionPair> iLookupCache = new List<AddressCollectionPair>();
       
   509         private Dictionary<PlatformFileName, SymbolCollection> iFileNameDictionary = new Dictionary<PlatformFileName, SymbolCollection>();
       
   510         #endregion
       
   511     }
       
   512 }