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