sysperfana/heapanalyser/UI/UIs/Console/HAUIConsole.cs
changeset 8 15296fd0af4a
--- /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
+	}
+}