--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/heapanalyser/UI/UIs/Console/HAUIConsole.cs Tue Jun 15 12:47:20 2010 +0300
@@ -0,0 +1,384 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* - Redistributions of source code must retain the above copyright notice,
+* this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+* - Neither the name of Nokia Corporation nor the names of its contributors
+* may be used to endorse or promote products derived from this software
+* without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+using System;
+using System.Text;
+using System.IO;
+using System.Xml;
+using System.Collections.Generic;
+using System.Windows.Forms;
+using SymbianUtils;
+using SymbianUtils.Settings;
+using SymbianUtils.Tracer;
+using SymbianUtils.FileSystem.Utilities;
+using SymbianXmlInputLib.Parser;
+using SymbianXmlInputLib.Parser.Nodes;
+using SymbianXmlInputLib.Elements;
+using SymbianXmlInputLib.Elements.Types.Category;
+using SymbianXmlInputLib.Elements.Types.FileSystem;
+using SymbianXmlInputLib.Elements.Types.Command;
+using SymbianDebugLib.Engine;
+using SymbianDebugLib.Entity;
+using SymbianStructuresLib.CodeSegments;
+using HeapLib;
+using HeapLib.Reconstructor;
+using HeapLib.Reconstructor.Misc;
+using HeapLib.Reconstructor.DataSources;
+using HeapLib.Reconstructor.DataSources.Analyser;
+using HeapUiLib.Dialogs;
+using HeapUiLib.Forms;
+using HeapAnalyser.Engine;
+using HeapAnalyser.Engine.Types;
+using HeapAnalyser.Exceptions;
+using HeapComparisonUiLib.Progress;
+using HeapAnalyser.UIs.Console.Files;
+using HeapAnalyser.UIs.Console.Inputs;
+
+namespace HeapAnalyser.UIs.Console
+{
+ public class HAUIConsole : HAUI
+ {
+ #region Constructors
+ public HAUIConsole( string[] aArgs, XmlSettings aSettings, HeapWizardEngine aEngine, ITracer aTracer )
+ : base( aArgs, aSettings, aEngine, aTracer )
+ {
+ iInputs = new HACmdLineInputParameters( this, aEngine );
+ }
+ #endregion
+
+ #region From HAUI
+ public override bool IsAppropriateUI
+ {
+ get
+ {
+ // There must be command line arguments in order to use the command line UI
+ bool ret = base.Args.Length != 0;
+ //
+ if ( ret )
+ {
+ string[] args = base.Args;
+ for ( int i = 0; i < args.Length; i++ )
+ {
+ string cmd = args[ i ].Trim().ToUpper();
+ string nextArg = ( i < args.Length - 1 ? args[ i + 1 ].Trim().ToUpper() : string.Empty );
+ //
+ try
+ {
+ if ( cmd == KPluginInputParameter && nextArg != string.Empty )
+ {
+ ret = true;
+ break;
+ }
+ }
+ catch ( Exception )
+ {
+ }
+ }
+ }
+ //
+ return ret;
+ }
+ }
+
+ public override Form PrepareInitialForm()
+ {
+ Form formToShow = null;
+ //
+ ParseInputs();
+ PrimeDebugEngine();
+
+ // If we're running the graphical UI then show the main analysis form,
+ // otherwise just run the comparison operation and exit.
+ switch ( base.Engine.OperationType )
+ {
+ case HeapWizardEngine.TOperationType.EOperationTypeAnalyseAndView:
+ formToShow = RunAnalyser();
+ break;
+ case HeapWizardEngine.TOperationType.EOperationTypeCompareHeapDumps:
+ RunComparison();
+ break;
+ }
+
+ return formToShow;
+ }
+
+ public override Form HandleFormClosed( object aSender, EventArgs aArgs )
+ {
+ Form ret = null;
+ return ret;
+ }
+ #endregion
+
+ #region Properties
+ #endregion
+
+ #region Event handlers
+ private void DbgEngine_EntityPrimingStarted( DbgEngine aEngine, DbgEntity aEntity, object aContext )
+ {
+ Trace( "[HA Cmd] Priming debug meta-data: " + aEntity.FullName );
+ }
+
+ private void DbgEngine_EntityPrimingProgress( DbgEngine aEngine, DbgEntity aEntity, object aContext )
+ {
+ if ( aContext != null )
+ {
+ if ( aContext.GetType() == typeof( int ) )
+ {
+ int value = (int) aContext;
+ Trace( "[HA Cmd] Priming debug meta-data progress: {0:d3}% {1}", value, aEntity.FullName );
+ }
+ }
+ }
+
+ private void DbgEngine_EntityPrimingComplete( DbgEngine aEngine, DbgEntity aEntity, object aContext )
+ {
+ Trace( "[HA Cmd] Primed debug meta-data: " + aEntity.FullName );
+ }
+
+ private void SymbolLibCodeSegDefinitionResolver_LocatedFile( string aFileName )
+ {
+ Trace( "[HA Cmd] Located debug meta data: " + aFileName );
+ }
+ #endregion
+
+ #region Internal constants
+ private const string KPluginInputParameter = "-INPUT";
+ #endregion
+
+ #region Internal methods
+ private void ParseInputs()
+ {
+ Trace( "[HA Cmd] ParseInputs() - START " );
+ Trace( string.Empty );
+ Trace( "[HA Cmd] command line: " + System.Environment.CommandLine );
+ Trace( "[HA Cmd] command wd: " + System.Environment.CurrentDirectory );
+ Trace( "[HA Cmd] proc count: " + System.Environment.ProcessorCount );
+ Trace( "[HA Cmd] sysdir: " + System.Environment.SystemDirectory );
+ Trace( "[HA Cmd] version: " + System.Environment.Version.ToString() );
+ Trace( string.Empty );
+
+ // We expect to see an "-input" parameter
+ string inputFileName = ExtractCommandLineInputParameter( Args );
+
+ // If no file was found then inputFileName will be an empty string.
+ if ( string.IsNullOrEmpty( inputFileName ) )
+ {
+ throw new HAUIException( "Input file parameter missing", HAUIException.KErrCommandLineArgumentsMissing );
+ }
+ else if ( !FSUtilities.Exists( inputFileName ) )
+ {
+ throw new HAUIException( "Input file not found", HAUIException.KErrCommandLineArgumentsFileNotFound );
+ }
+ else
+ {
+ Trace( "[HA Cmd] ParseInputs() - start read inputs" );
+ iInputs.Read( inputFileName );
+ Trace( "[HA Cmd] ParseInputs() - inputs read successfully" );
+
+ // Validate the inputs are correct.
+ if ( string.IsNullOrEmpty( iInputs.ThreadName ) )
+ {
+ throw new HAUIException( "The specified thread name is invalid", HAUIException.KErrCommandLineAnalysisThreadNameInvalid );
+ }
+ else
+ {
+ // Validate input data
+ int sourceCount = iInputs.SourceFiles.Count;
+ switch( base.Engine.OperationType )
+ {
+ case HeapWizardEngine.TOperationType.EOperationTypeAnalyseAndView:
+ if ( iInputs.SourceFiles.Count != 1 && iInputs.SourceFiles[ 0 ].IsFile )
+ {
+ Trace( "[HA Cmd] ParseInputs() - viewer - missing source file!" );
+ throw new HAUIException( "Source file not specified", HAUIException.KErrCommandLineSourceFileNotFound );
+ }
+ break;
+ case HeapWizardEngine.TOperationType.EOperationTypeCompareHeapDumps:
+ if ( iInputs.SourceFiles.Count != 2 && iInputs.SourceFiles[ 0 ].IsFile && iInputs.SourceFiles[ 1 ].IsFile )
+ {
+ Trace( "[HA Cmd] ParseInputs() - comparison - missing source files!" );
+ throw new HAUIException( "Source files not specified", HAUIException.KErrCommandLineSourceFileNotFound );
+ }
+ break;
+ }
+
+ // Validate output (where needed)
+ if ( base.Engine.OperationType == HeapWizardEngine.TOperationType.EOperationTypeCompareHeapDumps )
+ {
+ bool outputSet = iInputs.OutputFile != null;
+ if ( !outputSet )
+ {
+ throw new HAUIException( "Output file not specified", HAUIException.KErrCommandLineAnalysisOutputInvalid );
+ }
+ }
+ }
+ }
+
+ Trace( "[HA Cmd] ParseInputs() - END" );
+ }
+
+ private void PrimeDebugEngine()
+ {
+ DbgEngine debugEngine = base.Engine.DebugEngine;
+ //
+ Exception primerException = null;
+ HACmdLineFSEntityList<HACmdLineFSEntity> metaDataFiles = iInputs.MetaDataFiles;
+ //
+ try
+ {
+ debugEngine.Clear();
+
+ foreach ( HACmdLineFSEntity entry in metaDataFiles )
+ {
+ Trace( "[HA Cmd] Seeding debug meta engine with entry: " + entry.Name );
+ DbgEntity entity = debugEngine.Add( entry.Name );
+ if ( entity != null )
+ {
+ Trace( "[HA Cmd] Entry type detected as: [" + entity.CategoryName + "]" );
+ entity.Tag = entry;
+ }
+ else
+ {
+ Trace( "[HA Cmd] Entry not handled: " + entry.Name );
+ }
+ }
+
+ // Listen to prime events
+ try
+ {
+ Trace( "[HA Cmd] Starting prime operation... " );
+ debugEngine.EntityPrimingStarted += new DbgEngine.EventHandler( DbgEngine_EntityPrimingStarted );
+ debugEngine.EntityPrimingProgress += new DbgEngine.EventHandler( DbgEngine_EntityPrimingProgress );
+ debugEngine.EntityPrimingComplete += new DbgEngine.EventHandler( DbgEngine_EntityPrimingComplete );
+ debugEngine.Prime( TSynchronicity.EAsynchronous );
+ Trace( "[HA Cmd] Debug meta data priming completed successfully." );
+ }
+ finally
+ {
+ debugEngine.EntityPrimingStarted -= new DbgEngine.EventHandler( DbgEngine_EntityPrimingStarted );
+ debugEngine.EntityPrimingProgress -= new DbgEngine.EventHandler( DbgEngine_EntityPrimingProgress );
+ debugEngine.EntityPrimingComplete -= new DbgEngine.EventHandler( DbgEngine_EntityPrimingComplete );
+ }
+ }
+ catch ( Exception exception )
+ {
+ Trace( "[HA Cmd] Debug meta data priming exception: " + exception.Message + ", " + exception.StackTrace );
+ primerException = exception;
+ }
+ }
+
+ private Form RunAnalyser()
+ {
+ string file = iInputs.SourceFiles[ 0 ].File.FullName;
+ base.Engine.AnalysisEngine.DataSource = PrepareDataSource( file );
+ base.Engine.AnalysisEngine.CreateParser();
+ //
+ Form ret = new HeapViewerForm( base.Engine.AnalysisEngine.Reconstructor, base.Settings );
+ return ret;
+ }
+
+ private void RunComparison()
+ {
+ // Does the output file already exist? If so, try to delete it.
+ // If not, then carry on.
+ if ( iInputs.OutputFile.File.Exists )
+ {
+ // If deletion fails then return an error by way of heap analyser exception.
+ try
+ {
+ iInputs.OutputFile.File.Delete();
+ }
+ catch ( Exception )
+ {
+ throw new HAUIException( "Could not overwrite output file", HAUIException.KErrCommandLineAnalysisOutputInvalid );
+ }
+ }
+
+ ComparisonEngineHeapData comparisonEngine = base.Engine.ComparisonEngineData;
+ //
+ string file1 = iInputs.SourceFiles[ 0 ].File.FullName;
+ comparisonEngine.DataSource1 = PrepareDataSource( file1 );
+ //
+ string file2 = iInputs.SourceFiles[ 1 ].File.FullName;
+ comparisonEngine.DataSource2 = PrepareDataSource( file2 );
+ //
+ comparisonEngine.OutputFileName = iInputs.OutputFile.File.FullName;
+ base.Engine.ComparisonEngineData.CreateReconstructors();
+ ComparisonProgressDialogData.Compare( comparisonEngine.Reconstructor1,
+ comparisonEngine.Reconstructor2,
+ comparisonEngine.OutputFileName );
+
+ }
+
+ private DataSource PrepareDataSource( string aFileName )
+ {
+ DataSourceAnalyser analyser = HeapReconstructorDataSourceAnalyserDialog.Analyse( aFileName );
+ DataSourceCollection sources = analyser.DataSources;
+ DataSource source = sources[ iInputs.ThreadName ];
+ if ( source == null )
+ {
+ throw new HAUIException( "Thread was not found in source data", HAUIException.KErrCommandLineAnalysisThreadNameInvalid );
+ }
+ //
+ return source;
+ }
+
+ private static string ExtractCommandLineInputParameter( string[] aArgs )
+ {
+ string ret = string.Empty;
+
+ // -input d:\ca_fullsummary.xml
+ for ( int i = 0; i < aArgs.Length; i++ )
+ {
+ string cmd = aArgs[ i ].Trim().ToUpper();
+ string nextArg = ( i < aArgs.Length - 1 ? aArgs[ i + 1 ].Trim().ToUpper() : string.Empty );
+ //
+ if ( cmd == KPluginInputParameter && nextArg != string.Empty )
+ {
+ ret = nextArg;
+ }
+ }
+
+ return ret;
+ }
+ #endregion
+
+ #region Data members
+ private readonly HACmdLineInputParameters iInputs;
+ #endregion
+ }
+}