tmf/lttng: Update 2014 copyrights
[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.TmfExperiment;
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;
791 if (trace instanceof TmfExperiment) {
792 TmfExperiment experiment = (TmfExperiment) trace;
793 traces = experiment.getTraces();
794 } else {
795 traces = new ITmfTrace[] { trace };
796 }
797 ArrayList<ThreadEntry> entryList = new ArrayList<>();
798 for (ITmfTrace aTrace : traces) {
799 if (monitor.isCanceled()) {
800 return;
801 }
802 ITmfStateSystem ss = getCallStackStateSystem(aTrace);
803 if (ss == null) {
804 addUnavailableEntry(aTrace, entryList);
805 continue;
806 }
807 ss.waitUntilBuilt();
808 if (ss.isCancelled()) {
809 addUnavailableEntry(aTrace, entryList);
810 continue;
811 }
812 long startTime = ss.getStartTime();
813 long endTime = ss.getCurrentEndTime() + 1;
814 fStartTime = Math.min(fStartTime, startTime);
815 fEndTime = Math.max(fEndTime, endTime);
816 List<Integer> threadQuarks = ss.getQuarks(CallStackStateProvider.THREADS, "*"); //$NON-NLS-1$
817 for (int i = 0; i < threadQuarks.size(); i++) {
818 if (monitor.isCanceled()) {
819 return;
820 }
821 int threadQuark = threadQuarks.get(i);
822 String thread = ss.getAttributeName(threadQuark);
823 String threadEntryName = thread + ' ' + '(' + aTrace.getName() + ')';
824 ThreadEntry threadEntry = new ThreadEntry(aTrace, threadEntryName, threadQuark, startTime, endTime);
825 entryList.add(threadEntry);
826 int eventStackQuark;
827 try {
828 eventStackQuark = ss.getQuarkRelative(threadQuark, CallStackStateProvider.CALL_STACK);
829 int level = 1;
830 for (int stackLevelQuark : ss.getSubAttributes(eventStackQuark, false)) {
831 CallStackEntry callStackEntry = new CallStackEntry(stackLevelQuark, level++, aTrace);
832 threadEntry.addChild(callStackEntry);
833 }
834 } catch (AttributeNotFoundException e) {
835 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
836 }
837 }
838 }
839 synchronized (fEntryListMap) {
840 fEntryListMap.put(trace, new ArrayList<>(entryList));
841 }
842 if (trace == fTrace) {
843 refresh();
844 }
845 for (ThreadEntry threadEntry : entryList) {
846 for (CallStackEntry callStackEntry : threadEntry.getChildren()) {
847 if (monitor.isCanceled()) {
848 return;
849 }
850 buildStatusEvents(trace, callStackEntry, monitor);
851 }
852 }
853 }
854
855 private void addUnavailableEntry(ITmfTrace trace, List<ThreadEntry> list) {
856 String threadName = Messages.CallStackView_StackInfoNotAvailable + ' ' + '(' + trace.getName() + ')';
857 ThreadEntry threadEntry = new ThreadEntry(trace, threadName, -1, 0, 0);
858 list.add(threadEntry);
859 }
860
861 private void buildStatusEvents(ITmfTrace trace, CallStackEntry entry, IProgressMonitor monitor) {
862 ITmfStateSystem ss = getCallStackStateSystem(entry.getTrace());
863 if (ss == null) {
864 return;
865 }
866 long start = ss.getStartTime();
867 long end = ss.getCurrentEndTime() + 1;
868 long resolution = Math.max(1, (end - start) / fDisplayWidth);
869 List<ITimeEvent> eventList = getEventList(entry, start, end, resolution, monitor);
870 if (monitor.isCanceled()) {
871 return;
872 }
873 entry.setEventList(eventList);
874 if (trace == fTrace) {
875 redraw();
876 }
877 }
878
879 private static List<ITimeEvent> getEventList(CallStackEntry entry,
880 long startTime, long endTime, long resolution,
881 IProgressMonitor monitor) {
882 ITmfStateSystem ss = getCallStackStateSystem(entry.getTrace());
883 if (ss == null) {
884 return null;
885 }
886 long start = Math.max(startTime, ss.getStartTime());
887 long end = Math.min(endTime, ss.getCurrentEndTime() + 1);
888 if (end <= start) {
889 return null;
890 }
891 List<ITimeEvent> eventList = null;
892 try {
893 List<ITmfStateInterval> stackIntervals = ss.queryHistoryRange(entry.getQuark(), start, end - 1, resolution, monitor);
894 eventList = new ArrayList<>(stackIntervals.size());
895 long lastEndTime = -1;
896 boolean lastIsNull = true;
897 for (ITmfStateInterval statusInterval : stackIntervals) {
898 if (monitor.isCanceled()) {
899 return null;
900 }
901 long time = statusInterval.getStartTime();
902 long duration = statusInterval.getEndTime() - time + 1;
903 if (!statusInterval.getStateValue().isNull()) {
904 final int modulo = CallStackPresentationProvider.NUM_COLORS / 2;
905 int value = statusInterval.getStateValue().toString().hashCode() % modulo + modulo;
906 eventList.add(new CallStackEvent(entry, time, duration, value));
907 lastIsNull = false;
908 } else {
909 if (lastEndTime == -1) {
910 // add null event if it intersects the start time
911 eventList.add(new NullTimeEvent(entry, time, duration));
912 } else {
913 if (lastEndTime != time && lastIsNull) {
914 // add unknown event if between two null states
915 eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
916 }
917 if (time + duration >= endTime) {
918 // add null event if it intersects the end time
919 eventList.add(new NullTimeEvent(entry, time, duration));
920 }
921 }
922 lastIsNull = true;
923 }
924 lastEndTime = time + duration;
925 }
926 } catch (AttributeNotFoundException e) {
927 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
928 } catch (TimeRangeException e) {
929 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
930 } catch (StateSystemDisposedException e) {
931 /* Ignored */
932 }
933 return eventList;
934 }
935
936 private void selectTime(long time) {
937 if (fEntryList == null) {
938 return;
939 }
940 for (ThreadEntry threadEntry : fEntryList) {
941 ITmfStateSystem ss = threadEntry.getStateSystem();
942 if (ss == null) {
943 continue;
944 }
945 ss.waitUntilBuilt();
946 if (ss.isCancelled()) {
947 continue;
948 }
949 long queryTime = Math.max(ss.getStartTime(), Math.min(ss.getCurrentEndTime(), time));
950 for (CallStackEntry callStackEntry : threadEntry.getChildren()) {
951 try {
952 ITmfStateInterval stackLevelInterval = ss.querySingleState(queryTime, callStackEntry.getQuark());
953 ITmfStateValue nameValue = stackLevelInterval.getStateValue();
954 String name = ""; //$NON-NLS-1$
955 try {
956 if (nameValue.getType() == Type.STRING) {
957 String address = nameValue.unboxStr();
958 name = getFunctionName(address);
959 } else if (nameValue.getType() == Type.INTEGER) {
960 name = "0x" + Integer.toHexString(nameValue.unboxInt()); //$NON-NLS-1$
961 } else if (nameValue.getType() == Type.LONG) {
962 name = "0x" + Long.toHexString(nameValue.unboxLong()); //$NON-NLS-1$
963 }
964 } catch (StateValueTypeException e) {
965 }
966 callStackEntry.setFunctionName(name);
967 if (name.length() > 0) {
968 callStackEntry.setStartTime(stackLevelInterval.getStartTime());
969 callStackEntry.setEndTime(stackLevelInterval.getEndTime() + 1);
970 }
971 } catch (AttributeNotFoundException e) {
972 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
973 } catch (TimeRangeException e) {
974 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
975 } catch (StateSystemDisposedException e) {
976 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
977 }
978 }
979 }
980 fTimeGraphCombo.refresh();
981 }
982
983 private void refresh() {
984 Display.getDefault().asyncExec(new Runnable() {
985 @Override
986 public void run() {
987 if (fTimeGraphCombo.isDisposed()) {
988 return;
989 }
990 ITimeGraphEntry[] entries = null;
991 synchronized (fEntryListMap) {
992 fEntryList = fEntryListMap.get(fTrace);
993 if (fEntryList == null) {
994 fEntryList = new ArrayList<>();
995 }
996 entries = fEntryList.toArray(new ITimeGraphEntry[0]);
997 }
998 fTimeGraphCombo.setInput(entries);
999 fTimeGraphCombo.getTimeGraphViewer().setTimeBounds(fStartTime, fEndTime);
1000
1001 long selectionBeginTime = fTrace == null ? 0 : fTraceManager.getSelectionBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1002 long selectionEndTime = fTrace == null ? 0 : fTraceManager.getSelectionEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1003 long startTime = fTrace == null ? 0 : fTraceManager.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1004 long endTime = fTrace == null ? 0 : fTraceManager.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1005 startTime = Math.max(startTime, fStartTime);
1006 endTime = Math.min(endTime, fEndTime);
1007 fTimeGraphCombo.getTimeGraphViewer().setSelectionRange(selectionBeginTime, selectionEndTime);
1008 selectTime(selectionBeginTime);
1009 fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
1010 startZoomThread(startTime, endTime);
1011 }
1012 });
1013 }
1014
1015 private void redraw() {
1016 synchronized (fSyncObj) {
1017 if (fRedrawState == State.IDLE) {
1018 fRedrawState = State.BUSY;
1019 } else {
1020 fRedrawState = State.PENDING;
1021 return;
1022 }
1023 }
1024 Display.getDefault().asyncExec(new Runnable() {
1025 @Override
1026 public void run() {
1027 if (fTimeGraphCombo.isDisposed()) {
1028 return;
1029 }
1030 fTimeGraphCombo.redraw();
1031 fTimeGraphCombo.update();
1032 synchronized (fSyncObj) {
1033 if (fRedrawState == State.PENDING) {
1034 fRedrawState = State.IDLE;
1035 redraw();
1036 } else {
1037 fRedrawState = State.IDLE;
1038 }
1039 }
1040 }
1041 });
1042 }
1043
1044 private void startZoomThread(long startTime, long endTime) {
1045 if (fZoomThread != null) {
1046 fZoomThread.cancel();
1047 }
1048 fZoomThread = new ZoomThread(fEntryList, startTime, endTime);
1049 fZoomThread.start();
1050 }
1051
1052 private void makeActions() {
1053 fPreviousItemAction = fTimeGraphCombo.getTimeGraphViewer().getPreviousItemAction();
1054 fPreviousItemAction.setText(Messages.TmfTimeGraphViewer_PreviousItemActionNameText);
1055 fPreviousItemAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousItemActionToolTipText);
1056 fNextItemAction = fTimeGraphCombo.getTimeGraphViewer().getNextItemAction();
1057 fNextItemAction.setText(Messages.TmfTimeGraphViewer_NextItemActionNameText);
1058 fNextItemAction.setToolTipText(Messages.TmfTimeGraphViewer_NextItemActionToolTipText);
1059 }
1060
1061 private void contributeToActionBars() {
1062 IActionBars bars = getViewSite().getActionBars();
1063 fillLocalToolBar(bars.getToolBarManager());
1064
1065 // Create pin action
1066 contributePinActionToToolBar();
1067 fPinAction.addPropertyChangeListener(new IPropertyChangeListener(){
1068 @Override
1069 public void propertyChange(PropertyChangeEvent event) {
1070 if (IAction.CHECKED.equals(event.getProperty()) && !isPinned()) {
1071 if (fSavedRangeSyncSignal != null) {
1072 synchToRange(fSavedRangeSyncSignal);
1073 fSavedRangeSyncSignal = null;
1074 }
1075
1076 if (fSavedTimeSyncSignal != null) {
1077 synchToTime(fSavedTimeSyncSignal);
1078 fSavedTimeSyncSignal = null;
1079 }
1080 }
1081 }
1082 });
1083 }
1084
1085 private void fillLocalToolBar(IToolBarManager manager) {
1086 manager.add(getImportMappingAction());
1087 manager.add(fTimeGraphCombo.getTimeGraphViewer().getResetScaleAction());
1088 manager.add(getPreviousEventAction());
1089 manager.add(getNextEventAction());
1090 manager.add(fPreviousItemAction);
1091 manager.add(fNextItemAction);
1092 manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomInAction());
1093 manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomOutAction());
1094 manager.add(new Separator());
1095 }
1096
1097 /**
1098 * Get the the next event action.
1099 *
1100 * @return The action object
1101 */
1102 private Action getNextEventAction() {
1103 if (fNextEventAction == null) {
1104 fNextEventAction = new Action() {
1105 @Override
1106 public void run() {
1107 TimeGraphViewer viewer = fTimeGraphCombo.getTimeGraphViewer();
1108 ITimeGraphEntry entry = viewer.getSelection();
1109 if (entry instanceof CallStackEntry) {
1110 try {
1111 CallStackEntry callStackEntry = (CallStackEntry) entry;
1112 ITmfTrace trace = callStackEntry.getTrace();
1113 ITmfStateSystem ss = getCallStackStateSystem(trace);
1114 if (ss == null) {
1115 return;
1116 }
1117 long time = Math.max(ss.getStartTime(), Math.min(ss.getCurrentEndTime(), viewer.getSelectionBegin()));
1118 ThreadEntry threadEntry = (ThreadEntry) callStackEntry.getParent();
1119 int quark = ss.getQuarkRelative(threadEntry.getThreadQuark(), CallStackStateProvider.CALL_STACK);
1120 ITmfStateInterval stackInterval = ss.querySingleState(time, quark);
1121 long newTime = stackInterval.getEndTime() + 1;
1122 viewer.setSelectedTimeNotify(newTime, true);
1123 stackInterval = ss.querySingleState(Math.min(ss.getCurrentEndTime(), newTime), quark);
1124 int stackLevel = stackInterval.getStateValue().unboxInt();
1125 CallStackEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
1126 fTimeGraphCombo.setSelection(selectedEntry);
1127 viewer.getTimeGraphControl().fireSelectionChanged();
1128 startZoomThread(viewer.getTime0(), viewer.getTime1());
1129
1130 } catch (AttributeNotFoundException e) {
1131 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
1132 } catch (TimeRangeException e) {
1133 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
1134 } catch (StateSystemDisposedException e) {
1135 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
1136 } catch (StateValueTypeException e) {
1137 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
1138 }
1139 }
1140 }
1141 };
1142
1143 fNextEventAction.setText(Messages.TmfTimeGraphViewer_NextEventActionNameText);
1144 fNextEventAction.setToolTipText(Messages.TmfTimeGraphViewer_NextEventActionToolTipText);
1145 fNextEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_NEXT_EVENT));
1146 }
1147
1148 return fNextEventAction;
1149 }
1150
1151 /**
1152 * Get the previous event action.
1153 *
1154 * @return The Action object
1155 */
1156 private Action getPreviousEventAction() {
1157 if (fPrevEventAction == null) {
1158 fPrevEventAction = new Action() {
1159 @Override
1160 public void run() {
1161 TimeGraphViewer viewer = fTimeGraphCombo.getTimeGraphViewer();
1162 ITimeGraphEntry entry = viewer.getSelection();
1163 if (entry instanceof CallStackEntry) {
1164 try {
1165 CallStackEntry callStackEntry = (CallStackEntry) entry;
1166 ITmfTrace trace = callStackEntry.getTrace();
1167 ITmfStateSystem ss = getCallStackStateSystem(trace);
1168 if (ss == null) {
1169 return;
1170 }
1171 long time = Math.max(ss.getStartTime(), Math.min(ss.getCurrentEndTime(), viewer.getSelectionBegin()));
1172 ThreadEntry threadEntry = (ThreadEntry) callStackEntry.getParent();
1173 int quark = ss.getQuarkRelative(threadEntry.getThreadQuark(), CallStackStateProvider.CALL_STACK);
1174 ITmfStateInterval stackInterval = ss.querySingleState(time, quark);
1175 if (stackInterval.getStartTime() == time && time > ss.getStartTime()) {
1176 stackInterval = ss.querySingleState(time - 1, quark);
1177 }
1178 viewer.setSelectedTimeNotify(stackInterval.getStartTime(), true);
1179 int stackLevel = stackInterval.getStateValue().unboxInt();
1180 CallStackEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
1181 fTimeGraphCombo.setSelection(selectedEntry);
1182 viewer.getTimeGraphControl().fireSelectionChanged();
1183 startZoomThread(viewer.getTime0(), viewer.getTime1());
1184
1185 } catch (AttributeNotFoundException e) {
1186 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
1187 } catch (TimeRangeException e) {
1188 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
1189 } catch (StateSystemDisposedException e) {
1190 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
1191 } catch (StateValueTypeException e) {
1192 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
1193 }
1194 }
1195 }
1196 };
1197
1198 fPrevEventAction.setText(Messages.TmfTimeGraphViewer_PreviousEventActionNameText);
1199 fPrevEventAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousEventActionToolTipText);
1200 fPrevEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_PREV_EVENT));
1201 }
1202
1203 return fPrevEventAction;
1204 }
1205
1206 @Nullable
1207 static ITmfStateSystem getCallStackStateSystem(ITmfTrace trace) {
1208 /*
1209 * Since we cannot know the exact analysis ID (in separate plugins), we
1210 * will search using the analysis type.
1211 */
1212 Iterable<AbstractCallStackAnalysis> modules =
1213 trace.getAnalysisModulesOfClass(AbstractCallStackAnalysis.class);
1214 Iterator<AbstractCallStackAnalysis> it = modules.iterator();
1215 if (!it.hasNext()) {
1216 /* This trace does not provide a call-stack analysis */
1217 return null;
1218 }
1219
1220 /*
1221 * We only look at the first module we find.
1222 *
1223 * TODO Handle the advanced case where one trace provides more than one
1224 * call-stack analysis.
1225 */
1226 AbstractCallStackAnalysis module = it.next();
1227 /* This analysis is not automatic, we need to schedule it on-demand */
1228 module.schedule();
1229 module.waitForInitialization();
1230 ITmfStateSystem ss = module.getStateSystem();
1231 if (ss == null) {
1232 /* If we've waited for initialization, 'ss' should not be null */
1233 throw new IllegalStateException();
1234 }
1235 return ss;
1236 }
1237
1238 // ------------------------------------------------------------------------
1239 // Methods related to function name mapping
1240 // ------------------------------------------------------------------------
1241
1242 /**
1243 * Toolbar icon to import the function address-to-name mapping file.
1244 */
1245 private Action getImportMappingAction() {
1246 if (fImportMappingAction != null) {
1247 return fImportMappingAction;
1248 }
1249 fImportMappingAction = new Action() {
1250 @Override
1251 public void run() {
1252 FileDialog dialog = new FileDialog(getViewSite().getShell());
1253 dialog.setText(Messages.CallStackView_ImportMappingDialogTitle);
1254 String filePath = dialog.open();
1255 if (filePath == null) {
1256 /* No file was selected, don't change anything */
1257 return;
1258 }
1259 /*
1260 * Start the mapping import in a separate thread (we do not want
1261 * to UI thread to do this).
1262 */
1263 Job job = new ImportMappingJob(new File(filePath));
1264 job.schedule();
1265 }
1266 };
1267
1268 fImportMappingAction.setText(Messages.CallStackView_ImportMappingButtonText);
1269 fImportMappingAction.setToolTipText(Messages.CallStackView_ImportMappingButtonTooltip);
1270 fImportMappingAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(IMPORT_MAPPING_ICON_PATH));
1271
1272 return fImportMappingAction;
1273 }
1274
1275 private class ImportMappingJob extends Job {
1276 private final File fMappingFile;
1277
1278 public ImportMappingJob(File mappingFile) {
1279 super(Messages.CallStackView_ImportMappingJobName);
1280 fMappingFile = mappingFile;
1281 }
1282
1283 @Override
1284 public IStatus run(IProgressMonitor monitor) {
1285 fNameMapping = FunctionNameMapper.mapFromNmTextFile(fMappingFile);
1286
1287 /* Refresh the time graph and the list of entries */
1288 buildThreadList(fTrace, new NullProgressMonitor());
1289 redraw();
1290
1291 return Status.OK_STATUS;
1292 }
1293 }
1294
1295 String getFunctionName(String address) {
1296 if (fNameMapping == null) {
1297 /* No mapping available, just print the addresses */
1298 return address;
1299 }
1300 String ret = fNameMapping.get(address);
1301 if (ret == null) {
1302 /* We didn't find this address in the mapping file, just use the address */
1303 return address;
1304 }
1305 return ret;
1306 }
1307
1308 }
This page took 0.1293 seconds and 5 git commands to generate.