|
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 } |