diff -r 8e12a575a9b5 -r 15296fd0af4a sysperfana/heapanalyser/Libraries/Engine/HeapComparisonLib/CSV/Workers/CSVWorkerTwoDataSetComparator.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sysperfana/heapanalyser/Libraries/Engine/HeapComparisonLib/CSV/Workers/CSVWorkerTwoDataSetComparator.cs Tue Jun 15 12:47:20 2010 +0300 @@ -0,0 +1,246 @@ +/* +* 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.IO; +using System.Collections.Generic; +using System.Threading; +using SymbianUtils; + +namespace HeapComparisonLib.CSV +{ + internal class CSVWorkerTwoDataSetComparator : DisposableObject + { + #region Observer related + public enum TEvent + { + EExportingStarted = 0, + EExportingProgress, + EExportingComplete + } + + public delegate void Observer( TEvent aEvent, string aFullName ); + public event Observer eObserver; + #endregion + + #region Constructors & destructor + public CSVWorkerTwoDataSetComparator( CSVDataSet aCol1, CSVDataSet aCol2, string aOutputFileName ) + { + // Make copies because we actually dequeue items from the list as we processed them + // and we must not alter the originals or else we'll break the subsequent comparison(s) + iCol1 = new CSVDataSet( aCol1 ); + iCol2 = new CSVDataSet( aCol2 ); + iExcelExporter = new CSVExcelExporterTwoDataSets( aOutputFileName, aCol1.FileName, aCol2.FileName ); + } + #endregion + + #region API + public void CompareAndSaveAsync() + { + iWorkerThread = new System.Threading.Thread( new ThreadStart( ThreadFunction ) ); + iWorkerThread.Start(); + } + #endregion + + #region Properties + public int Progress + { + get + { + int count = 0; + int index = 0; + // + lock ( this ) + { + index = iIndex; + count = iPairings.Count; + } + + float ret = (float) index / (float) count; + ret *= 100.0f; + return (int) ret; + } + } + #endregion + + #region From DisposableObject + protected override void CleanupManagedResources() + { + try + { + if ( iExcelExporter != null ) + { + iExcelExporter.Dispose(); + iExcelExporter = null; + } + } + finally + { + base.CleanupManagedResources(); + } + } + #endregion + + #region Thread function + private void ThreadFunction() + { + // Report started + if ( eObserver != null ) + { + eObserver( TEvent.EExportingStarted, null ); + } + + // Create our list of sorted comparison pairs. + BuildPairs(); + + // Now compare them and export to excel + CompareAndExport(); + + // Dispose excel object - closes file + iExcelExporter.Dispose(); + iExcelExporter = null; + + // Report finished + if ( eObserver != null ) + { + eObserver( TEvent.EExportingComplete, null ); + } + } + #endregion + + #region Internal methods + private void BuildPairs() + { + // Treat the first collection as the master list. + int count = iCol1.Count; + for ( int i = count - 1; i >= 0; i-- ) + { + CSVThread master = iCol1[ i ]; + + // Remove primary entry also + iCol1.Remove( master ); + + // Create or locate secondary + CSVThread secondary = FindAppropriateSecondary( master, iCol2 ); + + // Create a pairing + iPairings.Add( master.FullName, new CSVThreadPair( master, secondary ) ); + } + + // Now do the same but for the secondary list this time. It should + // be largely empty. The only entries that will remain are threads + // which don't exist in the primary list. + count = iCol2.Count; + for ( int i = count - 1; i >= 0; i-- ) + { + CSVThread master = iCol2[ i ]; + + // Remove primary entry also + iCol2.Remove( master ); + + // Create or locate secondary + CSVThread secondary = FindAppropriateSecondary( master, iCol1 ); + + // Create a pairing - but this time the master is the 2nd entry + // in the pair. This ensures we keep the threads in the correct + // columns in the final excel spreadsheet. + iPairings.Add( master.FullName, new CSVThreadPair( secondary, master ) ); + } + } + + private CSVThread FindAppropriateSecondary( CSVThread aMaster, CSVDataSet aSecondaryCol ) + { + System.Diagnostics.Debug.Assert( aMaster.FullName != string.Empty ); + + // We must try to find the corresponding secondary thread with which to compare + // aMaster. + CSVThread secondary = aSecondaryCol[ aMaster.FullName ]; + if ( secondary == null ) + { + // Secondary collection doesn't contain this thread, so make a default entry. + secondary = CSVThread.NewDefault( aMaster.FullName ); + } + else + { + aSecondaryCol.Remove( secondary ); + } + + return secondary; + } + + private void CompareAndExport() + { + lock ( this ) + { + iIndex = 0; + } + + foreach ( KeyValuePair kvp in iPairings ) + { + CSVThreadPair pair = kvp.Value; + + // Report progress to any observers + if ( eObserver != null ) + { + eObserver( TEvent.EExportingProgress, kvp.Key ); + } + + lock ( this ) + { + ++iIndex; + } + + CompareAndExport( pair.Master, pair.Secondary ); + } + } + + private void CompareAndExport( CSVThread aMaster, CSVThread aSecondary ) + { + iExcelExporter.CompareThread( aMaster, aSecondary ); + } + #endregion + + #region Data members + private readonly CSVDataSet iCol1; + private readonly CSVDataSet iCol2; + private CSVExcelExporterTwoDataSets iExcelExporter = null; + private SortedList iPairings = new SortedList< string, CSVThreadPair>(); + private System.Threading.Thread iWorkerThread; + private int iIndex = 0; + #endregion + } +}