30c5bc148f1e532c9d4acc974c388183133c2844
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / views / callstack / CallStackView.java
1 /*******************************************************************************
2 * Copyright (c) 2013, 2014 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Patrick Tasse - Initial API and implementation
11 * Bernd Hufmann - Updated signal handling
12 *******************************************************************************/
13
14 package org.eclipse.linuxtools.tmf.ui.views.callstack;
15
16 import java.io.File;
17 import java.util.ArrayList;
18 import java.util.HashMap;
19 import java.util.Iterator;
20 import java.util.List;
21 import java.util.Map;
22
23 import org.eclipse.core.runtime.IProgressMonitor;
24 import org.eclipse.core.runtime.IStatus;
25 import org.eclipse.core.runtime.NullProgressMonitor;
26 import org.eclipse.core.runtime.Status;
27 import org.eclipse.core.runtime.jobs.Job;
28 import org.eclipse.jdt.annotation.Nullable;
29 import org.eclipse.jface.action.Action;
30 import org.eclipse.jface.action.IAction;
31 import org.eclipse.jface.action.IStatusLineManager;
32 import org.eclipse.jface.action.IToolBarManager;
33 import org.eclipse.jface.action.Separator;
34 import org.eclipse.jface.util.IPropertyChangeListener;
35 import org.eclipse.jface.util.PropertyChangeEvent;
36 import org.eclipse.jface.viewers.DoubleClickEvent;
37 import org.eclipse.jface.viewers.IDoubleClickListener;
38 import org.eclipse.jface.viewers.ILabelProviderListener;
39 import org.eclipse.jface.viewers.ISelection;
40 import org.eclipse.jface.viewers.IStructuredSelection;
41 import org.eclipse.jface.viewers.ITableLabelProvider;
42 import org.eclipse.jface.viewers.ITreeContentProvider;
43 import org.eclipse.jface.viewers.Viewer;
44 import org.eclipse.linuxtools.internal.tmf.ui.Activator;
45 import org.eclipse.linuxtools.internal.tmf.ui.ITmfImageConstants;
46 import org.eclipse.linuxtools.internal.tmf.ui.Messages;
47 import org.eclipse.linuxtools.tmf.core.callstack.CallStackStateProvider;
48 import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
49 import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException;
50 import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
51 import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
52 import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
53 import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
54 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
55 import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
56 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceClosedSignal;
57 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal;
58 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSelectedSignal;
59 import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
60 import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
61 import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue.Type;
62 import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
63 import org.eclipse.linuxtools.tmf.core.timestamp.TmfNanoTimestamp;
64 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
65 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
66 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestampDelta;
67 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
68 import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
69 import org.eclipse.linuxtools.tmf.ui.editors.ITmfTraceEditor;
70 import org.eclipse.linuxtools.tmf.ui.views.TmfView;
71 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;
72 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
73 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphCombo;
74 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;
75 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
76 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphViewer;
77 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;
78 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
79 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.NullTimeEvent;
80 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeEvent;
81 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.TimeGraphControl;
82 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.TimeGraphSelection;
83 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
84 import org.eclipse.swt.SWT;
85 import org.eclipse.swt.events.ControlAdapter;
86 import org.eclipse.swt.events.ControlEvent;
87 import org.eclipse.swt.events.MouseAdapter;
88 import org.eclipse.swt.events.MouseEvent;
89 import org.eclipse.swt.graphics.Image;
90 import org.eclipse.swt.widgets.Composite;
91 import org.eclipse.swt.widgets.Display;
92 import org.eclipse.swt.widgets.FileDialog;
93 import org.eclipse.ui.IActionBars;
94 import org.eclipse.ui.IEditorPart;
95
96 /**
97 * Main implementation for the Call Stack view
98 *
99 * @author Patrick Tasse
100 * @since 2.0
101 */
102 public class CallStackView extends TmfView {
103
104 // ------------------------------------------------------------------------
105 // Constants
106 // ------------------------------------------------------------------------
107
108 /** View ID. */
109 public static final String ID = "org.eclipse.linuxtools.tmf.ui.views.callstack"; //$NON-NLS-1$
110
111 /**
112 * Redraw state enum
113 */
114 private enum State { IDLE, BUSY, PENDING }
115
116 private static final String[] COLUMN_NAMES = new String[] {
117 Messages.CallStackView_FunctionColumn,
118 Messages.CallStackView_DepthColumn,
119 Messages.CallStackView_EntryTimeColumn,
120 Messages.CallStackView_ExitTimeColumn,
121 Messages.CallStackView_DurationColumn
122 };
123
124 private static final int[] COLUMN_WIDTHS = new int[] {
125 200,
126 50,
127 120,
128 120,
129 120
130 };
131
132 // Fraction of a function duration to be added as spacing
133 private static final double SPACING_RATIO = 0.01;
134
135 private static final Image THREAD_IMAGE = Activator.getDefault().getImageFromPath("icons/obj16/thread_obj.gif"); //$NON-NLS-1$
136 private static final Image STACKFRAME_IMAGE = Activator.getDefault().getImageFromPath("icons/obj16/stckframe_obj.gif"); //$NON-NLS-1$
137
138 private static final String IMPORT_MAPPING_ICON_PATH = "icons/etool16/import.gif"; //$NON-NLS-1$
139
140 // ------------------------------------------------------------------------
141 // Fields
142 // ------------------------------------------------------------------------
143
144 // The time graph combo
145 private TimeGraphCombo fTimeGraphCombo;
146
147 // The selected trace
148 private ITmfTrace fTrace;
149
150 // The selected thread map
151 private final Map<ITmfTrace, String> fSelectedThreadMap = new HashMap<>();
152
153 // The time graph entry list
154 private List<ThreadEntry> fEntryList;
155
156 // The trace to entry list hash map
157 private final Map<ITmfTrace, ArrayList<ThreadEntry>> fEntryListMap = new HashMap<>();
158
159 // The trace to build thread hash map
160 private final Map<ITmfTrace, BuildThread> fBuildThreadMap = new HashMap<>();
161
162 /** The map to map function addresses to function names */
163 private Map<String, String> fNameMapping;
164
165 // The start time
166 private long fStartTime;
167
168 // The end time
169 private long fEndTime;
170
171 // The display width
172 private int fDisplayWidth;
173
174 // The next event action
175 private Action fNextEventAction;
176
177 // The previous event action
178 private Action fPrevEventAction;
179
180 // The next item action
181 private Action fNextItemAction;
182
183 // The previous item action
184 private Action fPreviousItemAction;
185
186 /** The action to import a function-name mapping file */
187 private Action fImportMappingAction;
188
189 // The zoom thread
190 private ZoomThread fZoomThread;
191
192 // The redraw state used to prevent unnecessary queuing of display runnables
193 private State fRedrawState = State.IDLE;
194
195 // The redraw synchronization object
196 private final Object fSyncObj = new Object();
197
198 // The saved time sync. signal used when switching off the pinning of a view
199 private TmfTimeSynchSignal fSavedTimeSyncSignal;
200
201 // The saved time range sync. signal used when switching off the pinning of a view
202 private TmfRangeSynchSignal fSavedRangeSyncSignal;
203
204 // ------------------------------------------------------------------------
205 // Classes
206 // ------------------------------------------------------------------------
207
208 private class ThreadEntry implements ITimeGraphEntry {
209 // The start time
210 private final long fTraceStartTime;
211 // The end time
212 private final long fTraceEndTime;
213 // The children of the entry
214 private ArrayList<CallStackEntry> fChildren;
215 // The name of entry
216 private final String fName;
217 // The thread attribute quark
218 private final int fThreadQuark;
219 // The state system from which this entry comes
220 private final ITmfStateSystem fSS;
221
222 public ThreadEntry(ITmfTrace trace, String name, int threadQuark, long startTime, long endTime) {
223 fChildren = new ArrayList<>();
224 fName = name;
225 fTraceStartTime = startTime;
226 fTraceEndTime = endTime;
227 fThreadQuark = threadQuark;
228
229 fSS = getCallStackStateSystem(trace);
230 }
231
232 @Override
233 public ITimeGraphEntry getParent() {
234 return null;
235 }
236
237 @Override
238 public boolean hasChildren() {
239 if (fChildren == null) {
240 ITmfStateSystem ss = getStateSystem();
241 if (ss == null) {
242 return false;
243 }
244 try {
245 int eventStackQuark = ss.getQuarkRelative(fThreadQuark, CallStackStateProvider.CALL_STACK);
246 ITmfStateInterval eventStackInterval = ss.querySingleState(ss.getStartTime(), eventStackQuark);
247 return ! eventStackInterval.getStateValue().isNull() || eventStackInterval.getEndTime() != ss.getCurrentEndTime();
248 } catch (AttributeNotFoundException e) {
249 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
250 } catch (TimeRangeException e) {
251 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
252 } catch (StateSystemDisposedException e) {
253 /* Ignored */
254 }
255 }
256 return fChildren != null && fChildren.size() > 0;
257 }
258
259 @Override
260 public List<CallStackEntry> getChildren() {
261 return fChildren;
262 }
263
264 @Override
265 public String getName() {
266 return fName;
267 }
268
269 @Override
270 public long getStartTime() {
271 return fTraceStartTime;
272 }
273
274 @Override
275 public long getEndTime() {
276 return fTraceEndTime;
277 }
278
279 @Override
280 public boolean hasTimeEvents() {
281 return false;
282 }
283
284 @Override
285 public Iterator<ITimeEvent> getTimeEventsIterator() {
286 return null;
287 }
288
289 @Override
290 public <T extends ITimeEvent> Iterator<T> getTimeEventsIterator(long startTime, long stopTime, long visibleDuration) {
291 return null;
292 }
293
294 public int getThreadQuark() {
295 return fThreadQuark;
296 }
297
298 @Nullable
299 public ITmfStateSystem getStateSystem() {
300 return fSS;
301 }
302
303 public void addChild(CallStackEntry entry) {
304 entry.setParent(this);
305 fChildren.add(entry);
306 }
307 }
308
309 private class TreeContentProvider implements ITreeContentProvider {
310
311 @Override
312 public void dispose() {
313 }
314
315 @Override
316 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
317 }
318
319 @Override
320 public Object[] getElements(Object inputElement) {
321 return (ITimeGraphEntry[]) inputElement;
322 }
323
324 @Override
325 public Object[] getChildren(Object parentElement) {
326 ITimeGraphEntry entry = (ITimeGraphEntry) parentElement;
327 return entry.getChildren().toArray();
328 }
329
330 @Override
331 public Object getParent(Object element) {
332 ITimeGraphEntry entry = (ITimeGraphEntry) element;
333 return entry.getParent();
334 }
335
336 @Override
337 public boolean hasChildren(Object element) {
338 ITimeGraphEntry entry = (ITimeGraphEntry) element;
339 return entry.hasChildren();
340 }
341
342 }
343
344 private class TreeLabelProvider implements ITableLabelProvider {
345
346 @Override
347 public void addListener(ILabelProviderListener listener) {
348 }
349
350 @Override
351 public void dispose() {
352 }
353
354 @Override
355 public boolean isLabelProperty(Object element, String property) {
356 return false;
357 }
358
359 @Override
360 public void removeListener(ILabelProviderListener listener) {
361 }
362
363 @Override
364 public Image getColumnImage(Object element, int columnIndex) {
365 if (columnIndex == 0) {
366 if (element instanceof ThreadEntry) {
367 return THREAD_IMAGE;
368 } else if (element instanceof CallStackEntry) {
369 CallStackEntry entry = (CallStackEntry) element;
370 if (entry.getFunctionName().length() > 0) {
371 return STACKFRAME_IMAGE;
372 }
373 }
374 }
375 return null;
376 }
377
378 @Override
379 public String getColumnText(Object element, int columnIndex) {
380 if (element instanceof ThreadEntry) {
381 if (columnIndex == 0) {
382 return ((ThreadEntry) element).getName();
383 }
384 } else if (element instanceof CallStackEntry) {
385 CallStackEntry entry = (CallStackEntry) element;
386 if (columnIndex == 0) {
387 return entry.getFunctionName();
388 } else if (columnIndex == 1 && entry.getFunctionName().length() > 0) {
389 int depth = entry.getStackLevel();
390 return Integer.toString(depth);
391 } else if (columnIndex == 2 && entry.getFunctionName().length() > 0) {
392 ITmfTimestamp ts = new TmfTimestamp(entry.getStartTime(), ITmfTimestamp.NANOSECOND_SCALE);
393 return ts.toString();
394 } else if (columnIndex == 3 && entry.getFunctionName().length() > 0) {
395 ITmfTimestamp ts = new TmfTimestamp(entry.getEndTime(), ITmfTimestamp.NANOSECOND_SCALE);
396 return ts.toString();
397 } else if (columnIndex == 4 && entry.getFunctionName().length() > 0) {
398 ITmfTimestamp ts = new TmfTimestampDelta(entry.getEndTime() - entry.getStartTime(), ITmfTimestamp.NANOSECOND_SCALE);
399 return ts.toString();
400 }
401 }
402 return ""; //$NON-NLS-1$
403 }
404
405 }
406
407 private class BuildThread extends Thread {
408 private final ITmfTrace fBuildTrace;
409 private final IProgressMonitor fMonitor;
410
411 public BuildThread(ITmfTrace trace) {
412 super("CallStackView build"); //$NON-NLS-1$
413 fBuildTrace = trace;
414 fMonitor = new NullProgressMonitor();
415 }
416
417 @Override
418 public void run() {
419 buildThreadList(fBuildTrace, fMonitor);
420 synchronized (fBuildThreadMap) {
421 fBuildThreadMap.remove(this);
422 }
423 }
424
425 public void cancel() {
426 fMonitor.setCanceled(true);
427 }
428 }
429
430 private class ZoomThread extends Thread {
431 private final List<ThreadEntry> fZoomEntryList;
432 private final long fZoomStartTime;
433 private final long fZoomEndTime;
434 private final IProgressMonitor fMonitor;
435
436 public ZoomThread(List<ThreadEntry> entryList, long startTime, long endTime) {
437 super("ResourcesView zoom"); //$NON-NLS-1$
438 fZoomEntryList = entryList;
439 fZoomStartTime = startTime;
440 fZoomEndTime = endTime;
441 fMonitor = new NullProgressMonitor();
442 }
443
444 @Override
445 public void run() {
446 if (fZoomEntryList == null) {
447 return;
448 }
449 long resolution = Math.max(1, (fZoomEndTime - fZoomStartTime) / fDisplayWidth);
450 for (ThreadEntry threadEntry : fZoomEntryList) {
451 ITmfStateSystem ss = threadEntry.getStateSystem();
452 if (ss == null) {
453 continue;
454 }
455 ss.waitUntilBuilt();
456 if (ss.isCancelled()) {
457 continue;
458 }
459 for (ITimeGraphEntry child : threadEntry.getChildren()) {
460 if (fMonitor.isCanceled()) {
461 break;
462 }
463 CallStackEntry entry = (CallStackEntry) child;
464 if (fZoomStartTime <= fStartTime && fZoomEndTime >= fEndTime) {
465 entry.setZoomedEventList(null);
466 } else {
467 List<ITimeEvent> zoomedEventList = getEventList(entry, fZoomStartTime, fZoomEndTime, resolution, fMonitor);
468 if (zoomedEventList != null) {
469 entry.setZoomedEventList(zoomedEventList);
470 }
471 }
472 redraw();
473 }
474 }
475 }
476
477 public void cancel() {
478 fMonitor.setCanceled(true);
479 }
480 }
481
482 // ------------------------------------------------------------------------
483 // Constructors
484 // ------------------------------------------------------------------------
485
486 /**
487 * Default constructor
488 */
489 public CallStackView() {
490 super(ID);
491 fDisplayWidth = Display.getDefault().getBounds().width;
492 }
493
494 // ------------------------------------------------------------------------
495 // ViewPart
496 // ------------------------------------------------------------------------
497
498 @Override
499 public void createPartControl(Composite parent) {
500 fTimeGraphCombo = new TimeGraphCombo(parent, SWT.NONE);
501
502 fTimeGraphCombo.setTreeContentProvider(new TreeContentProvider());
503
504 fTimeGraphCombo.setTreeLabelProvider(new TreeLabelProvider());
505
506 fTimeGraphCombo.setTreeColumns(COLUMN_NAMES);
507
508 fTimeGraphCombo.getTreeViewer().getTree().getColumn(0).setWidth(COLUMN_WIDTHS[0]);
509 fTimeGraphCombo.getTreeViewer().getTree().getColumn(1).setWidth(COLUMN_WIDTHS[1]);
510 fTimeGraphCombo.getTreeViewer().getTree().getColumn(2).setWidth(COLUMN_WIDTHS[2]);
511 fTimeGraphCombo.getTreeViewer().getTree().getColumn(3).setWidth(COLUMN_WIDTHS[3]);
512 fTimeGraphCombo.getTreeViewer().getTree().getColumn(4).setWidth(COLUMN_WIDTHS[4]);
513
514 fTimeGraphCombo.setTimeGraphProvider(new CallStackPresentationProvider(this));
515 fTimeGraphCombo.getTimeGraphViewer().setTimeFormat(TimeFormat.CALENDAR);
516
517 fTimeGraphCombo.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
518 @Override
519 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {
520 long startTime = event.getStartTime();
521 long endTime = event.getEndTime();
522 TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime));
523 broadcast(new TmfRangeSynchSignal(CallStackView.this, range));
524 startZoomThread(startTime, endTime);
525 }
526 });
527
528 fTimeGraphCombo.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
529 @Override
530 public void timeSelected(TimeGraphTimeEvent event) {
531 long beginTime = event.getBeginTime();
532 long endTime = event.getEndTime();
533 selectTime(beginTime);
534 broadcast(new TmfTimeSynchSignal(CallStackView.this, new TmfNanoTimestamp(beginTime), new TmfNanoTimestamp(endTime)));
535 }
536 });
537
538 fTimeGraphCombo.getTimeGraphViewer().getControl().addControlListener(new ControlAdapter() {
539 @Override
540 public void controlResized(ControlEvent e) {
541 fDisplayWidth = fTimeGraphCombo.getTimeGraphViewer().getControl().getSize().x;
542 if (fEntryList != null) {
543 startZoomThread(fTimeGraphCombo.getTimeGraphViewer().getTime0(), fTimeGraphCombo.getTimeGraphViewer().getTime1());
544 }
545 }
546 });
547
548 fTimeGraphCombo.getTreeViewer().addDoubleClickListener(new IDoubleClickListener() {
549 @Override
550 public void doubleClick(DoubleClickEvent event) {
551 Object selection = ((IStructuredSelection) event.getSelection()).getFirstElement();
552 if (selection instanceof CallStackEntry) {
553 CallStackEntry entry = (CallStackEntry) selection;
554 if (entry.getFunctionName().length() > 0) {
555 long startTime = entry.getStartTime();
556 long endTime = entry.getEndTime();
557 long spacingTime = (long) ((endTime - startTime) * SPACING_RATIO);
558 startTime -= spacingTime;
559 endTime += spacingTime;
560 TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime));
561 broadcast(new TmfRangeSynchSignal(CallStackView.this, range));
562 fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
563 startZoomThread(startTime, endTime);
564 }
565 }
566 }
567 });
568
569 fTimeGraphCombo.getTimeGraphViewer().getTimeGraphControl().addMouseListener(new MouseAdapter() {
570 @Override
571 public void mouseDoubleClick(MouseEvent e) {
572 TimeGraphControl timeGraphControl = fTimeGraphCombo.getTimeGraphViewer().getTimeGraphControl();
573 ISelection selection = timeGraphControl.getSelection();
574 if (selection instanceof TimeGraphSelection) {
575 Object o = ((TimeGraphSelection) selection).getFirstElement();
576 if (o instanceof CallStackEvent) {
577 CallStackEvent event = (CallStackEvent) o;
578 long startTime = event.getTime();
579 long endTime = startTime + event.getDuration();
580 long spacingTime = (long) ((endTime - startTime) * SPACING_RATIO);
581 startTime -= spacingTime;
582 endTime += spacingTime;
583 TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime));
584 broadcast(new TmfRangeSynchSignal(CallStackView.this, range));
585 fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
586 startZoomThread(startTime, endTime);
587 }
588 }
589 }
590 });
591
592 IStatusLineManager statusLineManager = getViewSite().getActionBars().getStatusLineManager();
593 fTimeGraphCombo.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager);
594
595 // View Action Handling
596 makeActions();
597 contributeToActionBars();
598
599 IEditorPart editor = getSite().getPage().getActiveEditor();
600 if (editor instanceof ITmfTraceEditor) {
601 ITmfTrace trace = ((ITmfTraceEditor) editor).getTrace();
602 if (trace != null) {
603 traceSelected(new TmfTraceSelectedSignal(this, trace));
604 }
605 }
606 }
607
608 @Override
609 public void setFocus() {
610 fTimeGraphCombo.setFocus();
611 }
612
613 // ------------------------------------------------------------------------
614 // Signal handlers
615 // ------------------------------------------------------------------------
616 /**
617 * Handler for the trace opened signal.
618 * @param signal
619 * The incoming signal
620 * @since 2.0
621 */
622 @TmfSignalHandler
623 public void traceOpened(TmfTraceOpenedSignal signal) {
624 fTrace = signal.getTrace();
625 loadTrace();
626 }
627
628 /**
629 * Handler for the trace selected signal
630 *
631 * @param signal
632 * The incoming signal
633 */
634 @TmfSignalHandler
635 public void traceSelected(final TmfTraceSelectedSignal signal) {
636 if (signal.getTrace() == fTrace) {
637 return;
638 }
639 fTrace = signal.getTrace();
640 loadTrace();
641 }
642
643 /**
644 * Trace is closed: clear the data structures and the view
645 *
646 * @param signal the signal received
647 */
648 @TmfSignalHandler
649 public void traceClosed(final TmfTraceClosedSignal signal) {
650 synchronized (fBuildThreadMap) {
651 BuildThread buildThread = fBuildThreadMap.remove(signal.getTrace());
652 if (buildThread != null) {
653 buildThread.cancel();
654 }
655 }
656 synchronized (fEntryListMap) {
657 fEntryListMap.remove(signal.getTrace());
658 }
659 fSelectedThreadMap.remove(signal.getTrace());
660 if (signal.getTrace() == fTrace) {
661 fTrace = null;
662 fStartTime = 0;
663 fEndTime = 0;
664 refresh();
665 }
666 }
667
668 /**
669 * Handler for the TimeSynch signal
670 *
671 * @param signal
672 * The incoming signal
673 */
674 @TmfSignalHandler
675 public void synchToTime(final TmfTimeSynchSignal signal) {
676
677 fSavedTimeSyncSignal = isPinned() ? new TmfTimeSynchSignal(signal.getSource(), signal.getBeginTime(), signal.getEndTime()) : null;
678
679 if (signal.getSource() == this || fTrace == null || isPinned()) {
680 return;
681 }
682 final long beginTime = signal.getBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
683 final long endTime = signal.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
684 Display.getDefault().asyncExec(new Runnable() {
685 @Override
686 public void run() {
687 if (fTimeGraphCombo.isDisposed()) {
688 return;
689 }
690 if (beginTime == endTime) {
691 fTimeGraphCombo.getTimeGraphViewer().setSelectedTime(beginTime, true);
692 } else {
693 fTimeGraphCombo.getTimeGraphViewer().setSelectionRange(beginTime, endTime);
694 }
695 selectTime(beginTime);
696 startZoomThread(fTimeGraphCombo.getTimeGraphViewer().getTime0(), fTimeGraphCombo.getTimeGraphViewer().getTime1());
697 if (fEntryList == null) {
698 return;
699 }
700 TimeGraphViewer viewer = fTimeGraphCombo.getTimeGraphViewer();
701 for (ThreadEntry threadEntry : fEntryList) {
702 ITmfStateSystem ss = threadEntry.getStateSystem();
703 if (ss == null || beginTime < ss.getStartTime() || beginTime > ss.getCurrentEndTime()) {
704 continue;
705 }
706 try {
707 int quark = ss.getQuarkRelative(threadEntry.getThreadQuark(), CallStackStateProvider.CALL_STACK);
708 ITmfStateInterval stackInterval = ss.querySingleState(beginTime, quark);
709 if (beginTime == stackInterval.getStartTime()) {
710 int stackLevel = stackInterval.getStateValue().unboxInt();
711 CallStackEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
712 fTimeGraphCombo.setSelection(selectedEntry);
713 viewer.getTimeGraphControl().fireSelectionChanged();
714 break;
715 }
716 } catch (AttributeNotFoundException e) {
717 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
718 } catch (TimeRangeException e) {
719 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
720 } catch (StateSystemDisposedException e) {
721 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
722 } catch (StateValueTypeException e) {
723 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
724 }
725 }
726 }
727 });
728 }
729
730 /**
731 * Handler for the RangeSynch signal
732 *
733 * @param signal
734 * The incoming signal
735 */
736 @TmfSignalHandler
737 public void synchToRange(final TmfRangeSynchSignal signal) {
738
739 if (isPinned()) {
740 fSavedRangeSyncSignal =
741 new TmfRangeSynchSignal(signal.getSource(), new TmfTimeRange(signal.getCurrentRange().getStartTime(), signal.getCurrentRange().getEndTime()));
742
743 fSavedTimeSyncSignal = null;
744 }
745
746 if (signal.getSource() == this || fTrace == null || isPinned()) {
747 return;
748 }
749 if (signal.getCurrentRange().getIntersection(fTrace.getTimeRange()) == null) {
750 return;
751 }
752 final long startTime = signal.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
753 final long endTime = signal.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
754 Display.getDefault().asyncExec(new Runnable() {
755 @Override
756 public void run() {
757 if (fTimeGraphCombo.isDisposed()) {
758 return;
759 }
760 fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
761 startZoomThread(startTime, endTime);
762 }
763 });
764 }
765
766 // ------------------------------------------------------------------------
767 // Internal
768 // ------------------------------------------------------------------------
769
770 private void loadTrace() {
771 synchronized (fEntryListMap) {
772 fEntryList = fEntryListMap.get(fTrace);
773 if (fEntryList == null) {
774 synchronized (fBuildThreadMap) {
775 BuildThread buildThread = new BuildThread(fTrace);
776 fBuildThreadMap.put(fTrace, buildThread);
777 buildThread.start();
778 }
779 } else {
780 fStartTime = fTrace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
781 fEndTime = fTrace.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
782 refresh();
783 }
784 }
785 }
786
787 private void buildThreadList(final ITmfTrace trace, IProgressMonitor monitor) {
788 fStartTime = Long.MAX_VALUE;
789 fEndTime = Long.MIN_VALUE;
790 ITmfTrace[] traces = TmfTraceManager.getTraceSet(trace);
791 ArrayList<ThreadEntry> entryList = new ArrayList<>();
792 for (ITmfTrace aTrace : traces) {
793 if (monitor.isCanceled()) {
794 return;
795 }
796 ITmfStateSystem ss = getCallStackStateSystem(aTrace);
797 if (ss == null) {
798 addUnavailableEntry(aTrace, entryList);
799 continue;
800 }
801 ss.waitUntilBuilt();
802 if (ss.isCancelled()) {
803 addUnavailableEntry(aTrace, entryList);
804 continue;
805 }
806 long startTime = ss.getStartTime();
807 long endTime = ss.getCurrentEndTime() + 1;
808 fStartTime = Math.min(fStartTime, startTime);
809 fEndTime = Math.max(fEndTime, endTime);
810 List<Integer> threadQuarks = ss.getQuarks(CallStackStateProvider.THREADS, "*"); //$NON-NLS-1$
811 for (int i = 0; i < threadQuarks.size(); i++) {
812 if (monitor.isCanceled()) {
813 return;
814 }
815 int threadQuark = threadQuarks.get(i);
816 String thread = ss.getAttributeName(threadQuark);
817 String threadEntryName = thread + ' ' + '(' + aTrace.getName() + ')';
818 ThreadEntry threadEntry = new ThreadEntry(aTrace, threadEntryName, threadQuark, startTime, endTime);
819 entryList.add(threadEntry);
820 int eventStackQuark;
821 try {
822 eventStackQuark = ss.getQuarkRelative(threadQuark, CallStackStateProvider.CALL_STACK);
823 int level = 1;
824 for (int stackLevelQuark : ss.getSubAttributes(eventStackQuark, false)) {
825 CallStackEntry callStackEntry = new CallStackEntry(stackLevelQuark, level++, aTrace);
826 threadEntry.addChild(callStackEntry);
827 }
828 } catch (AttributeNotFoundException e) {
829 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
830 }
831 }
832 }
833 synchronized (fEntryListMap) {
834 fEntryListMap.put(trace, new ArrayList<>(entryList));
835 }
836 if (trace == fTrace) {
837 refresh();
838 }
839 for (ThreadEntry threadEntry : entryList) {
840 for (CallStackEntry callStackEntry : threadEntry.getChildren()) {
841 if (monitor.isCanceled()) {
842 return;
843 }
844 buildStatusEvents(trace, callStackEntry, monitor);
845 }
846 }
847 }
848
849 private void addUnavailableEntry(ITmfTrace trace, List<ThreadEntry> list) {
850 String threadName = Messages.CallStackView_StackInfoNotAvailable + ' ' + '(' + trace.getName() + ')';
851 ThreadEntry threadEntry = new ThreadEntry(trace, threadName, -1, 0, 0);
852 list.add(threadEntry);
853 }
854
855 private void buildStatusEvents(ITmfTrace trace, CallStackEntry entry, IProgressMonitor monitor) {
856 ITmfStateSystem ss = getCallStackStateSystem(entry.getTrace());
857 if (ss == null) {
858 return;
859 }
860 long start = ss.getStartTime();
861 long end = ss.getCurrentEndTime() + 1;
862 long resolution = Math.max(1, (end - start) / fDisplayWidth);
863 List<ITimeEvent> eventList = getEventList(entry, start, end, resolution, monitor);
864 if (monitor.isCanceled()) {
865 return;
866 }
867 entry.setEventList(eventList);
868 if (trace == fTrace) {
869 redraw();
870 }
871 }
872
873 private static List<ITimeEvent> getEventList(CallStackEntry entry,
874 long startTime, long endTime, long resolution,
875 IProgressMonitor monitor) {
876 ITmfStateSystem ss = getCallStackStateSystem(entry.getTrace());
877 if (ss == null) {
878 return null;
879 }
880 long start = Math.max(startTime, ss.getStartTime());
881 long end = Math.min(endTime, ss.getCurrentEndTime() + 1);
882 if (end <= start) {
883 return null;
884 }
885 List<ITimeEvent> eventList = null;
886 try {
887 List<ITmfStateInterval> stackIntervals = ss.queryHistoryRange(entry.getQuark(), start, end - 1, resolution, monitor);
888 eventList = new ArrayList<>(stackIntervals.size());
889 long lastEndTime = -1;
890 boolean lastIsNull = true;
891 for (ITmfStateInterval statusInterval : stackIntervals) {
892 if (monitor.isCanceled()) {
893 return null;
894 }
895 long time = statusInterval.getStartTime();
896 long duration = statusInterval.getEndTime() - time + 1;
897 if (!statusInterval.getStateValue().isNull()) {
898 final int modulo = CallStackPresentationProvider.NUM_COLORS / 2;
899 int value = statusInterval.getStateValue().toString().hashCode() % modulo + modulo;
900 eventList.add(new CallStackEvent(entry, time, duration, value));
901 lastIsNull = false;
902 } else {
903 if (lastEndTime == -1) {
904 // add null event if it intersects the start time
905 eventList.add(new NullTimeEvent(entry, time, duration));
906 } else {
907 if (lastEndTime != time && lastIsNull) {
908 // add unknown event if between two null states
909 eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
910 }
911 if (time + duration >= endTime) {
912 // add null event if it intersects the end time
913 eventList.add(new NullTimeEvent(entry, time, duration));
914 }
915 }
916 lastIsNull = true;
917 }
918 lastEndTime = time + duration;
919 }
920 } catch (AttributeNotFoundException e) {
921 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
922 } catch (TimeRangeException e) {
923 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
924 } catch (StateSystemDisposedException e) {
925 /* Ignored */
926 }
927 return eventList;
928 }
929
930 private void selectTime(long time) {
931 if (fEntryList == null) {
932 return;
933 }
934 for (ThreadEntry threadEntry : fEntryList) {
935 ITmfStateSystem ss = threadEntry.getStateSystem();
936 if (ss == null) {
937 continue;
938 }
939 ss.waitUntilBuilt();
940 if (ss.isCancelled()) {
941 continue;
942 }
943 long queryTime = Math.max(ss.getStartTime(), Math.min(ss.getCurrentEndTime(), time));
944 for (CallStackEntry callStackEntry : threadEntry.getChildren()) {
945 try {
946 ITmfStateInterval stackLevelInterval = ss.querySingleState(queryTime, callStackEntry.getQuark());
947 ITmfStateValue nameValue = stackLevelInterval.getStateValue();
948 String name = ""; //$NON-NLS-1$
949 try {
950 if (nameValue.getType() == Type.STRING) {
951 String address = nameValue.unboxStr();
952 name = getFunctionName(address);
953 } else if (nameValue.getType() == Type.INTEGER) {
954 name = "0x" + Integer.toHexString(nameValue.unboxInt()); //$NON-NLS-1$
955 } else if (nameValue.getType() == Type.LONG) {
956 name = "0x" + Long.toHexString(nameValue.unboxLong()); //$NON-NLS-1$
957 }
958 } catch (StateValueTypeException e) {
959 }
960 callStackEntry.setFunctionName(name);
961 if (name.length() > 0) {
962 callStackEntry.setStartTime(stackLevelInterval.getStartTime());
963 callStackEntry.setEndTime(stackLevelInterval.getEndTime() + 1);
964 }
965 } catch (AttributeNotFoundException e) {
966 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
967 } catch (TimeRangeException e) {
968 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
969 } catch (StateSystemDisposedException e) {
970 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
971 }
972 }
973 }
974 fTimeGraphCombo.refresh();
975 }
976
977 private void refresh() {
978 Display.getDefault().asyncExec(new Runnable() {
979 @Override
980 public void run() {
981 if (fTimeGraphCombo.isDisposed()) {
982 return;
983 }
984 ITimeGraphEntry[] entries = null;
985 synchronized (fEntryListMap) {
986 fEntryList = fEntryListMap.get(fTrace);
987 if (fEntryList == null) {
988 fEntryList = new ArrayList<>();
989 }
990 entries = fEntryList.toArray(new ITimeGraphEntry[0]);
991 }
992 fTimeGraphCombo.setInput(entries);
993 fTimeGraphCombo.getTimeGraphViewer().setTimeBounds(fStartTime, fEndTime);
994
995 long selectionBeginTime = fTrace == null ? 0 : fTraceManager.getSelectionBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
996 long selectionEndTime = fTrace == null ? 0 : fTraceManager.getSelectionEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
997 long startTime = fTrace == null ? 0 : fTraceManager.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
998 long endTime = fTrace == null ? 0 : fTraceManager.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
999 startTime = Math.max(startTime, fStartTime);
1000 endTime = Math.min(endTime, fEndTime);
1001 fTimeGraphCombo.getTimeGraphViewer().setSelectionRange(selectionBeginTime, selectionEndTime);
1002 selectTime(selectionBeginTime);
1003 fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
1004 startZoomThread(startTime, endTime);
1005 }
1006 });
1007 }
1008
1009 private void redraw() {
1010 synchronized (fSyncObj) {
1011 if (fRedrawState == State.IDLE) {
1012 fRedrawState = State.BUSY;
1013 } else {
1014 fRedrawState = State.PENDING;
1015 return;
1016 }
1017 }
1018 Display.getDefault().asyncExec(new Runnable() {
1019 @Override
1020 public void run() {
1021 if (fTimeGraphCombo.isDisposed()) {
1022 return;
1023 }
1024 fTimeGraphCombo.redraw();
1025 fTimeGraphCombo.update();
1026 synchronized (fSyncObj) {
1027 if (fRedrawState == State.PENDING) {
1028 fRedrawState = State.IDLE;
1029 redraw();
1030 } else {
1031 fRedrawState = State.IDLE;
1032 }
1033 }
1034 }
1035 });
1036 }
1037
1038 private void startZoomThread(long startTime, long endTime) {
1039 if (fZoomThread != null) {
1040 fZoomThread.cancel();
1041 }
1042 fZoomThread = new ZoomThread(fEntryList, startTime, endTime);
1043 fZoomThread.start();
1044 }
1045
1046 private void makeActions() {
1047 fPreviousItemAction = fTimeGraphCombo.getTimeGraphViewer().getPreviousItemAction();
1048 fPreviousItemAction.setText(Messages.TmfTimeGraphViewer_PreviousItemActionNameText);
1049 fPreviousItemAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousItemActionToolTipText);
1050 fNextItemAction = fTimeGraphCombo.getTimeGraphViewer().getNextItemAction();
1051 fNextItemAction.setText(Messages.TmfTimeGraphViewer_NextItemActionNameText);
1052 fNextItemAction.setToolTipText(Messages.TmfTimeGraphViewer_NextItemActionToolTipText);
1053 }
1054
1055 private void contributeToActionBars() {
1056 IActionBars bars = getViewSite().getActionBars();
1057 fillLocalToolBar(bars.getToolBarManager());
1058
1059 // Create pin action
1060 contributePinActionToToolBar();
1061 fPinAction.addPropertyChangeListener(new IPropertyChangeListener(){
1062 @Override
1063 public void propertyChange(PropertyChangeEvent event) {
1064 if (IAction.CHECKED.equals(event.getProperty()) && !isPinned()) {
1065 if (fSavedRangeSyncSignal != null) {
1066 synchToRange(fSavedRangeSyncSignal);
1067 fSavedRangeSyncSignal = null;
1068 }
1069
1070 if (fSavedTimeSyncSignal != null) {
1071 synchToTime(fSavedTimeSyncSignal);
1072 fSavedTimeSyncSignal = null;
1073 }
1074 }
1075 }
1076 });
1077 }
1078
1079 private void fillLocalToolBar(IToolBarManager manager) {
1080 manager.add(getImportMappingAction());
1081 manager.add(fTimeGraphCombo.getTimeGraphViewer().getResetScaleAction());
1082 manager.add(getPreviousEventAction());
1083 manager.add(getNextEventAction());
1084 manager.add(fPreviousItemAction);
1085 manager.add(fNextItemAction);
1086 manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomInAction());
1087 manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomOutAction());
1088 manager.add(new Separator());
1089 }
1090
1091 /**
1092 * Get the the next event action.
1093 *
1094 * @return The action object
1095 */
1096 private Action getNextEventAction() {
1097 if (fNextEventAction == null) {
1098 fNextEventAction = new Action() {
1099 @Override
1100 public void run() {
1101 TimeGraphViewer viewer = fTimeGraphCombo.getTimeGraphViewer();
1102 ITimeGraphEntry entry = viewer.getSelection();
1103 if (entry instanceof CallStackEntry) {
1104 try {
1105 CallStackEntry callStackEntry = (CallStackEntry) entry;
1106 ITmfTrace trace = callStackEntry.getTrace();
1107 ITmfStateSystem ss = getCallStackStateSystem(trace);
1108 if (ss == null) {
1109 return;
1110 }
1111 long time = Math.max(ss.getStartTime(), Math.min(ss.getCurrentEndTime(), viewer.getSelectionBegin()));
1112 ThreadEntry threadEntry = (ThreadEntry) callStackEntry.getParent();
1113 int quark = ss.getQuarkRelative(threadEntry.getThreadQuark(), CallStackStateProvider.CALL_STACK);
1114 ITmfStateInterval stackInterval = ss.querySingleState(time, quark);
1115 long newTime = stackInterval.getEndTime() + 1;
1116 viewer.setSelectedTimeNotify(newTime, true);
1117 stackInterval = ss.querySingleState(Math.min(ss.getCurrentEndTime(), newTime), quark);
1118 int stackLevel = stackInterval.getStateValue().unboxInt();
1119 CallStackEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
1120 fTimeGraphCombo.setSelection(selectedEntry);
1121 viewer.getTimeGraphControl().fireSelectionChanged();
1122 startZoomThread(viewer.getTime0(), viewer.getTime1());
1123
1124 } catch (AttributeNotFoundException e) {
1125 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
1126 } catch (TimeRangeException e) {
1127 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
1128 } catch (StateSystemDisposedException e) {
1129 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
1130 } catch (StateValueTypeException e) {
1131 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
1132 }
1133 }
1134 }
1135 };
1136
1137 fNextEventAction.setText(Messages.TmfTimeGraphViewer_NextEventActionNameText);
1138 fNextEventAction.setToolTipText(Messages.TmfTimeGraphViewer_NextEventActionToolTipText);
1139 fNextEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_NEXT_EVENT));
1140 }
1141
1142 return fNextEventAction;
1143 }
1144
1145 /**
1146 * Get the previous event action.
1147 *
1148 * @return The Action object
1149 */
1150 private Action getPreviousEventAction() {
1151 if (fPrevEventAction == null) {
1152 fPrevEventAction = new Action() {
1153 @Override
1154 public void run() {
1155 TimeGraphViewer viewer = fTimeGraphCombo.getTimeGraphViewer();
1156 ITimeGraphEntry entry = viewer.getSelection();
1157 if (entry instanceof CallStackEntry) {
1158 try {
1159 CallStackEntry callStackEntry = (CallStackEntry) entry;
1160 ITmfTrace trace = callStackEntry.getTrace();
1161 ITmfStateSystem ss = getCallStackStateSystem(trace);
1162 if (ss == null) {
1163 return;
1164 }
1165 long time = Math.max(ss.getStartTime(), Math.min(ss.getCurrentEndTime(), viewer.getSelectionBegin()));
1166 ThreadEntry threadEntry = (ThreadEntry) callStackEntry.getParent();
1167 int quark = ss.getQuarkRelative(threadEntry.getThreadQuark(), CallStackStateProvider.CALL_STACK);
1168 ITmfStateInterval stackInterval = ss.querySingleState(time, quark);
1169 if (stackInterval.getStartTime() == time && time > ss.getStartTime()) {
1170 stackInterval = ss.querySingleState(time - 1, quark);
1171 }
1172 viewer.setSelectedTimeNotify(stackInterval.getStartTime(), true);
1173 int stackLevel = stackInterval.getStateValue().unboxInt();
1174 CallStackEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
1175 fTimeGraphCombo.setSelection(selectedEntry);
1176 viewer.getTimeGraphControl().fireSelectionChanged();
1177 startZoomThread(viewer.getTime0(), viewer.getTime1());
1178
1179 } catch (AttributeNotFoundException e) {
1180 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
1181 } catch (TimeRangeException e) {
1182 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
1183 } catch (StateSystemDisposedException e) {
1184 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
1185 } catch (StateValueTypeException e) {
1186 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
1187 }
1188 }
1189 }
1190 };
1191
1192 fPrevEventAction.setText(Messages.TmfTimeGraphViewer_PreviousEventActionNameText);
1193 fPrevEventAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousEventActionToolTipText);
1194 fPrevEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_PREV_EVENT));
1195 }
1196
1197 return fPrevEventAction;
1198 }
1199
1200 @Nullable
1201 static ITmfStateSystem getCallStackStateSystem(ITmfTrace trace) {
1202 /*
1203 * Since we cannot know the exact analysis ID (in separate plugins), we
1204 * will search using the analysis type.
1205 */
1206 Iterable<AbstractCallStackAnalysis> modules =
1207 trace.getAnalysisModulesOfClass(AbstractCallStackAnalysis.class);
1208 Iterator<AbstractCallStackAnalysis> it = modules.iterator();
1209 if (!it.hasNext()) {
1210 /* This trace does not provide a call-stack analysis */
1211 return null;
1212 }
1213
1214 /*
1215 * We only look at the first module we find.
1216 *
1217 * TODO Handle the advanced case where one trace provides more than one
1218 * call-stack analysis.
1219 */
1220 AbstractCallStackAnalysis module = it.next();
1221 /* This analysis is not automatic, we need to schedule it on-demand */
1222 module.schedule();
1223 module.waitForInitialization();
1224 ITmfStateSystem ss = module.getStateSystem();
1225 if (ss == null) {
1226 /* If we've waited for initialization, 'ss' should not be null */
1227 throw new IllegalStateException();
1228 }
1229 return ss;
1230 }
1231
1232 // ------------------------------------------------------------------------
1233 // Methods related to function name mapping
1234 // ------------------------------------------------------------------------
1235
1236 /**
1237 * Toolbar icon to import the function address-to-name mapping file.
1238 */
1239 private Action getImportMappingAction() {
1240 if (fImportMappingAction != null) {
1241 return fImportMappingAction;
1242 }
1243 fImportMappingAction = new Action() {
1244 @Override
1245 public void run() {
1246 FileDialog dialog = new FileDialog(getViewSite().getShell());
1247 dialog.setText(Messages.CallStackView_ImportMappingDialogTitle);
1248 String filePath = dialog.open();
1249 if (filePath == null) {
1250 /* No file was selected, don't change anything */
1251 return;
1252 }
1253 /*
1254 * Start the mapping import in a separate thread (we do not want
1255 * to UI thread to do this).
1256 */
1257 Job job = new ImportMappingJob(new File(filePath));
1258 job.schedule();
1259 }
1260 };
1261
1262 fImportMappingAction.setText(Messages.CallStackView_ImportMappingButtonText);
1263 fImportMappingAction.setToolTipText(Messages.CallStackView_ImportMappingButtonTooltip);
1264 fImportMappingAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(IMPORT_MAPPING_ICON_PATH));
1265
1266 return fImportMappingAction;
1267 }
1268
1269 private class ImportMappingJob extends Job {
1270 private final File fMappingFile;
1271
1272 public ImportMappingJob(File mappingFile) {
1273 super(Messages.CallStackView_ImportMappingJobName);
1274 fMappingFile = mappingFile;
1275 }
1276
1277 @Override
1278 public IStatus run(IProgressMonitor monitor) {
1279 fNameMapping = FunctionNameMapper.mapFromNmTextFile(fMappingFile);
1280
1281 /* Refresh the time graph and the list of entries */
1282 buildThreadList(fTrace, new NullProgressMonitor());
1283 redraw();
1284
1285 return Status.OK_STATUS;
1286 }
1287 }
1288
1289 String getFunctionName(String address) {
1290 if (fNameMapping == null) {
1291 /* No mapping available, just print the addresses */
1292 return address;
1293 }
1294 String ret = fNameMapping.get(address);
1295 if (ret == null) {
1296 /* We didn't find this address in the mapping file, just use the address */
1297 return address;
1298 }
1299 return ret;
1300 }
1301
1302 }
This page took 0.067187 seconds and 4 git commands to generate.