sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/AnalyserDataProcessor.java
changeset 2 b9ab3b238396
child 5 844b047e260d
equal deleted inserted replaced
1:1050670c6980 2:b9ab3b238396
       
     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 the License "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 
       
    18 package com.nokia.carbide.cpp.internal.pi.analyser;
       
    19 
       
    20 import java.io.ByteArrayInputStream;
       
    21 import java.io.File;
       
    22 import java.io.IOException;
       
    23 import java.io.PrintWriter;
       
    24 import java.io.StringWriter;
       
    25 import java.lang.reflect.InvocationTargetException;
       
    26 import java.net.URI;
       
    27 import java.util.ArrayList;
       
    28 import java.util.Enumeration;
       
    29 import java.util.Hashtable;
       
    30 import java.util.Iterator;
       
    31 
       
    32 import org.eclipse.core.resources.IFile;
       
    33 import org.eclipse.core.resources.WorkspaceJob;
       
    34 import org.eclipse.core.runtime.CoreException;
       
    35 import org.eclipse.core.runtime.IProgressMonitor;
       
    36 import org.eclipse.core.runtime.IStatus;
       
    37 import org.eclipse.core.runtime.Status;
       
    38 import org.eclipse.core.runtime.jobs.IJobChangeEvent;
       
    39 import org.eclipse.core.runtime.jobs.IJobChangeListener;
       
    40 import org.eclipse.core.runtime.jobs.Job;
       
    41 import org.eclipse.jface.operation.IRunnableWithProgress;
       
    42 import org.eclipse.swt.events.PaintEvent;
       
    43 import org.eclipse.swt.events.PaintListener;
       
    44 import org.eclipse.swt.widgets.Composite;
       
    45 import org.eclipse.swt.widgets.Display;
       
    46 import org.eclipse.ui.IEditorPart;
       
    47 import org.eclipse.ui.PartInitException;
       
    48 import org.eclipse.ui.PlatformUI;
       
    49 import org.eclipse.ui.ide.IDE;
       
    50 import org.eclipse.ui.progress.IProgressService;
       
    51 
       
    52 import com.nokia.carbide.cpp.internal.pi.manager.PluginInitialiser;
       
    53 import com.nokia.carbide.cpp.internal.pi.model.FunctionResolver;
       
    54 import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
       
    55 import com.nokia.carbide.cpp.internal.pi.model.RefinableTrace;
       
    56 import com.nokia.carbide.cpp.internal.pi.model.TraceDataRepository;
       
    57 import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
       
    58 import com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace;
       
    59 import com.nokia.carbide.cpp.internal.pi.plugin.model.IVisualizable;
       
    60 import com.nokia.carbide.cpp.internal.pi.test.AnalysisInfoHandler;
       
    61 import com.nokia.carbide.cpp.internal.pi.test.IProvideTraceAdditionalInfo;
       
    62 import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
       
    63 import com.nokia.carbide.cpp.internal.pi.visual.GraphDrawRequest;
       
    64 import com.nokia.carbide.cpp.internal.pi.visual.PICompositePanel;
       
    65 import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
       
    66 import com.nokia.carbide.cpp.pi.importer.SampleImporter;
       
    67 import com.nokia.carbide.cpp.pi.util.GeneralMessages;
       
    68 import com.nokia.carbide.cpp.pi.util.PIExceptionRuntime;
       
    69 
       
    70 
       
    71 /*
       
    72  * Class for abstracting data processing core routine for open and import
       
    73  */
       
    74 
       
    75 public class AnalyserDataProcessor {
       
    76 	// whether the profile file was read correctly
       
    77 	public static int STATE_OK				= 0;
       
    78 	public static int STATE_IMPORTING		= 1;
       
    79 	public static int STATE_OPENING			= 2;
       
    80 	public static int STATE_TIMESTAMP		= 3;
       
    81 	public static int STATE_CANCELED		= 4;
       
    82 	public static int STATE_INVALID			= 5;
       
    83 	public static int TOTAL_PROGRESS_COUNT	= 10000;
       
    84 
       
    85 	static AnalyserDataProcessor instance = null;
       
    86 
       
    87 	// following states should be cleanup for every run
       
    88 	
       
    89 	// There should be only one progress monitor used by data processor
       
    90 	// regardless the task, and we don't want to expose public interface
       
    91 	// that juggle around progress monitor, to avoid messy situation of
       
    92 	// multiple progress indicator
       
    93 	static IProgressMonitor mp = null;
       
    94 	static Exception lastException = null;
       
    95 	private static int analyserDataProcessorState = STATE_INVALID;
       
    96 		
       
    97 	private AnalyserDataProcessor() {
       
    98 		// singleton
       
    99 	}
       
   100 	
       
   101 	public static AnalyserDataProcessor getInstance() {
       
   102 		if (instance == null) {
       
   103 			instance = new AnalyserDataProcessor();
       
   104 		}
       
   105 		return instance;
       
   106 	}
       
   107 	
       
   108 	// return whether the processed data file was successfully read
       
   109 	public int getState() {
       
   110 		return analyserDataProcessorState;
       
   111 	}
       
   112 	
       
   113 	public void setImportFailed() {
       
   114 		analyserDataProcessorState = STATE_INVALID;
       
   115 	}
       
   116 	
       
   117 	private void setProgressMonitor (IProgressMonitor progressMonitor) {
       
   118 		mp = progressMonitor;
       
   119 	}
       
   120 	
       
   121 	private IProgressMonitor getProgressMonitor() {
       
   122 		return mp;
       
   123 	}
       
   124 		
       
   125 	public Exception getLastException() {
       
   126 		return lastException;
       
   127 	}
       
   128 	
       
   129 	private void importNewAnalysis(Hashtable<Integer,String> traceFileNames, int uid) throws InterruptedException, InvocationTargetException {
       
   130 		analyserDataProcessorState = STATE_IMPORTING;
       
   131 		final int workUnitsForImport = TOTAL_PROGRESS_COUNT * 60 / 100;
       
   132 		int workUnitsLeft = workUnitsForImport * 99 / 100;
       
   133 		
       
   134 		checkCancelledThrowIE();
       
   135 			
       
   136 		// loop through all the plugins associated with traces
       
   137 		Enumeration<AbstractPiPlugin> enumer = PluginInitialiser.getPluginInstances(uid, "com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace"); //$NON-NLS-1$
       
   138 		Enumeration<AbstractPiPlugin> tmpEnum = PluginInitialiser.getPluginInstances(uid, "com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace"); //$NON-NLS-1$
       
   139 		int numberOfPlugins = 0;
       
   140 		while (tmpEnum.hasMoreElements()) {
       
   141 			numberOfPlugins++;
       
   142 			tmpEnum.nextElement();
       
   143 		}
       
   144 		while (enumer.hasMoreElements())
       
   145     	{
       
   146     		ITrace plugin = (ITrace)enumer.nextElement();
       
   147     		int traceId = plugin.getTraceId();
       
   148     		AbstractPiPlugin p = (AbstractPiPlugin)plugin;
       
   149     		
       
   150     		// map trace plugins to this analysis data
       
   151     		NpiInstanceRepository.getInstance().addPlugin(uid, p);
       
   152     		if (traceId != -1)
       
   153     		{
       
   154     			String fileName = traceFileNames.get(traceId);
       
   155     			if (fileName != null)
       
   156     			{
       
   157     				File traceFile = new File(fileName);
       
   158     				if (traceFile.exists()) 
       
   159 						if (traceFile.getName().endsWith(".dat"))  //$NON-NLS-1$
       
   160 							ProfileReader.getInstance().readTraceFile(plugin, traceFile, this,uid);
       
   161     			}
       
   162     		}
       
   163             // assume this load takes 39%
       
   164     		getProgressMonitor().worked((workUnitsForImport * 39 / 100) / numberOfPlugins);
       
   165     		checkCancelledThrowIE();
       
   166             workUnitsLeft -= (workUnitsForImport * 39 / 100) / numberOfPlugins;
       
   167     	}
       
   168 		getProgressMonitor().worked((workUnitsForImport * 60 / 100) - workUnitsLeft);
       
   169 		checkCancelledThrowIE();
       
   170 		workUnitsLeft = (workUnitsForImport * 60 / 100);
       
   171     	
       
   172 		// refine any traces whose addresses can be refined
       
   173 		Iterator<ParsedTraceData> traces = TraceDataRepository.getInstance().getTraceCollectionIter(uid);
       
   174     	if (traces == null) {
       
   175     		throw new InvocationTargetException(new PIExceptionRuntime(Messages.getString("AnalyserDataProcessor.0") + uid + Messages.getString("AnalyserDataProcessor.1")));     //$NON-NLS-1$ //$NON-NLS-2$
       
   176     	}
       
   177     	while (traces.hasNext())
       
   178     	{
       
   179     		ParsedTraceData trace = (ParsedTraceData)traces.next();
       
   180     		// for those trace data items that can be refined
       
   181     		if (trace.traceData instanceof RefinableTrace)
       
   182     		{
       
   183     			Iterator<ParsedTraceData> traces2 = TraceDataRepository.getInstance().getTraceCollectionIter(uid);
       
   184     		
       
   185     			while (traces2.hasNext())
       
   186     			{
       
   187     				ParsedTraceData trace2 = traces2.next();
       
   188 
       
   189     				// refine with other resolvers but not with own (which has been used already)
       
   190     				if (!trace2.equals(trace) && trace2.functionResolvers != null)
       
   191     				{
       
   192     					for (int i = 0; i < trace2.functionResolvers.length; i++)
       
   193     					{
       
   194     						FunctionResolver fr = trace2.functionResolvers[i];
       
   195     						System.out.println(Messages.getString("AnalyserDataProcessor.2") + trace.traceData.getClass().getName() + Messages.getString("AnalyserDataProcessor.3") + fr.getResolverString());     //$NON-NLS-1$ //$NON-NLS-2$
       
   196 
       
   197     						((RefinableTrace)trace.traceData).refineTrace(fr);
       
   198     					}
       
   199     				}
       
   200     				checkCancelledThrowIE();
       
   201     			}
       
   202     			
       
   203     			// after all refinement is done, do any final touches to the samples
       
   204     			((RefinableTrace)trace.traceData).finalizeTrace();
       
   205     		}
       
   206     		getProgressMonitor().worked(workUnitsLeft / 2);
       
   207     		checkCancelledThrowIE();
       
   208     		workUnitsLeft -= workUnitsLeft / 2;
       
   209     	}
       
   210     	// Should move resolver out of trace, PI only need resolver in import phase, trace is more of a
       
   211     	// core data in NPI file; before that, we would just strip all resolvers here
       
   212     	Iterator<ParsedTraceData> tracesItr = TraceDataRepository.getInstance().getTraceCollectionIter(uid);
       
   213     	while (tracesItr.hasNext()) {
       
   214     		ParsedTraceData ptd = tracesItr.next();
       
   215     		ptd.functionResolvers = null;
       
   216     	}
       
   217     	System.gc();
       
   218 	}
       
   219 	
       
   220 	private void loadExistingAnalysis(final Composite parent, final String analysisFilename, final String displayName, final int uid) throws InvocationTargetException, InterruptedException {
       
   221 		assertThrowITE(NpiInstanceRepository.getInstance().activeUid() == uid, Messages.getString("AnalyserDataProcessor.4"));   //$NON-NLS-1$
       
   222 		
       
   223 		// do the loading part with indicator in non-UI thread
       
   224 		final IProgressMonitor pm = getProgressMonitor();
       
   225 		pm.worked(1);
       
   226 		class LoadRunnable implements Runnable {
       
   227 			IOException myIOE = null;
       
   228 			InterruptedException myIE  =null;
       
   229 			
       
   230 			public void handleException () throws InvocationTargetException, InterruptedException {
       
   231 				if (myIOE != null) {
       
   232 					String reason = Messages.getString("AnalyserDataProcessor.12") + analysisFilename; //$NON-NLS-1$
       
   233 					if (myIOE.getMessage() != null) {
       
   234 						reason += " " + myIOE.getMessage(); //$NON-NLS-1$
       
   235 					}
       
   236 					assertThrowITE(myIOE, reason);
       
   237 				}
       
   238 				if (myIE != null) {
       
   239 					throw myIE;
       
   240 				}
       
   241 			}
       
   242 			
       
   243 			public void run() {
       
   244 				try {
       
   245 					ProfileReader.getInstance().loadAnalysisFile(analysisFilename, displayName, pm, uid);
       
   246 				} catch (IOException e) {
       
   247 					myIOE = e;
       
   248 				} catch (InterruptedException e) {
       
   249 					myIE = e;
       
   250 				}	
       
   251 			}
       
   252 		}
       
   253 		LoadRunnable loadRunnable = new LoadRunnable();
       
   254 		new Thread(loadRunnable).run();
       
   255 		loadRunnable.handleException();
       
   256 		checkCancelledThrowIE();
       
   257 		
       
   258 		processTraceDrawAndResize(parent, false);
       
   259 	}
       
   260 	
       
   261 	// called by createPage() of PIPageEditor
       
   262 	public void openNpiForPIPageEditor(final URI analysisFileURI, final Composite parent, final int uid) {
       
   263 		boolean isImport = analyserDataProcessorState == STATE_IMPORTING;
       
   264 		final String displayName = new java.io.File(analysisFileURI).getName();
       
   265 		
       
   266 		if (isImport && getProgressMonitor() != null) {
       
   267 			//import is already wrapped in runnable, and we should have progressmonitor
       
   268 			getProgressMonitor().setTaskName(Messages.getString("AnalyserDataProcessor.5") + displayName);   //$NON-NLS-1$
       
   269 			try {
       
   270 				analyserDataProcessorState = STATE_OPENING;
       
   271 				// by saying isImport true, we assume trace is set up proper in repository
       
   272 				processTraceDrawAndResize(parent, true);
       
   273 				analyserDataProcessorState = STATE_OK;
       
   274 				if (false)
       
   275 				internalOpenNPI (analysisFileURI, parent, uid);
       
   276 			} catch (InvocationTargetException e) {
       
   277 				analyserDataProcessorState = STATE_INVALID;
       
   278 				String error = Messages.getString("AnalyserDataProcessor.6") + e.getTargetException().getMessage() + Messages.getString("AnalyserDataProcessor.7");   //$NON-NLS-1$ //$NON-NLS-2$
       
   279 				if (e.getTargetException().getStackTrace() != null) {
       
   280 					StringWriter sw = new StringWriter ();
       
   281 					PrintWriter pw = new PrintWriter(sw);
       
   282 					e.getTargetException().printStackTrace(pw);
       
   283 					error += sw.toString() + "\n"; //$NON-NLS-1$
       
   284 				}
       
   285 				GeneralMessages.showErrorMessage(error);
       
   286 			} catch (InterruptedException e) {
       
   287 				String error = Messages.getString("AnalyserDataProcessor.8") + e.getMessage() + Messages.getString("AnalyserDataProcessor.9");   //$NON-NLS-1$ //$NON-NLS-2$
       
   288 				analyserDataProcessorState = STATE_CANCELED;
       
   289 			} catch (Exception e) {
       
   290 				analyserDataProcessorState = STATE_INVALID;
       
   291 				String error = Messages.getString("AnalyserDataProcessor.6") + e.getMessage() + Messages.getString("AnalyserDataProcessor.7");   //$NON-NLS-1$ //$NON-NLS-2$
       
   292 				if (e.getStackTrace() != null) {
       
   293 					StringWriter sw = new StringWriter ();
       
   294 					PrintWriter pw = new PrintWriter(sw);
       
   295 					e.printStackTrace(pw);
       
   296 					error += sw.toString() + "\n"; //$NON-NLS-1$
       
   297 				}
       
   298 				GeneralMessages.showErrorMessage(error);
       
   299 			}
       
   300 		} else {
       
   301 			setUp();
       
   302 			//open need to be wrapped in runnable, and we should set progressmonitor
       
   303 			IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
       
   304 			IRunnableWithProgress runnable= new IRunnableWithProgress() {
       
   305 
       
   306 				public void run(IProgressMonitor progressMonitor)
       
   307 				throws InvocationTargetException, InterruptedException {
       
   308 					setProgressMonitor(progressMonitor);
       
   309 					progressMonitor.beginTask(Messages.getString("AnalyserDataProcessor.10") + displayName, AnalyserDataProcessor.TOTAL_PROGRESS_COUNT * 20 / 100); //$NON-NLS-1$
       
   310 					internalOpenNPI (analysisFileURI, parent, uid);
       
   311 				}
       
   312 
       
   313 			};
       
   314 			
       
   315 			try {
       
   316 				progressService.busyCursorWhile(runnable);
       
   317 			} catch (InvocationTargetException e) {
       
   318 				analyserDataProcessorState = STATE_INVALID;
       
   319 			} catch (InterruptedException e) {
       
   320 				analyserDataProcessorState = STATE_CANCELED;
       
   321 			}
       
   322 		}
       
   323 		
       
   324 		getProgressMonitor().done();
       
   325 	}
       
   326 	
       
   327 	private void internalOpenNPI(final URI analysisFileURI, final Composite parent, final int uid) throws InvocationTargetException, InterruptedException {
       
   328 	
       
   329 		analyserDataProcessorState = STATE_OPENING;
       
   330 		
       
   331 		if (analysisFileURI == null) {
       
   332 			assertThrowITE(false, Messages.getString("AnalyserDataProcessor.11")); //$NON-NLS-1$
       
   333 			return;
       
   334 		}
       
   335 		
       
   336 		String filePath = null;
       
   337 		String displayName = null;
       
   338 		
       
   339 		filePath = analysisFileURI.getPath();
       
   340 		displayName = new java.io.File(analysisFileURI).getName();
       
   341 		
       
   342 		loadExistingAnalysis(parent, filePath, displayName, uid);
       
   343 		analyserDataProcessorState = STATE_OK;
       
   344 
       
   345 	}
       
   346 		
       
   347 	public void importSaveAndOpen(final IFile analysisFile, boolean pollTillNpiSaved) {
       
   348 		analyserDataProcessorState = STATE_IMPORTING;
       
   349 		setProgressMonitor(null);
       
   350 		
       
   351 		final int uid = NpiInstanceRepository.getInstance().register(null);
       
   352 
       
   353 		setUp();
       
   354 		IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
       
   355 		IRunnableWithProgress runnableImportAndSave = new IRunnableWithProgress() {
       
   356 
       
   357 			public void run(IProgressMonitor progressMonitor)
       
   358 					throws InvocationTargetException, InterruptedException {
       
   359 				setProgressMonitor(progressMonitor);
       
   360 				progressMonitor.beginTask(Messages.getString("AnalyserDataProcessor.17") + analysisFile.getName(), TOTAL_PROGRESS_COUNT);   //$NON-NLS-1$
       
   361 				// open a profile data file that should contain at least thread/address information
       
   362 
       
   363 				// import new .dat
       
   364 				assertThrowITE(SampleImporter.getInstance().validate(), Messages.getString("AnalyserDataProcessor.18"));	  //$NON-NLS-1$
       
   365 				
       
   366 				// invoke analysis-specific plugin instances
       
   367 				PluginInitialiser.invokePluginInstances(uid, "com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace"); //$NON-NLS-1$
       
   368 
       
   369 				StreamFileParser stp;
       
   370 				try {
       
   371 					stp = new StreamFileParser(new File(SampleImporter.getInstance().getDatFileName()));
       
   372 					Hashtable<Integer,String> traceFileNames = new Hashtable<Integer,String>();
       
   373 					ArrayList<File> tracesForCleanUp = new ArrayList<File>();
       
   374 
       
   375 					// loop through all the plugins associated with traces and note their trace IDs names
       
   376 					Enumeration<AbstractPiPlugin> enumer = PluginInitialiser.getPluginInstances(uid, "com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace"); //$NON-NLS-1$
       
   377 					while (enumer.hasMoreElements())
       
   378 					{
       
   379 						File tempFile;
       
   380 						ITrace plugin = (ITrace)enumer.nextElement();
       
   381 						int traceId = plugin.getTraceId();
       
   382 						if (traceId != -1)
       
   383 						{
       
   384 							try {
       
   385 								tempFile = stp.getTempFileForTraceType(traceId);
       
   386 								if (tempFile != null)
       
   387 								{
       
   388 									tempFile.deleteOnExit();
       
   389 									traceFileNames.put(traceId, tempFile.getAbsolutePath());
       
   390 									tracesForCleanUp.add(tempFile);
       
   391 								}
       
   392 
       
   393 							} catch (IOException e) {
       
   394 								throw new InvocationTargetException(e, Messages.getString("AnalyserDataProcessor.25")); //$NON-NLS-1$
       
   395 							}
       
   396 						}
       
   397 					}
       
   398 					
       
   399 					// import a new analysis
       
   400 					importNewAnalysis(traceFileNames, uid);
       
   401 
       
   402 					// clean up temp file for each trace
       
   403 					for (File traceFile : tracesForCleanUp) {
       
   404 						traceFile.delete();
       
   405 					}
       
   406 				} catch (IOException e) {
       
   407 					throw new InvocationTargetException(e, Messages.getString("AnalyserDataProcessor.26") + SampleImporter.getInstance().getDatFileName()); //$NON-NLS-1$
       
   408 				}
       
   409 
       
   410 				if (progressMonitor.isCanceled()) {
       
   411 					throw new InterruptedException(Messages.getString("AnalyserDataProcessor.19"));   //$NON-NLS-1$
       
   412 				}
       
   413 
       
   414 				// give the .NPI file null contents
       
   415 				byte[] b = new byte[0];
       
   416 				try {
       
   417 					analysisFile.create(new ByteArrayInputStream(b), true, null);
       
   418 					// make sure we can open an input stream to the trace file
       
   419 					analysisFile.getContents();
       
   420 				} catch (CoreException e) {
       
   421 					throw new InvocationTargetException(e, Messages.getString("AnalyserDataProcessor.14") + analysisFile.getName()); //$NON-NLS-1$
       
   422 				}
       
   423 				
       
   424 				// extract additional info from importer
       
   425 				int numberOfTraces = 0;
       
   426 				Iterator<ParsedTraceData> enuTraces = TraceDataRepository.getInstance().getTraceCollectionIter(uid);
       
   427 				AnalysisInfoHandler handler = NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler();
       
   428 
       
   429 				// for all traces exist in .dat set up their additional info
       
   430 			    while (enuTraces.hasNext()) {
       
   431 			    	Object object = enuTraces.next();
       
   432 
       
   433 			    	numberOfTraces++;
       
   434 			    	
       
   435 			    	if (object instanceof ParsedTraceData) {
       
   436 			    		ParsedTraceData parsedTraceData = (ParsedTraceData) object;
       
   437 			    		if (parsedTraceData.traceData != null) {
       
   438 				    		Class traceClass = parsedTraceData.traceData.getClass();
       
   439 
       
   440 							// this code is clumsy because the plugin, not the trace, has the trace ID info
       
   441 				    		Enumeration<AbstractPiPlugin> enuPlugins = PluginInitialiser.getPluginInstances(uid, "com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace"); //$NON-NLS-1$
       
   442 							while (enuPlugins.hasMoreElements())
       
   443 							{
       
   444 								ITrace plugin = (ITrace)enuPlugins.nextElement();
       
   445 								// only do when trace exist in .data
       
   446 								if (traceClass == plugin.getTraceClass()) {
       
   447 							    	if (plugin instanceof IProvideTraceAdditionalInfo) {
       
   448 										((IProvideTraceAdditionalInfo)plugin).setupInfoHandler(handler);						    		
       
   449 							    	}
       
   450 								}
       
   451 							}			
       
   452 			    		}
       
   453 			    	}
       
   454 			    }
       
   455 				
       
   456 				// refresh so project know the update done by Java(non-Eclipse API)
       
   457 				try {
       
   458 					analysisFile.refreshLocal(0, null);
       
   459 				} catch (CoreException e) {
       
   460 					throw new InvocationTargetException(e, Messages.getString("AnalyserDataProcessor.15") + analysisFile.getName()); //$NON-NLS-1$
       
   461 				}		
       
   462 			}
       
   463 		};
       
   464 		
       
   465 		IRunnableWithProgress runnableOpen = new IRunnableWithProgress() {
       
   466 
       
   467 			public void run(IProgressMonitor arg0)
       
   468 					throws InvocationTargetException, InterruptedException {
       
   469 				// open the saved file
       
   470 				if (analysisFile.exists() && AnalyserDataProcessor.getInstance().getState() == STATE_IMPORTING ) {
       
   471 						// open the file itself
       
   472 					
       
   473 					// need to open in UI context
       
   474 					Display.getDefault().syncExec(new Runnable() {
       
   475 
       
   476 						public void run() {
       
   477 							IEditorPart editor = null;
       
   478 							try {
       
   479 								editor = IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() , analysisFile, true);
       
   480 							} catch (PartInitException e) {
       
   481 								try {
       
   482 									assertThrowITE(e, analysisFile.getName() + Messages.getString("AnalyserDataProcessor.24")); //$NON-NLS-1$
       
   483 								} catch (InvocationTargetException e1) {
       
   484 									//already set data structure proper, do nothing
       
   485 								}
       
   486 							}
       
   487 							if (AnalyserDataProcessor.getInstance().getState() == STATE_CANCELED) {
       
   488 								// close the editor file view
       
   489 								editor.getSite().getPage().closeEditor(editor, false);
       
   490 							} else if (AnalyserDataProcessor.getInstance().getState() != STATE_OK ) {
       
   491 								// close the editor file view
       
   492 								editor.getSite().getPage().closeEditor(editor, false);
       
   493 							}							
       
   494 						}
       
   495 					});
       
   496 				}
       
   497 			}
       
   498 			
       
   499 		};
       
   500 		
       
   501 		try {
       
   502 			progressService.busyCursorWhile(runnableImportAndSave);
       
   503 		
       
   504 			final WorkspaceJob saveNpi = new WorkspaceJob (Messages.getString("AnalyserDataProcessor.savingImportedFile")) { //$NON-NLS-1$
       
   505 
       
   506 				public IStatus runInWorkspace(IProgressMonitor monitor)
       
   507 						throws CoreException {
       
   508 					try {
       
   509 						ProfileReader.getInstance().writeAnalysisFile(analysisFile.getLocation().toString(), monitor, uid);
       
   510 					} catch (InvocationTargetException e) {
       
   511 						return new Status(IStatus.ERROR, "com.nokia.carbide.cpp.pi", Messages.getString("AnalyserDataProcessor.invocationTargetException"), e); //$NON-NLS-1$ //$NON-NLS-2$
       
   512 					} catch (InterruptedException e) {
       
   513 						return new Status(IStatus.CANCEL, "com.nokia.carbide.cpp.pi", Messages.getString("AnalyserDataProcessor.interruptedException"), e); //$NON-NLS-1$ //$NON-NLS-2$
       
   514 					}
       
   515 					return new Status(IStatus.OK, "com.nokia.carbide.cpp.pi", Messages.getString("AnalyserDataProcessor.ok"), null); //$NON-NLS-1$ //$NON-NLS-2$
       
   516 				}
       
   517 				
       
   518 			};
       
   519 		
       
   520 			progressService.busyCursorWhile(runnableOpen);
       
   521 
       
   522 			saveNpi.setPriority(Job.DECORATE);
       
   523 			saveNpi.addJobChangeListener(new IJobChangeListener () {
       
   524 				
       
   525 				public void aboutToRun(IJobChangeEvent event) {
       
   526 				}
       
   527 
       
   528 				public void awake(IJobChangeEvent event) {
       
   529 				}
       
   530 
       
   531 				public void done(IJobChangeEvent event) {
       
   532 					if (saveNpi.getResult().getSeverity()  != IStatus.OK) {
       
   533 						HandleRunnableException (saveNpi.getResult().getException(), uid, analysisFile);
       
   534 					}
       
   535 				}
       
   536 
       
   537 				public void running(IJobChangeEvent event) {
       
   538 				}
       
   539 
       
   540 				public void scheduled(IJobChangeEvent event) {
       
   541 				}
       
   542 
       
   543 				public void sleeping(IJobChangeEvent event) {
       
   544 				}
       
   545 				
       
   546 			});
       
   547 			
       
   548 			saveNpi.schedule();
       
   549 			
       
   550 			if (pollTillNpiSaved) {
       
   551 				while (saveNpi.getState() != Job.NONE) {
       
   552 					// until it's done
       
   553 				}
       
   554 			}
       
   555 			
       
   556 		} catch (InvocationTargetException e) {
       
   557 			HandleRunnableException(e, uid, analysisFile);
       
   558 		} catch (InterruptedException e) {
       
   559 			HandleRunnableException(e, uid, analysisFile);
       
   560 		}							
       
   561 	}
       
   562 	
       
   563 	private void HandleRunnableException(Throwable throwable, final int uid, IFile analysisFile) {
       
   564 		NpiInstanceRepository.getInstance().unregister(uid);
       
   565 		if (throwable instanceof InvocationTargetException) {
       
   566 			String error = Messages.getString("AnalyserDataProcessor.20"); //$NON-NLS-1$
       
   567 			if (throwable.getMessage() != null) {
       
   568 				error += throwable.getMessage() + "\n"; //$NON-NLS-1$
       
   569 			}
       
   570 			error += Messages.getString("AnalyserDataProcessor.21");   //$NON-NLS-1$ //$NON-NLS-2$
       
   571 			if (((InvocationTargetException)throwable).getTargetException().getStackTrace() != null) {
       
   572 				StringWriter sw = new StringWriter ();
       
   573 				PrintWriter pw = new PrintWriter(sw);
       
   574 				((InvocationTargetException)throwable).printStackTrace(pw);
       
   575 				error += sw.toString() + "\n"; //$NON-NLS-1$
       
   576 			}
       
   577 			GeneralMessages.showErrorMessage(error);
       
   578 			analyserDataProcessorState = STATE_INVALID;
       
   579 		} else if (throwable instanceof InterruptedException) {
       
   580 			GeneralMessages.showErrorMessage(Messages.getString("AnalyserDataProcessor.22"));  //$NON-NLS-1$
       
   581 			analyserDataProcessorState = STATE_CANCELED;
       
   582 		} else {
       
   583 			String error = Messages.getString("AnalyserDataProcessor.20"); //$NON-NLS-1$
       
   584 			if (throwable.getStackTrace() != null) {
       
   585 				StringWriter sw = new StringWriter ();
       
   586 				PrintWriter pw = new PrintWriter(sw);
       
   587 				((InvocationTargetException)throwable).printStackTrace(pw);
       
   588 				error += sw.toString() + "\n"; //$NON-NLS-1$
       
   589 			}
       
   590 			GeneralMessages.showErrorMessage(error);
       
   591 			analyserDataProcessorState = STATE_INVALID;		
       
   592 		}
       
   593 		// don't leave any garbage behind if we failed or bailed
       
   594 		if (analysisFile != null && AnalyserDataProcessor.getInstance().getState() != STATE_OK ) {
       
   595 			java.io.File javaFile = new java.io.File(analysisFile.getLocation().toString());
       
   596 			boolean deleted = javaFile.delete();
       
   597 				
       
   598 			if (deleted == false){
       
   599 				try {
       
   600 					analysisFile.delete(true, null);
       
   601 				} catch (CoreException ce) {
       
   602 					ce.printStackTrace();
       
   603 				}
       
   604 			}
       
   605 
       
   606 			try {
       
   607 				// force Eclipse to be aware of the removed file by doing an IFile refresh
       
   608 				analysisFile.refreshLocal(0, null);
       
   609 			} catch (CoreException ce) {
       
   610 				ce.printStackTrace();
       
   611 			}
       
   612 		}	
       
   613 	}
       
   614 	
       
   615 	// standalone for save as
       
   616 	public void saveAnalysis(final String filename, final int uid) throws InvocationTargetException, InterruptedException {
       
   617 		IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
       
   618 		IRunnableWithProgress runnable= new IRunnableWithProgress() {
       
   619 
       
   620 			public void run(IProgressMonitor progressMonitor)
       
   621 					throws InvocationTargetException, InterruptedException {
       
   622 				saveAnalysisInternal(filename, uid);
       
   623 			}
       
   624 			
       
   625 		};
       
   626 		try {
       
   627 			progressService.busyCursorWhile(runnable);
       
   628 		} catch (InvocationTargetException e) {
       
   629 			analyserDataProcessorState = STATE_INVALID;
       
   630 		} catch (InterruptedException e) {
       
   631 			analyserDataProcessorState = STATE_CANCELED;
       
   632 		}
       
   633 	}
       
   634 
       
   635 	// save profiling data to NPI file
       
   636 	private void saveAnalysisInternal(final String filename, final int uid) throws InvocationTargetException, InterruptedException {
       
   637 		ProfileReader.getInstance().writeAnalysisFile(filename, getProgressMonitor(), uid);
       
   638 	}
       
   639 	
       
   640 	private void processVisualizableItem(ITrace plugin)
       
   641 	{
       
   642 		IVisualizable visualizable = (IVisualizable)plugin;
       
   643 		
       
   644 		if (!visualizable.arePagesCreated())
       
   645 		{
       
   646 			// create any editor pages
       
   647 			for (int i = 0; i < visualizable.getCreatePageCount(); i++)
       
   648 			{
       
   649 				int index = visualizable.getCreatePageIndex(i);
       
   650 				ArrayList<ProfileVisualiser> pages = NpiInstanceRepository.getInstance().activeUidGetProfilePages();
       
   651 				if (pages != null) {
       
   652 					// if we don't care what the page index is, or the index is too big, add it to the end
       
   653 					if ((index == PIPageEditor.NEXT_AVAILABLE_PAGE) || (index > pages.size())) {
       
   654 						index = pages.size();
       
   655 						
       
   656 						// let the plugin know what index we assigned
       
   657 						visualizable.setPageIndex(i, index);
       
   658 					}
       
   659 					
       
   660 					ProfileVisualiser pV = visualizable.createPage(index);
       
   661 					
       
   662 					// add the page to the editor
       
   663 					if (pV != null)
       
   664 						pages.add(index, pV);					
       
   665 				}
       
   666 			}
       
   667 		}
       
   668 		
       
   669 		int uid = NpiInstanceRepository.getInstance().activeUid();
       
   670 		
       
   671 		// determine how many graphs to draw (several may get added to the same page)
       
   672 		for (int i = 0; i < visualizable.getGraphCount(); i++)
       
   673 		{
       
   674 			GraphDrawRequest gdr   = visualizable.getDrawRequest(i);
       
   675 			GenericTraceGraph gtg  = visualizable.getTraceGraph(i);
       
   676 			String title           = visualizable.getGraphTitle(i);
       
   677 			int	pageNumber         = visualizable.getPageNumber(i);
       
   678 			
       
   679 			ProfileVisualiser page = NpiInstanceRepository.getInstance().getProfilePage(uid, pageNumber);
       
   680 
       
   681 			if (gtg != null)
       
   682 			{
       
   683 				page.getTopComposite().addGraphComponent(gtg, title, visualizable.getClass(), gdr);
       
   684 			}
       
   685 
       
   686 			Integer lastSample = visualizable.getLastSample(i);
       
   687 			if (lastSample != null)
       
   688 			{
       
   689 				page.setLastSampleX(lastSample.intValue());
       
   690 			}
       
   691 		}
       
   692 	}
       
   693 	
       
   694 	private void processTraceDrawAndResize(final Composite parent, boolean isImport) {
       
   695 		// if it is import, everything is already read in place, otherwise
       
   696 		// setup those from object file read
       
   697 		if (!isImport) {
       
   698 			ProfileReader.getInstance().processDataReadFromNpiFile(this);
       
   699 		}
       
   700 		
       
   701 		int uid = NpiInstanceRepository.getInstance().activeUid();
       
   702 		
       
   703 		// initialize trace and do visual
       
   704 		ArrayList<AbstractPiPlugin> plugins = NpiInstanceRepository.getInstance().getPlugins(uid);
       
   705 		for (final AbstractPiPlugin plugin : plugins) {
       
   706 			if (plugin instanceof ITrace) {
       
   707 				final ParsedTraceData parsedData = TraceDataRepository.getInstance().getTrace(uid, ((ITrace)plugin).getTraceClass());
       
   708 				if (parsedData != null) {
       
   709 					final ITrace pluginTrace = (ITrace)plugin;
       
   710 					pluginTrace.initialiseTrace(parsedData.traceData);
       
   711 	    			// do the graphic painting with indicator, SWT require it to be in UI thread
       
   712 					if (plugin instanceof IVisualizable) {
       
   713 						Display.getDefault().syncExec( new Runnable() {
       
   714 							public void run() {
       
   715 								processVisualizableItem(pluginTrace);
       
   716 							}
       
   717 		    			});	
       
   718 					}
       
   719 				}
       
   720 			}
       
   721 		}
       
   722 		
       
   723 		if (!isImport) {
       
   724 			ProfileReader.getInstance().setAddtionalDataForRecordable();
       
   725 		}
       
   726 		
       
   727 		ProfileReader.getInstance().setTraceMenus(NpiInstanceRepository.getInstance().getPlugins(uid), uid);
       
   728 		// do the graphic painting with indicator, SWT require it to be in UI thread
       
   729 		Display.getDefault().syncExec( new Runnable() {
       
   730 			public void run() {
       
   731 				parent.addPaintListener( new PaintListener () {
       
   732 		  			
       
   733 					public void paintControl(PaintEvent arg0) {
       
   734 
       
   735 						if(parent.getBounds().width > 0) {
       
   736 							ArrayList<ProfileVisualiser> pages = NpiInstanceRepository.getInstance().activeUidGetProfilePages();
       
   737 							
       
   738 							// make sure we are called after the pages have been created?
       
   739 							if (pages.size() > 0) {
       
   740 								for (final ProfileVisualiser page : pages) {
       
   741 									// NOTE: This assumes that the first profile page has a graph
       
   742 						        	final PICompositePanel visibleComposite = page.getTopComposite();
       
   743 						        	visibleComposite.performZoomToGraph(visibleComposite, parent.getBounds().width);
       
   744 						        	
       
   745 						        	//TODO uncomment when performance issues relating to gfc are solved
       
   746 						        	//Select whole graph
       
   747 						        	//visibleComposite.selectWholeGraph();
       
   748 								}
       
   749 			
       
   750 								// scale to whole trace only once
       
   751 					        	parent.removePaintListener(this);
       
   752 							}
       
   753 						}
       
   754 					}
       
   755 		  		});
       
   756 			}
       
   757 		});
       
   758 	}
       
   759 	
       
   760 	// This is for test automation, removing time stamps, so we can diff .npi
       
   761 	public void importForStrippingTimeStamp(final Composite parent) {
       
   762 		if (SampleImporter.getInstance().isStrippingTimeStamp()) {
       
   763 			// had to do this monkey business for pi validation because
       
   764 			// serialization is an untestable format
       
   765 			// read file
       
   766 			final SampleImporter sampleImporter = SampleImporter.getInstance();
       
   767 
       
   768 			IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
       
   769 			IRunnableWithProgress runnable= new IRunnableWithProgress() {
       
   770 
       
   771 				public void run(IProgressMonitor progressMonitor)
       
   772 						throws InvocationTargetException,
       
   773 						InterruptedException {
       
   774 					setProgressMonitor(progressMonitor);
       
   775 					progressMonitor.beginTask(Messages.getString("AnalyserDataProcessor.23"), 100);   //$NON-NLS-1$
       
   776 					try {
       
   777 						int uid = NpiInstanceRepository.getInstance().activeUid();
       
   778 						loadExistingAnalysis(parent, sampleImporter.getDatFileName(), sampleImporter.getDatFileName(), uid);
       
   779 						// time stample differs for every save, take it out
       
   780 						AnalysisInfoHandler infoHandler = NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler();
       
   781 						if (infoHandler != null) {
       
   782 							infoHandler.eraseTimeStamp();
       
   783 						}
       
   784 						// write file
       
   785 						saveAnalysisInternal(sampleImporter.getPiFileName(), uid);
       
   786 					} catch (Exception e) {
       
   787 						e.printStackTrace();
       
   788 					}
       
   789 				}
       
   790 			};
       
   791 			try {
       
   792 				progressService.busyCursorWhile(runnable);
       
   793 			} catch (InvocationTargetException e) {
       
   794 				analyserDataProcessorState = STATE_INVALID;
       
   795 				e.printStackTrace();
       
   796 			} catch (InterruptedException e) {
       
   797 				analyserDataProcessorState = STATE_CANCELED;
       
   798 				e.printStackTrace();
       
   799 			}
       
   800 			setProgressMonitor(null);
       
   801 		}
       
   802 	}
       
   803 	
       
   804 	// catch all for any exception, so we can print an error stack trace page later
       
   805 	private void assertThrowITE(boolean cond, String message) throws InvocationTargetException {
       
   806 		if (!cond) {
       
   807 			PIExceptionRuntime pire = new PIExceptionRuntime(message);	//$NON-NLS-1$
       
   808 			InvocationTargetException ite = new InvocationTargetException(pire);
       
   809 			lastException = ite;
       
   810 			analyserDataProcessorState = STATE_INVALID;
       
   811 			if (getProgressMonitor() != null) {
       
   812 				getProgressMonitor().done();
       
   813 			}
       
   814 			GeneralMessages.showErrorMessage(message);
       
   815 			throw ite;
       
   816 		}
       
   817 	}
       
   818 	
       
   819 	private void assertThrowITE(Exception e, String message) throws InvocationTargetException {
       
   820 		InvocationTargetException ite;
       
   821 		if (message != null) {
       
   822 			ite = new InvocationTargetException(e, message);
       
   823 		} else {
       
   824 			ite = new InvocationTargetException(e);
       
   825 		}
       
   826 		lastException = ite;
       
   827 		analyserDataProcessorState = STATE_INVALID;
       
   828 		if (getProgressMonitor() != null) {
       
   829 			getProgressMonitor().done();
       
   830 		}
       
   831 		GeneralMessages.showErrorMessage(message);
       
   832 		throw ite;
       
   833 
       
   834 	}
       
   835 
       
   836 	
       
   837 	// General handling for Cancel operation
       
   838 	public void checkCancelledThrowIE() throws InterruptedException {
       
   839 		if (getProgressMonitor() != null && getProgressMonitor().isCanceled()) {
       
   840 			InterruptedException ie = new InterruptedException();
       
   841 			analyserDataProcessorState = STATE_CANCELED;
       
   842 			throw ie;
       
   843 		}
       
   844 	}
       
   845 	
       
   846 	private void setUp() {
       
   847 		if (getProgressMonitor() != null) {
       
   848 			getProgressMonitor().done();
       
   849 			setProgressMonitor(null);
       
   850 		}
       
   851 		lastException = null;
       
   852 		analyserDataProcessorState = STATE_OK;
       
   853 	}
       
   854 }