crashanalysercmd/Libraries/Engine/CrashItemLib/Crash/Container/CIContainer.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;
       
    19 using System.Collections.Generic;
       
    20 using System.IO;
       
    21 using System.Reflection;
       
    22 using CrashItemLib.Crash.Base;
       
    23 using CrashItemLib.Crash.Events;
       
    24 using CrashItemLib.Crash.Header;
       
    25 using CrashItemLib.Crash.InfoHW;
       
    26 using CrashItemLib.Crash.InfoSW;
       
    27 using CrashItemLib.Crash.Messages;
       
    28 using CrashItemLib.Crash.Source;
       
    29 using CrashItemLib.Crash.Summarisable;
       
    30 using CrashItemLib.Crash.Symbols;
       
    31 using CrashItemLib.Crash.Traces;
       
    32 using CrashItemLib.Crash.Reports;
       
    33 using CrashItemLib.Crash.Registers;
       
    34 using CrashItemLib.Engine;
       
    35 using SymbianDebugLib.Engine;
       
    36 
       
    37 namespace CrashItemLib.Crash.Container
       
    38 {
       
    39     public sealed class CIContainer : CIElement, ICISymbolManager
       
    40     {
       
    41         #region Enumerations
       
    42         internal enum TCIElementEventType
       
    43         {
       
    44             ECIEventChildAdded = 0,
       
    45             ECIEventChildRemoved,
       
    46         }
       
    47 
       
    48         public enum TStatus
       
    49         {
       
    50             EStatusDefault = 0,
       
    51             EStatusErrorContainer
       
    52         }
       
    53         #endregion
       
    54 
       
    55         #region Delegates & events
       
    56         internal delegate void ElementEventHandler( CIContainer aContainer, CIElement aElement, TCIElementEventType aType );
       
    57         internal event ElementEventHandler ElementEvents;
       
    58         #endregion
       
    59 
       
    60         #region Static constructors
       
    61         internal static CIContainer New( CIEngine aEngine, CISource aSource )
       
    62         {
       
    63             CIContainer ret = new CIContainer( aEngine, aSource );
       
    64             return ret;
       
    65         }
       
    66 
       
    67         public static CIContainer NewErrorContainer( CIEngine aEngine, CISource aSource )
       
    68         {
       
    69             CIContainer ret = new CIContainer( aEngine, aSource );
       
    70             ret.Status = TStatus.EStatusErrorContainer;
       
    71             return ret;
       
    72         }
       
    73         #endregion
       
    74 
       
    75         #region Constructors
       
    76         private CIContainer( CIEngine aEngine, CISource aSource )
       
    77             : base( KRootElementId )
       
    78 		{
       
    79             iEngine = aEngine;
       
    80 
       
    81             // Immediately set up container association (to point to ourself) 
       
    82             // just incase...
       
    83             base.Container = this;
       
    84 
       
    85             // And indicate, that since we *are* the container, we want all our children
       
    86             // to automatically be "in it" too.
       
    87             base.IsInContainer = true;
       
    88 
       
    89             // Add source descriptor
       
    90             CISourceElement source = new CISourceElement( this, aSource );
       
    91             AddChild( source );
       
    92 
       
    93             // Add other mandatory elements
       
    94             AddMandatoryElements();
       
    95 		}
       
    96 		#endregion
       
    97 
       
    98         #region API
       
    99         public IEnumerable<CISummarisableEntity> GetSummarisableEnumerator()
       
   100         {
       
   101             CIElementList<CISummarisableEntity> list = base.ChildrenByType<CISummarisableEntity>();
       
   102             return list;
       
   103         }
       
   104         #endregion
       
   105 
       
   106         #region Constants
       
   107         public const int KRootElementId = CIElementIdProvider.KInitialStartingValue;
       
   108         #endregion
       
   109 
       
   110         #region Properties
       
   111         public object Tag
       
   112 		{
       
   113 			get { return iTag; }
       
   114 			set { iTag = value; }
       
   115 		}
       
   116 
       
   117         public TStatus Status
       
   118         {
       
   119             get { return iStatus; }
       
   120             set { iStatus = value; }
       
   121         }
       
   122 
       
   123         public string[] FileNames
       
   124         {
       
   125             get
       
   126             {
       
   127                 List<string> files = new List<string>();
       
   128                 if ( iFileNames != null )
       
   129                 {
       
   130                     files.AddRange( iFileNames );
       
   131                 }
       
   132                 return files.ToArray();
       
   133             }
       
   134         }
       
   135 
       
   136         public override CIEngine Engine
       
   137         {
       
   138             get { return iEngine; }
       
   139         }
       
   140 
       
   141         public CISummarisableEntity PrimarySummary
       
   142         {
       
   143             get
       
   144             {
       
   145                 CISummarisableEntity ret = null;
       
   146 
       
   147                 // The primary summary is the first summary we can locate
       
   148                 // that relates to a crash.
       
   149                 CISummarisableEntityList summaries = Summaries;
       
   150                 foreach ( CISummarisableEntity entity in summaries )
       
   151                 {
       
   152                     bool isCrash = entity.IsAbnormalTermination;
       
   153                     if ( isCrash )
       
   154                     {
       
   155                         // Prefer threads to raw stack items.
       
   156                         if ( ret != null )
       
   157                         {
       
   158                             // If the 'best match' so far is just a stack, then replace it with whatever
       
   159                             // we've just found. This means we could replace a raw stack with another raw
       
   160                             // stack. We could never replace a thread entity with a stack entity though.
       
   161                             if ( ret.IsAvailable( CISummarisableEntity.TElement.EElementThread ) == false )
       
   162                             {
       
   163                                 ret = entity;
       
   164                             }
       
   165                         }
       
   166                         else
       
   167                         {
       
   168                             ret = entity;
       
   169                         }
       
   170                     }
       
   171                 }
       
   172 
       
   173                 return ret;
       
   174             }
       
   175         }
       
   176         #endregion
       
   177 
       
   178         #region Mandatory elements
       
   179         public CIHeader Header
       
   180         {
       
   181             get { return (CIHeader) ChildByType( typeof( CIHeader ) ); }
       
   182         }
       
   183 
       
   184         public CIEventList Events
       
   185         {
       
   186             get { return (CIEventList) ChildByType( typeof( CIEventList ) ); }
       
   187         }
       
   188 
       
   189         public CITraceData Traces
       
   190         {
       
   191             get { return (CITraceData) ChildByType( typeof( CITraceData ) ); }
       
   192         }
       
   193 
       
   194         public CISourceElement Source
       
   195         {
       
   196             get { return (CISourceElement) ChildByType( typeof( CISourceElement ) ); }
       
   197         }
       
   198 
       
   199         public CISymbolDictionary Symbols
       
   200         {
       
   201             get { return (CISymbolDictionary) ChildByType( typeof( CISymbolDictionary ) ); }
       
   202         }
       
   203 
       
   204         public CIMessageDictionary Messages
       
   205         {
       
   206             get { return (CIMessageDictionary) ChildByType( typeof( CIMessageDictionary ) ); }
       
   207         }
       
   208 
       
   209         public CISummarisableEntityList Summaries
       
   210         {
       
   211             get { return (CISummarisableEntityList) ChildByType( typeof( CISummarisableEntityList ) ); }
       
   212         }
       
   213 
       
   214         public CIRegisterListCollection Registers
       
   215         {
       
   216             get
       
   217             {
       
   218                 return (CIRegisterListCollection) ChildByType( typeof( CIRegisterListCollection ) );
       
   219             }
       
   220         }
       
   221 
       
   222         public CIReportInfo ReportInfo
       
   223         {
       
   224             get { return (CIReportInfo) ChildByType( typeof( CIReportInfo ) ); }
       
   225         }
       
   226         #endregion
       
   227 
       
   228         #region Internal methods
       
   229         internal void RunFinalizers( CIElementFinalizationParameters aParams )
       
   230         {
       
   231             Queue<CIElement> mustBeCalledLast = new Queue<CIElement>();
       
   232             base.DoFinalize( aParams, mustBeCalledLast, false );
       
   233 
       
   234             // Now call the elements that are to be finalized last
       
   235             while ( mustBeCalledLast.Count > 0 )
       
   236             {
       
   237                 CIElement child = mustBeCalledLast.Dequeue();
       
   238                 child.DoFinalize( aParams, mustBeCalledLast, true );
       
   239             }
       
   240         }
       
   241         
       
   242         internal int GetNextElementId()
       
   243         {
       
   244             return Engine.GetNextElementId();
       
   245         }
       
   246 
       
   247         private void AddMandatoryElements()
       
   248         {
       
   249             Type attribType = typeof( CIElementAttributeMandatory );
       
   250             Type[] types = Assembly.GetExecutingAssembly().GetTypes();
       
   251             //
       
   252             foreach( Type t in types)
       
   253             {
       
   254                 // Get all the constructors for the type
       
   255                 if ( !t.IsAbstract && typeof( CIElement ).IsAssignableFrom( t ) )
       
   256                 {
       
   257                     ConstructorInfo[] ctors = t.GetConstructors( BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public );
       
   258                     foreach ( ConstructorInfo ctor in ctors )
       
   259                     {
       
   260                         // If the specified ctor is decorated with the "mandatory" attribute
       
   261                         // then it must be a mandatory class, so new an instance up...
       
   262                         object[] attribs = ctor.GetCustomAttributes( attribType, false );
       
   263                         if ( attribs.Length > 0 )
       
   264                         {
       
   265                             // Check that it has the expected signature.
       
   266                             // We expect mandatory constructors to take only a single parameter
       
   267                             // which is the container itself, i.e. this object
       
   268                             ParameterInfo[] parameters = ctor.GetParameters();
       
   269                             if ( parameters.Length == 1 && parameters[ 0 ].ParameterType == this.GetType() )
       
   270                             {
       
   271                                 CIElement element = ctor.Invoke( new object[] { this } ) as CIElement;
       
   272                                 if ( element != null )
       
   273                                 {
       
   274                                     element.Parent = this;
       
   275                                     AddChild( element );
       
   276                                 }
       
   277                             }
       
   278                         }
       
   279                     }
       
   280                 }
       
   281             }
       
   282             //
       
   283             AddChild( new CISymbolDictionary( this ) );
       
   284         }
       
   285 
       
   286         private void CacheFileNames( DbgEngine aDebugEngine )
       
   287         {
       
   288             if ( iFileNames == null )
       
   289             {
       
   290                 iFileNames = new List<string>();
       
   291 
       
   292                 CISourceElement source = Source;
       
   293                 foreach ( FileInfo file in source.AllFiles )
       
   294                 {
       
   295                     iFileNames.Add( file.FullName );
       
   296                 }
       
   297 
       
   298                 // Meta-data files
       
   299                 SymbianUtils.FileSystem.FSEntity[] entities = aDebugEngine.FileSystemEntities;
       
   300                 foreach ( SymbianUtils.FileSystem.FSEntity e in entities )
       
   301                 {
       
   302                     if ( e.IsFile )
       
   303                     {
       
   304                         FileInfo file = ( (SymbianUtils.FileSystem.FSEntityFile) e ).File;
       
   305                         iFileNames.Add( file.FullName );
       
   306                     }
       
   307                 }
       
   308             }
       
   309         }
       
   310         #endregion
       
   311 
       
   312         #region Internal container event propagation
       
   313         internal void OnContainerElementRegistered( CIElement aElement )
       
   314         {
       
   315             if ( ElementEvents != null )
       
   316             {
       
   317                 ElementEvents( this, aElement, TCIElementEventType.ECIEventChildAdded );
       
   318             }
       
   319         }
       
   320 
       
   321         internal void OnContainerElementUnregistered( CIElement aElement )
       
   322         {
       
   323             if ( ElementEvents != null )
       
   324             {
       
   325                 ElementEvents( this, aElement, TCIElementEventType.ECIEventChildRemoved );
       
   326             }
       
   327         }
       
   328         #endregion
       
   329 
       
   330         #region From ICISymbolManager
       
   331         public CISymbolDictionary SymbolDictionary
       
   332         {
       
   333             get { return this.Symbols; }
       
   334         }
       
   335         #endregion
       
   336 
       
   337         #region From CIElement
       
   338         /// <summary>
       
   339         /// Ensure that we only allow single instances of some objects to be added
       
   340         /// as direct children.
       
   341         /// </summary>
       
   342         public override void AddChild( CIElement aChild )
       
   343         {
       
   344             bool exception = false;
       
   345             //
       
   346             if ( aChild is CIEventList && Events != null )
       
   347             {
       
   348                 exception = true;
       
   349             }
       
   350             else if ( aChild is CISymbolDictionary && Symbols != null )
       
   351             {
       
   352                 exception = true;
       
   353             }
       
   354             else if ( aChild is CIMessageDictionary && Messages != null )
       
   355             {
       
   356                 exception = true;
       
   357             }
       
   358             else if ( aChild is CISourceElement && Source != null )
       
   359             {
       
   360                 exception = true;
       
   361             }
       
   362             else if ( aChild is CISummarisableEntityList && Summaries != null )
       
   363             {
       
   364                 exception = true;
       
   365             }
       
   366             else if ( aChild is CIHeader && Header != null )
       
   367             {
       
   368                 exception = true;
       
   369             }
       
   370             else if ( aChild is CIReportInfo && ReportInfo != null )
       
   371             {
       
   372                 exception = true;
       
   373             }
       
   374             else
       
   375             {
       
   376                 // These aren't mandatory, but there should only be one...
       
   377                 int count = -1;
       
   378                 if ( aChild is CIInfoHW )
       
   379                 {
       
   380                     count = base.ChildrenByType<CIInfoHW>().Count;
       
   381                 }
       
   382                 else if ( aChild is CIInfoSW )
       
   383                 {
       
   384                     count = base.ChildrenByType<CIInfoSW>().Count;
       
   385                 }
       
   386 
       
   387                 if ( count > 1 )
       
   388                 {
       
   389                     throw new ArgumentException( "An instance of the specified object has already been added to the container" );
       
   390                 }
       
   391             }
       
   392 
       
   393             if ( exception )
       
   394             {
       
   395                 throw new ArgumentException( "Can only add a single instance of " + aChild.GetType() + " to the container" );
       
   396             }
       
   397 
       
   398             base.AddChild( aChild );
       
   399         }
       
   400 
       
   401         /// <summary>
       
   402         /// Called by CIElement when an object is *directly* added
       
   403         /// as a child of the container.
       
   404         /// </summary>
       
   405         protected override void OnElementAddedToSelf( CIElement aElement )
       
   406         {
       
   407             // The master switch that ensures all elements and their children
       
   408             // are flagged as in the container.
       
   409             aElement.IsInContainer = true;
       
   410         }
       
   411 
       
   412         internal override void OnFinalize( CIElementFinalizationParameters aParams )
       
   413         {
       
   414             base.OnFinalize( aParams );
       
   415 
       
   416             // Cache file names
       
   417             CacheFileNames( aParams.DebugEngine );
       
   418         }
       
   419         #endregion
       
   420 
       
   421         #region Data members
       
   422         private readonly CIEngine iEngine;
       
   423         private object iTag = null;
       
   424         private TStatus iStatus = TStatus.EStatusDefault;
       
   425         private List<string> iFileNames = null;
       
   426 		#endregion
       
   427     }
       
   428 }