sysperfana/heapanalyser/UI/UIs/Console/HAUIConsole.cs
changeset 8 15296fd0af4a
equal deleted inserted replaced
7:8e12a575a9b5 8:15296fd0af4a
       
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 *
       
     5 * Redistribution and use in source and binary forms, with or without
       
     6 * modification, are permitted provided that the following conditions are met:
       
     7 *
       
     8 * - Redistributions of source code must retain the above copyright notice,
       
     9 *   this list of conditions and the following disclaimer.
       
    10 * - Redistributions in binary form must reproduce the above copyright notice,
       
    11 *   this list of conditions and the following disclaimer in the documentation
       
    12 *   and/or other materials provided with the distribution.
       
    13 * - Neither the name of Nokia Corporation nor the names of its contributors
       
    14 *   may be used to endorse or promote products derived from this software
       
    15 *   without specific prior written permission.
       
    16 *
       
    17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
       
    18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
       
    20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
       
    21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
       
    22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
       
    23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
       
    24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
       
    25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
       
    26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
       
    27 * POSSIBILITY OF SUCH DAMAGE.
       
    28 * 
       
    29 * Initial Contributors:
       
    30 * Nokia Corporation - initial contribution.
       
    31 *
       
    32 * Contributors:
       
    33 *
       
    34 * Description: 
       
    35 *
       
    36 */
       
    37 
       
    38 using System;
       
    39 using System.Text;
       
    40 using System.IO;
       
    41 using System.Xml;
       
    42 using System.Collections.Generic;
       
    43 using System.Windows.Forms;
       
    44 using SymbianUtils;
       
    45 using SymbianUtils.Settings;
       
    46 using SymbianUtils.Tracer;
       
    47 using SymbianUtils.FileSystem.Utilities;
       
    48 using SymbianXmlInputLib.Parser;
       
    49 using SymbianXmlInputLib.Parser.Nodes;
       
    50 using SymbianXmlInputLib.Elements;
       
    51 using SymbianXmlInputLib.Elements.Types.Category;
       
    52 using SymbianXmlInputLib.Elements.Types.FileSystem;
       
    53 using SymbianXmlInputLib.Elements.Types.Command;
       
    54 using SymbianDebugLib.Engine;
       
    55 using SymbianDebugLib.Entity;
       
    56 using SymbianStructuresLib.CodeSegments;
       
    57 using HeapLib;
       
    58 using HeapLib.Reconstructor;
       
    59 using HeapLib.Reconstructor.Misc;
       
    60 using HeapLib.Reconstructor.DataSources;
       
    61 using HeapLib.Reconstructor.DataSources.Analyser;
       
    62 using HeapUiLib.Dialogs;
       
    63 using HeapUiLib.Forms;
       
    64 using HeapAnalyser.Engine;
       
    65 using HeapAnalyser.Engine.Types;
       
    66 using HeapAnalyser.Exceptions;
       
    67 using HeapComparisonUiLib.Progress;
       
    68 using HeapAnalyser.UIs.Console.Files;
       
    69 using HeapAnalyser.UIs.Console.Inputs;
       
    70 
       
    71 namespace HeapAnalyser.UIs.Console
       
    72 {
       
    73 	public class HAUIConsole : HAUI
       
    74 	{
       
    75 		#region Constructors
       
    76         public HAUIConsole( string[] aArgs, XmlSettings aSettings, HeapWizardEngine aEngine, ITracer aTracer )
       
    77             : base( aArgs, aSettings, aEngine, aTracer )
       
    78 		{
       
    79             iInputs = new HACmdLineInputParameters( this, aEngine );
       
    80 		}
       
    81 		#endregion
       
    82 
       
    83         #region From HAUI
       
    84         public override bool IsAppropriateUI
       
    85         {
       
    86             get
       
    87             { 
       
    88                 // There must be command line arguments in order to use the command line UI
       
    89                 bool ret = base.Args.Length != 0;
       
    90                 //
       
    91                 if ( ret )
       
    92                 {
       
    93                     string[] args = base.Args;
       
    94                     for ( int i = 0; i < args.Length; i++ )
       
    95                     {
       
    96                         string cmd = args[ i ].Trim().ToUpper();
       
    97                         string nextArg = ( i < args.Length - 1 ? args[ i + 1 ].Trim().ToUpper() : string.Empty );
       
    98                         //
       
    99                         try
       
   100                         {
       
   101                             if ( cmd == KPluginInputParameter && nextArg != string.Empty )
       
   102                             {
       
   103                                 ret = true;
       
   104                                 break;
       
   105                             }
       
   106                         }
       
   107                         catch ( Exception )
       
   108                         {
       
   109                         }
       
   110                     }
       
   111                 }
       
   112                 //
       
   113                 return ret;
       
   114             }
       
   115         }
       
   116 
       
   117         public override Form PrepareInitialForm()
       
   118         {
       
   119             Form formToShow = null;
       
   120             //
       
   121             ParseInputs();
       
   122             PrimeDebugEngine();
       
   123             
       
   124             // If we're running the graphical UI then show the main analysis form,
       
   125             // otherwise just run the comparison operation and exit.
       
   126             switch ( base.Engine.OperationType )
       
   127             {
       
   128             case HeapWizardEngine.TOperationType.EOperationTypeAnalyseAndView:
       
   129                 formToShow = RunAnalyser();
       
   130                 break;
       
   131             case HeapWizardEngine.TOperationType.EOperationTypeCompareHeapDumps:
       
   132                 RunComparison();
       
   133                 break;
       
   134             }
       
   135 
       
   136             return formToShow;
       
   137         }
       
   138 
       
   139         public override Form HandleFormClosed( object aSender, EventArgs aArgs )
       
   140         {
       
   141             Form ret = null;
       
   142             return ret;
       
   143         }
       
   144         #endregion
       
   145 
       
   146 		#region Properties
       
   147 		#endregion
       
   148 
       
   149         #region Event handlers
       
   150         private void DbgEngine_EntityPrimingStarted( DbgEngine aEngine, DbgEntity aEntity, object aContext )
       
   151         {
       
   152             Trace( "[HA Cmd] Priming debug meta-data: " + aEntity.FullName );
       
   153         }
       
   154 
       
   155         private void DbgEngine_EntityPrimingProgress( DbgEngine aEngine, DbgEntity aEntity, object aContext )
       
   156         {
       
   157             if ( aContext != null )
       
   158             {
       
   159                 if ( aContext.GetType() == typeof( int ) )
       
   160                 {
       
   161                     int value = (int) aContext;
       
   162                     Trace( "[HA Cmd] Priming debug meta-data progress: {0:d3}% {1}", value, aEntity.FullName );
       
   163                 }
       
   164             }
       
   165         }
       
   166 
       
   167         private void DbgEngine_EntityPrimingComplete( DbgEngine aEngine, DbgEntity aEntity, object aContext )
       
   168         {
       
   169             Trace( "[HA Cmd] Primed debug meta-data: " + aEntity.FullName );
       
   170         }
       
   171 
       
   172         private void SymbolLibCodeSegDefinitionResolver_LocatedFile( string aFileName )
       
   173         {
       
   174             Trace( "[HA Cmd] Located debug meta data: " + aFileName );
       
   175         }
       
   176         #endregion
       
   177 
       
   178         #region Internal constants
       
   179         private const string KPluginInputParameter = "-INPUT";
       
   180         #endregion
       
   181 
       
   182 		#region Internal methods
       
   183         private void ParseInputs()
       
   184         {
       
   185             Trace( "[HA Cmd] ParseInputs() - START " );
       
   186             Trace( string.Empty );
       
   187             Trace( "[HA Cmd] command line: " + System.Environment.CommandLine );
       
   188             Trace( "[HA Cmd] command wd:   " + System.Environment.CurrentDirectory );
       
   189             Trace( "[HA Cmd] proc count:   " + System.Environment.ProcessorCount );
       
   190             Trace( "[HA Cmd] sysdir:       " + System.Environment.SystemDirectory );
       
   191             Trace( "[HA Cmd] version:      " + System.Environment.Version.ToString() );
       
   192             Trace( string.Empty );
       
   193 
       
   194             // We expect to see an "-input" parameter
       
   195             string inputFileName = ExtractCommandLineInputParameter( Args );
       
   196 
       
   197             // If no file was found then inputFileName will be an empty string.
       
   198             if ( string.IsNullOrEmpty( inputFileName ) )
       
   199             {
       
   200                 throw new HAUIException( "Input file parameter missing", HAUIException.KErrCommandLineArgumentsMissing );
       
   201             }
       
   202             else if ( !FSUtilities.Exists( inputFileName ) )
       
   203             {
       
   204                 throw new HAUIException( "Input file not found", HAUIException.KErrCommandLineArgumentsFileNotFound );
       
   205             }
       
   206             else
       
   207             {
       
   208                 Trace( "[HA Cmd] ParseInputs() - start read inputs" );
       
   209                 iInputs.Read( inputFileName );
       
   210                 Trace( "[HA Cmd] ParseInputs() - inputs read successfully" );
       
   211 
       
   212                 // Validate the inputs are correct.
       
   213                 if ( string.IsNullOrEmpty( iInputs.ThreadName ) )
       
   214                 {
       
   215                     throw new HAUIException( "The specified thread name is invalid", HAUIException.KErrCommandLineAnalysisThreadNameInvalid );
       
   216                 }
       
   217                 else 
       
   218                 {
       
   219                     // Validate input data
       
   220                     int sourceCount = iInputs.SourceFiles.Count;
       
   221                     switch( base.Engine.OperationType )
       
   222                     {
       
   223                     case HeapWizardEngine.TOperationType.EOperationTypeAnalyseAndView:
       
   224                         if ( iInputs.SourceFiles.Count != 1 && iInputs.SourceFiles[ 0 ].IsFile )
       
   225                         {
       
   226                             Trace( "[HA Cmd] ParseInputs() - viewer - missing source file!" );
       
   227                             throw new HAUIException( "Source file not specified", HAUIException.KErrCommandLineSourceFileNotFound );
       
   228                         }
       
   229                         break;
       
   230                     case HeapWizardEngine.TOperationType.EOperationTypeCompareHeapDumps:
       
   231                         if ( iInputs.SourceFiles.Count != 2 && iInputs.SourceFiles[ 0 ].IsFile && iInputs.SourceFiles[ 1 ].IsFile )
       
   232                         {
       
   233                             Trace( "[HA Cmd] ParseInputs() - comparison - missing source files!" );
       
   234                             throw new HAUIException( "Source files not specified", HAUIException.KErrCommandLineSourceFileNotFound );
       
   235                         }
       
   236                         break;
       
   237                     }
       
   238 
       
   239                     // Validate output (where needed)
       
   240                     if ( base.Engine.OperationType == HeapWizardEngine.TOperationType.EOperationTypeCompareHeapDumps )
       
   241                     {
       
   242                         bool outputSet = iInputs.OutputFile != null;
       
   243                         if ( !outputSet )
       
   244                         {
       
   245                             throw new HAUIException( "Output file not specified", HAUIException.KErrCommandLineAnalysisOutputInvalid );
       
   246                         }
       
   247                     }
       
   248                 }
       
   249             }
       
   250 
       
   251             Trace( "[HA Cmd] ParseInputs() - END" );
       
   252         }
       
   253 
       
   254         private void PrimeDebugEngine()
       
   255         {
       
   256             DbgEngine debugEngine = base.Engine.DebugEngine;
       
   257             //
       
   258             Exception primerException = null;
       
   259             HACmdLineFSEntityList<HACmdLineFSEntity> metaDataFiles = iInputs.MetaDataFiles;
       
   260             //
       
   261             try
       
   262             {
       
   263                 debugEngine.Clear();
       
   264 
       
   265                 foreach ( HACmdLineFSEntity entry in metaDataFiles )
       
   266                 {
       
   267                     Trace( "[HA Cmd] Seeding debug meta engine with entry: " + entry.Name );
       
   268                     DbgEntity entity = debugEngine.Add( entry.Name );
       
   269                     if ( entity != null )
       
   270                     {
       
   271                         Trace( "[HA Cmd] Entry type detected as: [" + entity.CategoryName + "]" );
       
   272                         entity.Tag = entry;
       
   273                     }
       
   274                     else
       
   275                     {
       
   276                         Trace( "[HA Cmd] Entry not handled: " + entry.Name );
       
   277                     }
       
   278                 }
       
   279 
       
   280                 // Listen to prime events
       
   281                 try
       
   282                 {
       
   283                     Trace( "[HA Cmd] Starting prime operation... " );
       
   284                     debugEngine.EntityPrimingStarted += new DbgEngine.EventHandler( DbgEngine_EntityPrimingStarted );
       
   285                     debugEngine.EntityPrimingProgress += new DbgEngine.EventHandler( DbgEngine_EntityPrimingProgress );
       
   286                     debugEngine.EntityPrimingComplete += new DbgEngine.EventHandler( DbgEngine_EntityPrimingComplete );
       
   287                     debugEngine.Prime( TSynchronicity.EAsynchronous );
       
   288                     Trace( "[HA Cmd] Debug meta data priming completed successfully." );
       
   289                 }
       
   290                 finally
       
   291                 {
       
   292                     debugEngine.EntityPrimingStarted -= new DbgEngine.EventHandler( DbgEngine_EntityPrimingStarted );
       
   293                     debugEngine.EntityPrimingProgress -= new DbgEngine.EventHandler( DbgEngine_EntityPrimingProgress );
       
   294                     debugEngine.EntityPrimingComplete -= new DbgEngine.EventHandler( DbgEngine_EntityPrimingComplete );
       
   295                 }
       
   296             }
       
   297             catch ( Exception exception )
       
   298             {
       
   299                 Trace( "[HA Cmd] Debug meta data priming exception: " + exception.Message + ", " + exception.StackTrace );
       
   300                 primerException = exception;
       
   301             }
       
   302         }
       
   303 
       
   304         private Form RunAnalyser()
       
   305         {
       
   306             string file = iInputs.SourceFiles[ 0 ].File.FullName;
       
   307             base.Engine.AnalysisEngine.DataSource = PrepareDataSource( file );
       
   308             base.Engine.AnalysisEngine.CreateParser();
       
   309             //
       
   310             Form ret = new HeapViewerForm( base.Engine.AnalysisEngine.Reconstructor, base.Settings );
       
   311             return ret;
       
   312         }
       
   313 
       
   314         private void RunComparison()
       
   315         {
       
   316             // Does the output file already exist? If so, try to delete it.
       
   317             // If not, then carry on.
       
   318             if ( iInputs.OutputFile.File.Exists )
       
   319             {
       
   320                 // If deletion fails then return an error by way of heap analyser exception.
       
   321                 try
       
   322                 {
       
   323                     iInputs.OutputFile.File.Delete();
       
   324                 }
       
   325                 catch ( Exception )
       
   326                 {
       
   327                     throw new HAUIException( "Could not overwrite output file", HAUIException.KErrCommandLineAnalysisOutputInvalid );
       
   328                 }
       
   329             }
       
   330 
       
   331             ComparisonEngineHeapData comparisonEngine = base.Engine.ComparisonEngineData;
       
   332             //
       
   333             string file1 = iInputs.SourceFiles[ 0 ].File.FullName;
       
   334             comparisonEngine.DataSource1 = PrepareDataSource( file1 );
       
   335             //
       
   336             string file2 = iInputs.SourceFiles[ 1 ].File.FullName;
       
   337             comparisonEngine.DataSource2 = PrepareDataSource( file2 );
       
   338             //
       
   339             comparisonEngine.OutputFileName = iInputs.OutputFile.File.FullName;
       
   340             base.Engine.ComparisonEngineData.CreateReconstructors();
       
   341             ComparisonProgressDialogData.Compare( comparisonEngine.Reconstructor1,
       
   342                                                   comparisonEngine.Reconstructor2,
       
   343                                                   comparisonEngine.OutputFileName );
       
   344 
       
   345         }
       
   346 
       
   347         private DataSource PrepareDataSource( string aFileName )
       
   348         {
       
   349             DataSourceAnalyser analyser = HeapReconstructorDataSourceAnalyserDialog.Analyse( aFileName );
       
   350             DataSourceCollection sources = analyser.DataSources;
       
   351             DataSource source = sources[ iInputs.ThreadName ];
       
   352             if ( source == null )
       
   353             {
       
   354                 throw new HAUIException( "Thread was not found in source data", HAUIException.KErrCommandLineAnalysisThreadNameInvalid );
       
   355             }
       
   356             //
       
   357             return source;
       
   358         }
       
   359 
       
   360         private static string ExtractCommandLineInputParameter( string[] aArgs )
       
   361         {
       
   362             string ret = string.Empty;
       
   363 
       
   364             // -input d:\ca_fullsummary.xml
       
   365             for ( int i = 0; i < aArgs.Length; i++ )
       
   366             {
       
   367                 string cmd = aArgs[ i ].Trim().ToUpper();
       
   368                 string nextArg = ( i < aArgs.Length - 1 ? aArgs[ i + 1 ].Trim().ToUpper() : string.Empty );
       
   369                 //
       
   370                 if ( cmd == KPluginInputParameter && nextArg != string.Empty )
       
   371                 {
       
   372                     ret = nextArg;
       
   373                 }
       
   374             }
       
   375 
       
   376             return ret;
       
   377         }
       
   378         #endregion
       
   379 
       
   380 		#region Data members
       
   381         private readonly HACmdLineInputParameters iInputs;
       
   382         #endregion
       
   383 	}
       
   384 }