tmf: Fix NLS bundle for the time offset dialog
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / 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
41d9ce5b 12 * Marc-Andre Laperle - Map from binary file
e8251298
PT
13 *******************************************************************************/
14
2bdf0193 15package org.eclipse.tracecompass.tmf.ui.views.callstack;
e8251298 16
5da83da5 17import java.io.File;
e8251298 18import java.util.ArrayList;
26c33ee2 19import java.util.Collections;
46cc1ade 20import java.util.Comparator;
e8251298
PT
21import java.util.HashMap;
22import java.util.Iterator;
23import java.util.List;
52974e38 24import java.util.Map;
26c33ee2 25import java.util.concurrent.CopyOnWriteArrayList;
e8251298
PT
26
27import org.eclipse.core.runtime.IProgressMonitor;
5da83da5 28import org.eclipse.core.runtime.IStatus;
e8251298 29import org.eclipse.core.runtime.NullProgressMonitor;
5da83da5
AM
30import org.eclipse.core.runtime.Status;
31import org.eclipse.core.runtime.jobs.Job;
50659279 32import org.eclipse.jdt.annotation.Nullable;
e8251298
PT
33import org.eclipse.jface.action.Action;
34import org.eclipse.jface.action.IAction;
0fcf3b09 35import org.eclipse.jface.action.IStatusLineManager;
e8251298 36import org.eclipse.jface.action.IToolBarManager;
46cc1ade 37import org.eclipse.jface.action.MenuManager;
e8251298 38import org.eclipse.jface.action.Separator;
46cc1ade
PT
39import org.eclipse.jface.dialogs.IDialogSettings;
40import org.eclipse.jface.resource.ImageDescriptor;
e8251298
PT
41import org.eclipse.jface.util.IPropertyChangeListener;
42import org.eclipse.jface.util.PropertyChangeEvent;
43import org.eclipse.jface.viewers.DoubleClickEvent;
44import org.eclipse.jface.viewers.IDoubleClickListener;
45import org.eclipse.jface.viewers.ILabelProviderListener;
46import org.eclipse.jface.viewers.ISelection;
47import org.eclipse.jface.viewers.IStructuredSelection;
48import org.eclipse.jface.viewers.ITableLabelProvider;
49import org.eclipse.jface.viewers.ITreeContentProvider;
50import org.eclipse.jface.viewers.Viewer;
e8251298
PT
51import org.eclipse.swt.SWT;
52import org.eclipse.swt.events.ControlAdapter;
53import org.eclipse.swt.events.ControlEvent;
54import org.eclipse.swt.events.MouseAdapter;
55import org.eclipse.swt.events.MouseEvent;
56import org.eclipse.swt.graphics.Image;
57import org.eclipse.swt.widgets.Composite;
58import org.eclipse.swt.widgets.Display;
5da83da5 59import org.eclipse.swt.widgets.FileDialog;
46cc1ade
PT
60import org.eclipse.swt.widgets.Menu;
61import org.eclipse.swt.widgets.Tree;
2bdf0193
AM
62import org.eclipse.tracecompass.internal.tmf.ui.Activator;
63import org.eclipse.tracecompass.internal.tmf.ui.ITmfImageConstants;
64import org.eclipse.tracecompass.internal.tmf.ui.Messages;
e894a508
AM
65import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
66import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
67import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
68import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
69import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
70import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
71import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
72import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue.Type;
2bdf0193
AM
73import org.eclipse.tracecompass.tmf.core.signal.TmfRangeSynchSignal;
74import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
75import org.eclipse.tracecompass.tmf.core.signal.TmfTimeSynchSignal;
76import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
77import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
78import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
79import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
80import org.eclipse.tracecompass.tmf.core.timestamp.TmfNanoTimestamp;
81import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
82import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
83import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampDelta;
84import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
85import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
86import org.eclipse.tracecompass.tmf.ui.editors.ITmfTraceEditor;
87import org.eclipse.tracecompass.tmf.ui.views.TmfView;
88import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphContentProvider;
89import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;
90import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
91import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphCombo;
92import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;
93import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
94import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphViewer;
95import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
96import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
97import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent;
98import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
99import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
100import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl;
101import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphSelection;
102import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
e8251298
PT
103import org.eclipse.ui.IActionBars;
104import org.eclipse.ui.IEditorPart;
105
106/**
107 * Main implementation for the Call Stack view
108 *
109 * @author Patrick Tasse
110 * @since 2.0
111 */
112public class CallStackView extends TmfView {
113
114 // ------------------------------------------------------------------------
115 // Constants
116 // ------------------------------------------------------------------------
117
118 /** View ID. */
119 public static final String ID = "org.eclipse.linuxtools.tmf.ui.views.callstack"; //$NON-NLS-1$
120
121 /**
122 * Redraw state enum
123 */
bac9c0df
MK
124 private enum State {
125 IDLE, BUSY, PENDING
126 }
e8251298 127
46cc1ade 128 private static final String[] COLUMN_TIMES = new String[] {
e8251298
PT
129 Messages.CallStackView_FunctionColumn,
130 Messages.CallStackView_DepthColumn,
131 Messages.CallStackView_EntryTimeColumn,
132 Messages.CallStackView_ExitTimeColumn,
133 Messages.CallStackView_DurationColumn
134 };
135
52974e38
PT
136 private static final int[] COLUMN_WIDTHS = new int[] {
137 200,
138 50,
139 120,
140 120,
141 120
142 };
143
26c33ee2
PT
144 /** Timeout between updates in the build thread in ms */
145 private static final long BUILD_UPDATE_TIMEOUT = 500;
146
52974e38
PT
147 // Fraction of a function duration to be added as spacing
148 private static final double SPACING_RATIO = 0.01;
149
e8251298
PT
150 private static final Image THREAD_IMAGE = Activator.getDefault().getImageFromPath("icons/obj16/thread_obj.gif"); //$NON-NLS-1$
151 private static final Image STACKFRAME_IMAGE = Activator.getDefault().getImageFromPath("icons/obj16/stckframe_obj.gif"); //$NON-NLS-1$
152
5da83da5 153 private static final String IMPORT_MAPPING_ICON_PATH = "icons/etool16/import.gif"; //$NON-NLS-1$
41d9ce5b 154 private static final String IMPORT_BINARY_ICON_PATH = "icons/obj16/binaries_obj.gif"; //$NON-NLS-1$
5da83da5 155
46cc1ade
PT
156 private static final ImageDescriptor SORT_BY_NAME_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_alpha.gif"); //$NON-NLS-1$
157 private static final ImageDescriptor SORT_BY_NAME_REV_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_alpha_rev.gif"); //$NON-NLS-1$
158 private static final ImageDescriptor SORT_BY_ID_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_num.gif"); //$NON-NLS-1$
159 private static final ImageDescriptor SORT_BY_ID_REV_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_num_rev.gif"); //$NON-NLS-1$
160 private static final ImageDescriptor SORT_BY_TIME_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_time.gif"); //$NON-NLS-1$
161 private static final ImageDescriptor SORT_BY_TIME_REV_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_time_rev.gif"); //$NON-NLS-1$
162 private static final String SORT_OPTION_KEY = "sort.option"; //$NON-NLS-1$
bac9c0df
MK
163
164 private enum SortOption {
165 BY_NAME, BY_NAME_REV, BY_ID, BY_ID_REV, BY_TIME, BY_TIME_REV
166 }
167
46cc1ade
PT
168 private SortOption fSortOption;
169 private Comparator<ITimeGraphEntry> fThreadComparator = null;
170 private Action fSortByNameAction;
171 private Action fSortByIdAction;
172 private Action fSortByTimeAction;
173
e8251298
PT
174 // ------------------------------------------------------------------------
175 // Fields
176 // ------------------------------------------------------------------------
177
178 // The time graph combo
52974e38 179 private TimeGraphCombo fTimeGraphCombo;
e8251298
PT
180
181 // The selected trace
182 private ITmfTrace fTrace;
183
184 // The selected thread map
507b1336 185 private final Map<ITmfTrace, String> fSelectedThreadMap = new HashMap<>();
e8251298
PT
186
187 // The time graph entry list
60b4d44c 188 private List<TraceEntry> fEntryList;
e8251298
PT
189
190 // The trace to entry list hash map
26c33ee2 191 private final Map<ITmfTrace, List<TraceEntry>> fEntryListMap = new HashMap<>();
e8251298
PT
192
193 // The trace to build thread hash map
507b1336 194 private final Map<ITmfTrace, BuildThread> fBuildThreadMap = new HashMap<>();
e8251298 195
5da83da5
AM
196 /** The map to map function addresses to function names */
197 private Map<String, String> fNameMapping;
198
e8251298
PT
199 // The start time
200 private long fStartTime;
201
202 // The end time
203 private long fEndTime;
204
205 // The display width
206 private int fDisplayWidth;
207
208 // The next event action
209 private Action fNextEventAction;
210
211 // The previous event action
212 private Action fPrevEventAction;
213
214 // The next item action
215 private Action fNextItemAction;
216
217 // The previous item action
218 private Action fPreviousItemAction;
219
41d9ce5b 220 // The action to import a function-name mapping file
5da83da5
AM
221 private Action fImportMappingAction;
222
41d9ce5b
MAL
223 // The action to import a binary file mapping */
224 private Action fImportBinaryFileMappingAction;
225
e8251298
PT
226 // The zoom thread
227 private ZoomThread fZoomThread;
228
229 // The redraw state used to prevent unnecessary queuing of display runnables
230 private State fRedrawState = State.IDLE;
231
232 // The redraw synchronization object
52974e38 233 private final Object fSyncObj = new Object();
e8251298
PT
234
235 // The saved time sync. signal used when switching off the pinning of a view
236 private TmfTimeSynchSignal fSavedTimeSyncSignal;
237
bac9c0df
MK
238 // The saved time range sync. signal used when switching off the pinning of
239 // a view
e8251298
PT
240 private TmfRangeSynchSignal fSavedRangeSyncSignal;
241
242 // ------------------------------------------------------------------------
243 // Classes
244 // ------------------------------------------------------------------------
245
60b4d44c
PT
246 private class TraceEntry extends TimeGraphEntry {
247 public TraceEntry(String name, long startTime, long endTime) {
248 super(name, startTime, endTime);
249 }
250
251 @Override
252 public boolean hasTimeEvents() {
253 return false;
254 }
255 }
256
257 private class ThreadEntry extends TimeGraphEntry {
da27e43a
PT
258 // The call stack quark
259 private final int fCallStackQuark;
50659279
AM
260 // The state system from which this entry comes
261 private final ITmfStateSystem fSS;
46cc1ade
PT
262 // The thread id
263 private final long fThreadId;
e8251298 264
46cc1ade 265 public ThreadEntry(ITmfStateSystem ss, String name, long threadId, int callStackQuark, long startTime, long endTime) {
60b4d44c 266 super(name, startTime, endTime);
da27e43a 267 fCallStackQuark = callStackQuark;
46cc1ade 268 fThreadId = threadId;
da27e43a 269 fSS = ss;
e8251298
PT
270 }
271
e8251298
PT
272 @Override
273 public boolean hasTimeEvents() {
274 return false;
275 }
276
da27e43a
PT
277 public int getCallStackQuark() {
278 return fCallStackQuark;
e8251298
PT
279 }
280
46cc1ade
PT
281 public long getThreadId() {
282 return fThreadId;
283 }
284
50659279
AM
285 @Nullable
286 public ITmfStateSystem getStateSystem() {
287 return fSS;
e8251298 288 }
e8251298
PT
289 }
290
46cc1ade
PT
291 private class ThreadNameComparator implements Comparator<ITimeGraphEntry> {
292 private boolean reverse;
bac9c0df 293
46cc1ade
PT
294 public ThreadNameComparator(boolean reverse) {
295 this.reverse = reverse;
296 }
bac9c0df 297
46cc1ade
PT
298 @Override
299 public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) {
300 return reverse ? o2.getName().compareTo(o1.getName()) :
bac9c0df 301 o1.getName().compareTo(o2.getName());
46cc1ade
PT
302 }
303 }
304
305 private class ThreadIdComparator implements Comparator<ITimeGraphEntry> {
306 private boolean reverse;
bac9c0df 307
46cc1ade
PT
308 public ThreadIdComparator(boolean reverse) {
309 this.reverse = reverse;
310 }
bac9c0df 311
46cc1ade
PT
312 @Override
313 public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) {
314 ThreadEntry t1 = (ThreadEntry) o1;
315 ThreadEntry t2 = (ThreadEntry) o2;
316 return reverse ? Long.compare(t2.getThreadId(), t1.getThreadId()) :
bac9c0df 317 Long.compare(t1.getThreadId(), t2.getThreadId());
46cc1ade
PT
318 }
319 }
320
321 private class ThreadTimeComparator implements Comparator<ITimeGraphEntry> {
322 private boolean reverse;
bac9c0df 323
46cc1ade
PT
324 public ThreadTimeComparator(boolean reverse) {
325 this.reverse = reverse;
326 }
bac9c0df 327
46cc1ade
PT
328 @Override
329 public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) {
330 return reverse ? Long.compare(o2.getStartTime(), o1.getStartTime()) :
bac9c0df 331 Long.compare(o1.getStartTime(), o2.getStartTime());
46cc1ade
PT
332 }
333 }
334
e8251298
PT
335 private class TreeContentProvider implements ITreeContentProvider {
336
337 @Override
338 public void dispose() {
339 }
340
341 @Override
342 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
343 }
344
345 @Override
346 public Object[] getElements(Object inputElement) {
26c33ee2
PT
347 if (inputElement != null) {
348 try {
349 return ((List<?>) inputElement).toArray(new ITimeGraphEntry[0]);
350 } catch (ClassCastException e) {
351 }
352 }
353 return new ITimeGraphEntry[0];
e8251298
PT
354 }
355
356 @Override
357 public Object[] getChildren(Object parentElement) {
358 ITimeGraphEntry entry = (ITimeGraphEntry) parentElement;
359 return entry.getChildren().toArray();
360 }
361
362 @Override
363 public Object getParent(Object element) {
364 ITimeGraphEntry entry = (ITimeGraphEntry) element;
365 return entry.getParent();
366 }
367
368 @Override
369 public boolean hasChildren(Object element) {
370 ITimeGraphEntry entry = (ITimeGraphEntry) element;
371 return entry.hasChildren();
372 }
373
374 }
375
376 private class TreeLabelProvider implements ITableLabelProvider {
377
378 @Override
379 public void addListener(ILabelProviderListener listener) {
380 }
381
382 @Override
383 public void dispose() {
384 }
385
386 @Override
387 public boolean isLabelProperty(Object element, String property) {
388 return false;
389 }
390
391 @Override
392 public void removeListener(ILabelProviderListener listener) {
393 }
394
395 @Override
396 public Image getColumnImage(Object element, int columnIndex) {
397 if (columnIndex == 0) {
398 if (element instanceof ThreadEntry) {
399 return THREAD_IMAGE;
400 } else if (element instanceof CallStackEntry) {
401 CallStackEntry entry = (CallStackEntry) element;
402 if (entry.getFunctionName().length() > 0) {
403 return STACKFRAME_IMAGE;
404 }
405 }
406 }
407 return null;
408 }
409
410 @Override
411 public String getColumnText(Object element, int columnIndex) {
60b4d44c 412 if (element instanceof CallStackEntry) {
e8251298
PT
413 CallStackEntry entry = (CallStackEntry) element;
414 if (columnIndex == 0) {
415 return entry.getFunctionName();
52974e38
PT
416 } else if (columnIndex == 1 && entry.getFunctionName().length() > 0) {
417 int depth = entry.getStackLevel();
418 return Integer.toString(depth);
419 } else if (columnIndex == 2 && entry.getFunctionName().length() > 0) {
60b4d44c 420 ITmfTimestamp ts = new TmfTimestamp(entry.getFunctionEntryTime(), ITmfTimestamp.NANOSECOND_SCALE);
52974e38
PT
421 return ts.toString();
422 } else if (columnIndex == 3 && entry.getFunctionName().length() > 0) {
60b4d44c 423 ITmfTimestamp ts = new TmfTimestamp(entry.getFunctionExitTime(), ITmfTimestamp.NANOSECOND_SCALE);
52974e38
PT
424 return ts.toString();
425 } else if (columnIndex == 4 && entry.getFunctionName().length() > 0) {
60b4d44c 426 ITmfTimestamp ts = new TmfTimestampDelta(entry.getFunctionExitTime() - entry.getFunctionEntryTime(), ITmfTimestamp.NANOSECOND_SCALE);
52974e38 427 return ts.toString();
e8251298 428 }
60b4d44c
PT
429 } else if (element instanceof ITimeGraphEntry) {
430 if (columnIndex == 0) {
431 return ((ITimeGraphEntry) element).getName();
432 }
e8251298
PT
433 }
434 return ""; //$NON-NLS-1$
435 }
436
437 }
438
26c33ee2
PT
439 private class TimeGraphContentProvider implements ITimeGraphContentProvider {
440
441 @Override
442 public ITimeGraphEntry[] getElements(Object inputElement) {
443 if (inputElement != null) {
444 try {
445 return ((List<?>) inputElement).toArray(new ITimeGraphEntry[0]);
446 } catch (ClassCastException e) {
447 }
448 }
449 return new ITimeGraphEntry[0];
450 }
451
452 }
453
e8251298
PT
454 private class BuildThread extends Thread {
455 private final ITmfTrace fBuildTrace;
26c33ee2 456 private final ITmfTrace fParentTrace;
e8251298
PT
457 private final IProgressMonitor fMonitor;
458
26c33ee2 459 public BuildThread(ITmfTrace trace, ITmfTrace parentTrace) {
e8251298
PT
460 super("CallStackView build"); //$NON-NLS-1$
461 fBuildTrace = trace;
26c33ee2 462 fParentTrace = parentTrace;
e8251298
PT
463 fMonitor = new NullProgressMonitor();
464 }
465
466 @Override
467 public void run() {
26c33ee2 468 buildThreadList(fBuildTrace, fParentTrace, fMonitor);
e8251298 469 synchronized (fBuildThreadMap) {
26c33ee2 470 fBuildThreadMap.remove(fBuildTrace);
e8251298
PT
471 }
472 }
473
474 public void cancel() {
475 fMonitor.setCanceled(true);
476 }
477 }
478
479 private class ZoomThread extends Thread {
60b4d44c 480 private final List<TraceEntry> fZoomEntryList;
e8251298
PT
481 private final long fZoomStartTime;
482 private final long fZoomEndTime;
483 private final IProgressMonitor fMonitor;
484
60b4d44c
PT
485 public ZoomThread(List<TraceEntry> entryList, long startTime, long endTime) {
486 super("CallStackView zoom"); //$NON-NLS-1$
e8251298
PT
487 fZoomEntryList = entryList;
488 fZoomStartTime = startTime;
489 fZoomEndTime = endTime;
490 fMonitor = new NullProgressMonitor();
491 }
492
493 @Override
494 public void run() {
495 if (fZoomEntryList == null) {
496 return;
497 }
498 long resolution = Math.max(1, (fZoomEndTime - fZoomStartTime) / fDisplayWidth);
60b4d44c
PT
499 for (TraceEntry traceEntry : fZoomEntryList) {
500 for (ITimeGraphEntry threadEntry : traceEntry.getChildren()) {
501 ITmfStateSystem ss = ((ThreadEntry) threadEntry).getStateSystem();
502 if (ss == null) {
503 continue;
e8251298 504 }
60b4d44c
PT
505 ss.waitUntilBuilt();
506 if (ss.isCancelled()) {
507 continue;
508 }
509 for (ITimeGraphEntry child : threadEntry.getChildren()) {
510 if (fMonitor.isCanceled()) {
511 break;
512 }
513 CallStackEntry entry = (CallStackEntry) child;
514 if (fZoomStartTime <= fStartTime && fZoomEndTime >= fEndTime) {
515 entry.setZoomedEventList(null);
516 } else {
517 List<ITimeEvent> zoomedEventList = getEventList(entry, fZoomStartTime, fZoomEndTime, resolution, fMonitor);
518 if (zoomedEventList != null) {
519 entry.setZoomedEventList(zoomedEventList);
520 }
e8251298 521 }
60b4d44c 522 redraw();
e8251298 523 }
e8251298
PT
524 }
525 }
526 }
527
528 public void cancel() {
529 fMonitor.setCanceled(true);
530 }
531 }
532
533 // ------------------------------------------------------------------------
534 // Constructors
535 // ------------------------------------------------------------------------
536
537 /**
538 * Default constructor
539 */
540 public CallStackView() {
541 super(ID);
542 fDisplayWidth = Display.getDefault().getBounds().width;
543 }
544
545 // ------------------------------------------------------------------------
546 // ViewPart
547 // ------------------------------------------------------------------------
548
549 @Override
550 public void createPartControl(Composite parent) {
551 fTimeGraphCombo = new TimeGraphCombo(parent, SWT.NONE);
552
553 fTimeGraphCombo.setTreeContentProvider(new TreeContentProvider());
554
555 fTimeGraphCombo.setTreeLabelProvider(new TreeLabelProvider());
556
46cc1ade 557 fTimeGraphCombo.setTreeColumns(COLUMN_TIMES);
e8251298 558
52974e38
PT
559 fTimeGraphCombo.getTreeViewer().getTree().getColumn(0).setWidth(COLUMN_WIDTHS[0]);
560 fTimeGraphCombo.getTreeViewer().getTree().getColumn(1).setWidth(COLUMN_WIDTHS[1]);
561 fTimeGraphCombo.getTreeViewer().getTree().getColumn(2).setWidth(COLUMN_WIDTHS[2]);
562 fTimeGraphCombo.getTreeViewer().getTree().getColumn(3).setWidth(COLUMN_WIDTHS[3]);
563 fTimeGraphCombo.getTreeViewer().getTree().getColumn(4).setWidth(COLUMN_WIDTHS[4]);
e8251298 564
26c33ee2 565 fTimeGraphCombo.setTimeGraphContentProvider(new TimeGraphContentProvider());
5da83da5 566 fTimeGraphCombo.setTimeGraphProvider(new CallStackPresentationProvider(this));
e8251298
PT
567 fTimeGraphCombo.getTimeGraphViewer().setTimeFormat(TimeFormat.CALENDAR);
568
569 fTimeGraphCombo.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
570 @Override
571 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {
572 long startTime = event.getStartTime();
573 long endTime = event.getEndTime();
f566d40a 574 TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime));
0fcf3b09 575 broadcast(new TmfRangeSynchSignal(CallStackView.this, range));
e8251298
PT
576 startZoomThread(startTime, endTime);
577 }
578 });
579
580 fTimeGraphCombo.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
581 @Override
582 public void timeSelected(TimeGraphTimeEvent event) {
0fcf3b09
PT
583 long beginTime = event.getBeginTime();
584 long endTime = event.getEndTime();
26c33ee2 585 synchingToTime(beginTime);
f566d40a 586 broadcast(new TmfTimeSynchSignal(CallStackView.this, new TmfNanoTimestamp(beginTime), new TmfNanoTimestamp(endTime)));
e8251298
PT
587 }
588 });
589
590 fTimeGraphCombo.getTimeGraphViewer().getControl().addControlListener(new ControlAdapter() {
591 @Override
592 public void controlResized(ControlEvent e) {
593 fDisplayWidth = fTimeGraphCombo.getTimeGraphViewer().getControl().getSize().x;
594 if (fEntryList != null) {
595 startZoomThread(fTimeGraphCombo.getTimeGraphViewer().getTime0(), fTimeGraphCombo.getTimeGraphViewer().getTime1());
596 }
597 }
598 });
599
600 fTimeGraphCombo.getTreeViewer().addDoubleClickListener(new IDoubleClickListener() {
601 @Override
602 public void doubleClick(DoubleClickEvent event) {
603 Object selection = ((IStructuredSelection) event.getSelection()).getFirstElement();
604 if (selection instanceof CallStackEntry) {
605 CallStackEntry entry = (CallStackEntry) selection;
606 if (entry.getFunctionName().length() > 0) {
60b4d44c
PT
607 long entryTime = entry.getFunctionEntryTime();
608 long exitTime = entry.getFunctionExitTime();
609 long spacingTime = (long) ((exitTime - entryTime) * SPACING_RATIO);
610 entryTime -= spacingTime;
611 exitTime += spacingTime;
612 TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(entryTime), new TmfNanoTimestamp(exitTime));
0fcf3b09 613 broadcast(new TmfRangeSynchSignal(CallStackView.this, range));
60b4d44c
PT
614 fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(entryTime, exitTime);
615 startZoomThread(entryTime, exitTime);
e8251298
PT
616 }
617 }
618 }
619 });
620
621 fTimeGraphCombo.getTimeGraphViewer().getTimeGraphControl().addMouseListener(new MouseAdapter() {
622 @Override
623 public void mouseDoubleClick(MouseEvent e) {
624 TimeGraphControl timeGraphControl = fTimeGraphCombo.getTimeGraphViewer().getTimeGraphControl();
625 ISelection selection = timeGraphControl.getSelection();
626 if (selection instanceof TimeGraphSelection) {
627 Object o = ((TimeGraphSelection) selection).getFirstElement();
628 if (o instanceof CallStackEvent) {
629 CallStackEvent event = (CallStackEvent) o;
630 long startTime = event.getTime();
631 long endTime = startTime + event.getDuration();
52974e38 632 long spacingTime = (long) ((endTime - startTime) * SPACING_RATIO);
e8251298
PT
633 startTime -= spacingTime;
634 endTime += spacingTime;
f566d40a 635 TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime));
0fcf3b09 636 broadcast(new TmfRangeSynchSignal(CallStackView.this, range));
e8251298
PT
637 fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
638 startZoomThread(startTime, endTime);
639 }
640 }
641 }
642 });
643
0fcf3b09
PT
644 IStatusLineManager statusLineManager = getViewSite().getActionBars().getStatusLineManager();
645 fTimeGraphCombo.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager);
646
e8251298
PT
647 // View Action Handling
648 makeActions();
649 contributeToActionBars();
46cc1ade
PT
650 createContextMenu();
651 loadSortOption();
e8251298
PT
652
653 IEditorPart editor = getSite().getPage().getActiveEditor();
654 if (editor instanceof ITmfTraceEditor) {
655 ITmfTrace trace = ((ITmfTraceEditor) editor).getTrace();
656 if (trace != null) {
657 traceSelected(new TmfTraceSelectedSignal(this, trace));
658 }
659 }
660 }
661
662 @Override
663 public void setFocus() {
664 fTimeGraphCombo.setFocus();
665 }
666
667 // ------------------------------------------------------------------------
668 // Signal handlers
669 // ------------------------------------------------------------------------
fec1ac0b
BH
670 /**
671 * Handler for the trace opened signal.
bac9c0df 672 *
fec1ac0b
BH
673 * @param signal
674 * The incoming signal
675 * @since 2.0
676 */
677 @TmfSignalHandler
678 public void traceOpened(TmfTraceOpenedSignal signal) {
679 fTrace = signal.getTrace();
680 loadTrace();
681 }
e8251298
PT
682
683 /**
684 * Handler for the trace selected signal
685 *
686 * @param signal
687 * The incoming signal
688 */
689 @TmfSignalHandler
690 public void traceSelected(final TmfTraceSelectedSignal signal) {
691 if (signal.getTrace() == fTrace) {
692 return;
693 }
694 fTrace = signal.getTrace();
fec1ac0b 695 loadTrace();
e8251298
PT
696 }
697
698 /**
699 * Trace is closed: clear the data structures and the view
700 *
bac9c0df
MK
701 * @param signal
702 * the signal received
e8251298
PT
703 */
704 @TmfSignalHandler
705 public void traceClosed(final TmfTraceClosedSignal signal) {
706 synchronized (fBuildThreadMap) {
26c33ee2
PT
707 ITmfTrace[] traces = TmfTraceManager.getTraceSet(signal.getTrace());
708 for (ITmfTrace trace : traces) {
709 BuildThread buildThread = fBuildThreadMap.remove(trace);
710 if (buildThread != null) {
711 buildThread.cancel();
712 }
e8251298
PT
713 }
714 }
715 synchronized (fEntryListMap) {
716 fEntryListMap.remove(signal.getTrace());
717 }
718 fSelectedThreadMap.remove(signal.getTrace());
719 if (signal.getTrace() == fTrace) {
720 fTrace = null;
721 fStartTime = 0;
722 fEndTime = 0;
723 refresh();
724 }
725 }
726
727 /**
728 * Handler for the TimeSynch signal
729 *
730 * @param signal
731 * The incoming signal
732 */
733 @TmfSignalHandler
734 public void synchToTime(final TmfTimeSynchSignal signal) {
735
0fcf3b09 736 fSavedTimeSyncSignal = isPinned() ? new TmfTimeSynchSignal(signal.getSource(), signal.getBeginTime(), signal.getEndTime()) : null;
e8251298
PT
737
738 if (signal.getSource() == this || fTrace == null || isPinned()) {
739 return;
740 }
0fcf3b09
PT
741 final long beginTime = signal.getBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
742 final long endTime = signal.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
e8251298
PT
743 Display.getDefault().asyncExec(new Runnable() {
744 @Override
745 public void run() {
746 if (fTimeGraphCombo.isDisposed()) {
747 return;
748 }
0fcf3b09
PT
749 if (beginTime == endTime) {
750 fTimeGraphCombo.getTimeGraphViewer().setSelectedTime(beginTime, true);
751 } else {
752 fTimeGraphCombo.getTimeGraphViewer().setSelectionRange(beginTime, endTime);
753 }
26c33ee2 754 synchingToTime(beginTime);
e8251298
PT
755 startZoomThread(fTimeGraphCombo.getTimeGraphViewer().getTime0(), fTimeGraphCombo.getTimeGraphViewer().getTime1());
756 if (fEntryList == null) {
757 return;
758 }
759 TimeGraphViewer viewer = fTimeGraphCombo.getTimeGraphViewer();
60b4d44c
PT
760 for (TraceEntry traceEntry : fEntryList) {
761 for (ITimeGraphEntry child : traceEntry.getChildren()) {
762 ThreadEntry threadEntry = (ThreadEntry) child;
763 ITmfStateSystem ss = threadEntry.getStateSystem();
764 if (ss == null || beginTime < ss.getStartTime() || beginTime > ss.getCurrentEndTime()) {
765 continue;
766 }
767 try {
768 int quark = threadEntry.getCallStackQuark();
769 ITmfStateInterval stackInterval = ss.querySingleState(beginTime, quark);
770 if (beginTime == stackInterval.getStartTime()) {
771 int stackLevel = stackInterval.getStateValue().unboxInt();
772 ITimeGraphEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
773 fTimeGraphCombo.setSelection(selectedEntry);
774 viewer.getTimeGraphControl().fireSelectionChanged();
775 break;
776 }
bac9c0df 777 } catch (AttributeNotFoundException | TimeRangeException | StateSystemDisposedException | StateValueTypeException e) {
60b4d44c 778 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
e8251298 779 }
e8251298
PT
780 }
781 }
782 }
783 });
784 }
785
786 /**
787 * Handler for the RangeSynch signal
788 *
789 * @param signal
790 * The incoming signal
791 */
792 @TmfSignalHandler
793 public void synchToRange(final TmfRangeSynchSignal signal) {
794
795 if (isPinned()) {
796 fSavedRangeSyncSignal =
0fcf3b09 797 new TmfRangeSynchSignal(signal.getSource(), new TmfTimeRange(signal.getCurrentRange().getStartTime(), signal.getCurrentRange().getEndTime()));
e8251298
PT
798
799 fSavedTimeSyncSignal = null;
800 }
801
802 if (signal.getSource() == this || fTrace == null || isPinned()) {
803 return;
804 }
805 if (signal.getCurrentRange().getIntersection(fTrace.getTimeRange()) == null) {
806 return;
807 }
808 final long startTime = signal.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
809 final long endTime = signal.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
e8251298
PT
810 Display.getDefault().asyncExec(new Runnable() {
811 @Override
812 public void run() {
813 if (fTimeGraphCombo.isDisposed()) {
814 return;
815 }
816 fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
e8251298
PT
817 startZoomThread(startTime, endTime);
818 }
819 });
820 }
821
822 // ------------------------------------------------------------------------
823 // Internal
824 // ------------------------------------------------------------------------
5da83da5 825
fec1ac0b
BH
826 private void loadTrace() {
827 synchronized (fEntryListMap) {
828 fEntryList = fEntryListMap.get(fTrace);
829 if (fEntryList == null) {
26c33ee2
PT
830 fStartTime = Long.MAX_VALUE;
831 fEndTime = Long.MIN_VALUE;
fec1ac0b 832 synchronized (fBuildThreadMap) {
26c33ee2
PT
833 ITmfTrace[] traces = TmfTraceManager.getTraceSet(fTrace);
834 for (ITmfTrace trace : traces) {
835 BuildThread buildThread = new BuildThread(trace, fTrace);
836 fBuildThreadMap.put(trace, buildThread);
837 buildThread.start();
838 }
fec1ac0b
BH
839 }
840 } else {
841 fStartTime = fTrace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
842 fEndTime = fTrace.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
843 refresh();
844 }
845 }
846 }
e8251298 847
26c33ee2
PT
848 private void buildThreadList(final ITmfTrace trace, final ITmfTrace parentTrace, IProgressMonitor monitor) {
849 if (monitor.isCanceled()) {
850 return;
851 }
852 AbstractCallStackAnalysis module = getCallStackModule(trace);
853 if (module == null) {
854 addUnavailableEntry(trace, parentTrace);
855 return;
856 }
857 ITmfStateSystem ss = module.getStateSystem();
858 if (ss == null) {
859 addUnavailableEntry(trace, parentTrace);
860 return;
861 }
862
863 Map<ITmfTrace, TraceEntry> traceEntryMap = new HashMap<>();
864 Map<Integer, ThreadEntry> threadEntryMap = new HashMap<>();
865 String[] threadPaths = module.getThreadsPattern();
866
867 long start = ss.getStartTime();
868
869 boolean complete = false;
870 while (!complete) {
e8251298
PT
871 if (monitor.isCanceled()) {
872 return;
873 }
26c33ee2
PT
874 complete = ss.waitUntilBuilt(BUILD_UPDATE_TIMEOUT);
875 if (ss.isCancelled()) {
da27e43a
PT
876 return;
877 }
26c33ee2
PT
878 long end = ss.getCurrentEndTime();
879 if (start == end && !complete) { // when complete execute one last time regardless of end time
e8251298
PT
880 continue;
881 }
da27e43a 882 List<Integer> threadQuarks = ss.getQuarks(threadPaths);
26c33ee2
PT
883 TraceEntry traceEntry = traceEntryMap.get(trace);
884 if (traceEntry == null) {
885 traceEntry = new TraceEntry(trace.getName(), start, end + 1);
886 traceEntryMap.put(trace, traceEntry);
887 traceEntry.sortChildren(fThreadComparator);
888 addToEntryList(parentTrace, Collections.singletonList(traceEntry));
889 } else {
890 traceEntry.updateEndTime(end);
891 }
e8251298
PT
892 for (int i = 0; i < threadQuarks.size(); i++) {
893 if (monitor.isCanceled()) {
894 return;
895 }
896 int threadQuark = threadQuarks.get(i);
e8251298 897 try {
da27e43a
PT
898 String[] callStackPath = module.getCallStackPath();
899 int callStackQuark = ss.getQuarkRelative(threadQuark, callStackPath);
60b4d44c 900 String threadName = ss.getAttributeName(threadQuark);
26c33ee2 901 long threadEnd = end + 1;
46cc1ade 902 ITmfStateInterval endInterval = ss.querySingleState(ss.getCurrentEndTime(), callStackQuark);
26c33ee2
PT
903 if (endInterval.getStateValue().isNull() && endInterval.getStartTime() != ss.getStartTime()) {
904 threadEnd = endInterval.getStartTime();
905 }
906 ThreadEntry threadEntry = threadEntryMap.get(threadQuark);
907 if (threadEntry == null) {
908 long threadId = ss.querySingleState(ss.getCurrentEndTime(), threadQuark).getStateValue().unboxLong();
909 long threadStart = start;
910 ITmfStateInterval startInterval = ss.querySingleState(start, callStackQuark);
911 if (startInterval.getStateValue().isNull()) {
912 threadStart = Math.min(startInterval.getEndTime() + 1, end + 1);
913 }
914 threadEntry = new ThreadEntry(ss, threadName, threadId, callStackQuark, threadStart, threadEnd);
915 threadEntryMap.put(threadQuark, threadEntry);
916 traceEntry.addChild(threadEntry);
917 } else {
918 threadEntry.updateEndTime(threadEnd);
46cc1ade 919 }
e8251298 920 int level = 1;
da27e43a 921 for (int stackLevelQuark : ss.getSubAttributes(callStackQuark, false)) {
26c33ee2
PT
922 if (level > threadEntry.getChildren().size()) {
923 CallStackEntry callStackEntry = new CallStackEntry(threadName, stackLevelQuark, level, trace, ss);
924 threadEntry.addChild(callStackEntry);
925 }
926 level++;
e8251298
PT
927 }
928 } catch (AttributeNotFoundException e) {
52974e38 929 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
46cc1ade
PT
930 } catch (StateSystemDisposedException e) {
931 /* Ignored */
e8251298
PT
932 }
933 }
26c33ee2
PT
934 if (parentTrace == fTrace) {
935 synchronized (fEntryListMap) {
936 fStartTime = Math.min(fStartTime, start);
937 fEndTime = Math.max(fEndTime, end + 1);
938 }
939 refresh();
940 }
60b4d44c
PT
941 for (ITimeGraphEntry threadEntry : traceEntry.getChildren()) {
942 for (ITimeGraphEntry callStackEntry : threadEntry.getChildren()) {
943 if (monitor.isCanceled()) {
944 return;
945 }
26c33ee2 946 buildStatusEvents(parentTrace, (CallStackEntry) callStackEntry, monitor, start, end);
e8251298 947 }
e8251298 948 }
26c33ee2 949 start = end;
e8251298
PT
950 }
951 }
952
26c33ee2
PT
953 private void addToEntryList(ITmfTrace trace, List<TraceEntry> list) {
954 synchronized (fEntryListMap) {
955 List<TraceEntry> entryList = fEntryListMap.get(trace);
956 if (entryList == null) {
957 fEntryListMap.put(trace, new CopyOnWriteArrayList<>(list));
958 } else {
959 entryList.addAll(list);
960 }
961 }
962 }
963
964 private void addUnavailableEntry(ITmfTrace trace, ITmfTrace parentTrace) {
60b4d44c
PT
965 String name = Messages.CallStackView_StackInfoNotAvailable + ' ' + '(' + trace.getName() + ')';
966 TraceEntry unavailableEntry = new TraceEntry(name, 0, 0);
26c33ee2
PT
967 addToEntryList(parentTrace, Collections.singletonList(unavailableEntry));
968 if (parentTrace == fTrace) {
969 refresh();
970 }
2002c638
AM
971 }
972
26c33ee2 973 private void buildStatusEvents(ITmfTrace trace, CallStackEntry entry, IProgressMonitor monitor, long start, long end) {
da27e43a 974 ITmfStateSystem ss = entry.getStateSystem();
26c33ee2
PT
975 long resolution = Math.max(1, (end - ss.getStartTime()) / fDisplayWidth);
976 List<ITimeEvent> eventList = getEventList(entry, start, end + 1, resolution, monitor);
977 if (eventList != null) {
978 for (ITimeEvent event : eventList) {
979 entry.addEvent(event);
980 }
e8251298 981 }
e8251298
PT
982 if (trace == fTrace) {
983 redraw();
984 }
985 }
986
987 private static List<ITimeEvent> getEventList(CallStackEntry entry,
988 long startTime, long endTime, long resolution,
989 IProgressMonitor monitor) {
da27e43a 990 ITmfStateSystem ss = entry.getStateSystem();
e8251298
PT
991 long start = Math.max(startTime, ss.getStartTime());
992 long end = Math.min(endTime, ss.getCurrentEndTime() + 1);
993 if (end <= start) {
994 return null;
995 }
996 List<ITimeEvent> eventList = null;
997 try {
998 List<ITmfStateInterval> stackIntervals = ss.queryHistoryRange(entry.getQuark(), start, end - 1, resolution, monitor);
507b1336 999 eventList = new ArrayList<>(stackIntervals.size());
e8251298
PT
1000 long lastEndTime = -1;
1001 boolean lastIsNull = true;
1002 for (ITmfStateInterval statusInterval : stackIntervals) {
1003 if (monitor.isCanceled()) {
1004 return null;
1005 }
1006 long time = statusInterval.getStartTime();
1007 long duration = statusInterval.getEndTime() - time + 1;
1008 if (!statusInterval.getStateValue().isNull()) {
52974e38
PT
1009 final int modulo = CallStackPresentationProvider.NUM_COLORS / 2;
1010 int value = statusInterval.getStateValue().toString().hashCode() % modulo + modulo;
e8251298
PT
1011 eventList.add(new CallStackEvent(entry, time, duration, value));
1012 lastIsNull = false;
1013 } else {
beb1b921
PT
1014 if (lastEndTime == -1) {
1015 // add null event if it intersects the start time
1016 eventList.add(new NullTimeEvent(entry, time, duration));
1017 } else {
1018 if (lastEndTime != time && lastIsNull) {
1019 // add unknown event if between two null states
1020 eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
1021 }
1022 if (time + duration >= endTime) {
1023 // add null event if it intersects the end time
1024 eventList.add(new NullTimeEvent(entry, time, duration));
1025 }
e8251298 1026 }
e8251298
PT
1027 lastIsNull = true;
1028 }
1029 lastEndTime = time + duration;
1030 }
1031 } catch (AttributeNotFoundException e) {
52974e38 1032 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
e8251298 1033 } catch (TimeRangeException e) {
52974e38 1034 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
e8251298
PT
1035 } catch (StateSystemDisposedException e) {
1036 /* Ignored */
1037 }
1038 return eventList;
1039 }
1040
26c33ee2 1041 private void synchingToTime(long time) {
e8251298
PT
1042 if (fEntryList == null) {
1043 return;
1044 }
60b4d44c
PT
1045 for (TraceEntry traceEntry : fEntryList) {
1046 for (ITimeGraphEntry threadEntry : traceEntry.getChildren()) {
1047 ITmfStateSystem ss = ((ThreadEntry) threadEntry).getStateSystem();
1048 if (ss == null) {
1049 continue;
1050 }
60b4d44c
PT
1051 if (ss.isCancelled()) {
1052 continue;
1053 }
26c33ee2
PT
1054 if (time < ss.getStartTime() || time > ss.getCurrentEndTime()) {
1055 continue;
1056 }
60b4d44c
PT
1057 for (ITimeGraphEntry child : threadEntry.getChildren()) {
1058 CallStackEntry callStackEntry = (CallStackEntry) child;
e8251298 1059 try {
26c33ee2 1060 ITmfStateInterval stackLevelInterval = ss.querySingleState(time, callStackEntry.getQuark());
60b4d44c
PT
1061 ITmfStateValue nameValue = stackLevelInterval.getStateValue();
1062 String name = ""; //$NON-NLS-1$
1063 try {
1064 if (nameValue.getType() == Type.STRING) {
1065 String address = nameValue.unboxStr();
1066 name = getFunctionName(address);
1067 } else if (nameValue.getType() == Type.INTEGER) {
1068 name = "0x" + Integer.toHexString(nameValue.unboxInt()); //$NON-NLS-1$
1069 } else if (nameValue.getType() == Type.LONG) {
1070 name = "0x" + Long.toHexString(nameValue.unboxLong()); //$NON-NLS-1$
1071 }
1072 } catch (StateValueTypeException e) {
e8251298 1073 }
60b4d44c
PT
1074 callStackEntry.setFunctionName(name);
1075 if (name.length() > 0) {
1076 callStackEntry.setFunctionEntryTime(stackLevelInterval.getStartTime());
1077 callStackEntry.setFunctionExitTime(stackLevelInterval.getEndTime() + 1);
1078 }
1079 } catch (AttributeNotFoundException e) {
1080 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
60b4d44c 1081 } catch (StateSystemDisposedException e) {
26c33ee2 1082 /* Ignored */
e8251298 1083 }
e8251298
PT
1084 }
1085 }
1086 }
1087 fTimeGraphCombo.refresh();
e8251298
PT
1088 }
1089
1090 private void refresh() {
1091 Display.getDefault().asyncExec(new Runnable() {
1092 @Override
1093 public void run() {
1094 if (fTimeGraphCombo.isDisposed()) {
1095 return;
1096 }
e8251298
PT
1097 synchronized (fEntryListMap) {
1098 fEntryList = fEntryListMap.get(fTrace);
1099 if (fEntryList == null) {
507b1336 1100 fEntryList = new ArrayList<>();
e8251298 1101 }
46cc1ade
PT
1102 for (TraceEntry traceEntry : fEntryList) {
1103 traceEntry.sortChildren(fThreadComparator);
1104 }
e8251298 1105 }
26c33ee2
PT
1106 if (fEntryList != fTimeGraphCombo.getInput()) {
1107 fTimeGraphCombo.setInput(fEntryList);
1108 } else {
1109 fTimeGraphCombo.refresh();
1110 }
e8251298
PT
1111 fTimeGraphCombo.getTimeGraphViewer().setTimeBounds(fStartTime, fEndTime);
1112
0fcf3b09
PT
1113 long selectionBeginTime = fTrace == null ? 0 : fTraceManager.getSelectionBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1114 long selectionEndTime = fTrace == null ? 0 : fTraceManager.getSelectionEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
248af329
AM
1115 long startTime = fTrace == null ? 0 : fTraceManager.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1116 long endTime = fTrace == null ? 0 : fTraceManager.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
e8251298
PT
1117 startTime = Math.max(startTime, fStartTime);
1118 endTime = Math.min(endTime, fEndTime);
0fcf3b09 1119 fTimeGraphCombo.getTimeGraphViewer().setSelectionRange(selectionBeginTime, selectionEndTime);
26c33ee2 1120 synchingToTime(selectionBeginTime);
e8251298
PT
1121 fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
1122 startZoomThread(startTime, endTime);
1123 }
1124 });
1125 }
1126
1127 private void redraw() {
1128 synchronized (fSyncObj) {
1129 if (fRedrawState == State.IDLE) {
1130 fRedrawState = State.BUSY;
1131 } else {
1132 fRedrawState = State.PENDING;
1133 return;
1134 }
1135 }
1136 Display.getDefault().asyncExec(new Runnable() {
1137 @Override
1138 public void run() {
1139 if (fTimeGraphCombo.isDisposed()) {
1140 return;
1141 }
1142 fTimeGraphCombo.redraw();
1143 fTimeGraphCombo.update();
1144 synchronized (fSyncObj) {
1145 if (fRedrawState == State.PENDING) {
1146 fRedrawState = State.IDLE;
1147 redraw();
1148 } else {
1149 fRedrawState = State.IDLE;
1150 }
1151 }
1152 }
1153 });
1154 }
1155
1156 private void startZoomThread(long startTime, long endTime) {
1157 if (fZoomThread != null) {
1158 fZoomThread.cancel();
1159 }
1160 fZoomThread = new ZoomThread(fEntryList, startTime, endTime);
1161 fZoomThread.start();
1162 }
1163
1164 private void makeActions() {
1165 fPreviousItemAction = fTimeGraphCombo.getTimeGraphViewer().getPreviousItemAction();
1166 fPreviousItemAction.setText(Messages.TmfTimeGraphViewer_PreviousItemActionNameText);
1167 fPreviousItemAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousItemActionToolTipText);
1168 fNextItemAction = fTimeGraphCombo.getTimeGraphViewer().getNextItemAction();
1169 fNextItemAction.setText(Messages.TmfTimeGraphViewer_NextItemActionNameText);
1170 fNextItemAction.setToolTipText(Messages.TmfTimeGraphViewer_NextItemActionToolTipText);
1171 }
1172
1173 private void contributeToActionBars() {
1174 IActionBars bars = getViewSite().getActionBars();
1175 fillLocalToolBar(bars.getToolBarManager());
1176
1177 // Create pin action
1178 contributePinActionToToolBar();
bac9c0df 1179 fPinAction.addPropertyChangeListener(new IPropertyChangeListener() {
e8251298
PT
1180 @Override
1181 public void propertyChange(PropertyChangeEvent event) {
52974e38
PT
1182 if (IAction.CHECKED.equals(event.getProperty()) && !isPinned()) {
1183 if (fSavedRangeSyncSignal != null) {
1184 synchToRange(fSavedRangeSyncSignal);
1185 fSavedRangeSyncSignal = null;
1186 }
e8251298 1187
52974e38
PT
1188 if (fSavedTimeSyncSignal != null) {
1189 synchToTime(fSavedTimeSyncSignal);
1190 fSavedTimeSyncSignal = null;
e8251298
PT
1191 }
1192 }
1193 }
1194 });
1195 }
1196
1197 private void fillLocalToolBar(IToolBarManager manager) {
41d9ce5b 1198 manager.add(getImportBinaryAction());
5da83da5 1199 manager.add(getImportMappingAction());
46cc1ade
PT
1200 manager.add(new Separator());
1201 manager.add(getSortByNameAction());
1202 manager.add(getSortByIdAction());
1203 manager.add(getSortByTimeAction());
1204 manager.add(new Separator());
e8251298
PT
1205 manager.add(fTimeGraphCombo.getTimeGraphViewer().getResetScaleAction());
1206 manager.add(getPreviousEventAction());
1207 manager.add(getNextEventAction());
1208 manager.add(fPreviousItemAction);
1209 manager.add(fNextItemAction);
1210 manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomInAction());
1211 manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomOutAction());
1212 manager.add(new Separator());
1213 }
1214
46cc1ade
PT
1215 private void createContextMenu() {
1216 final MenuManager contextMenu = new MenuManager();
1217 contextMenu.add(getSortByNameAction());
1218 contextMenu.add(getSortByIdAction());
1219 contextMenu.add(getSortByTimeAction());
1220
1221 Tree tree = fTimeGraphCombo.getTreeViewer().getTree();
1222 Menu menu = contextMenu.createContextMenu(tree);
1223 tree.setMenu(menu);
1224 }
1225
e8251298
PT
1226 /**
1227 * Get the the next event action.
1228 *
1229 * @return The action object
1230 */
1231 private Action getNextEventAction() {
1232 if (fNextEventAction == null) {
1233 fNextEventAction = new Action() {
1234 @Override
1235 public void run() {
1236 TimeGraphViewer viewer = fTimeGraphCombo.getTimeGraphViewer();
1237 ITimeGraphEntry entry = viewer.getSelection();
1238 if (entry instanceof CallStackEntry) {
1239 try {
1240 CallStackEntry callStackEntry = (CallStackEntry) entry;
da27e43a 1241 ITmfStateSystem ss = callStackEntry.getStateSystem();
0fcf3b09 1242 long time = Math.max(ss.getStartTime(), Math.min(ss.getCurrentEndTime(), viewer.getSelectionBegin()));
e8251298 1243 ThreadEntry threadEntry = (ThreadEntry) callStackEntry.getParent();
da27e43a 1244 int quark = ss.getParentAttributeQuark(callStackEntry.getQuark());
e8251298
PT
1245 ITmfStateInterval stackInterval = ss.querySingleState(time, quark);
1246 long newTime = stackInterval.getEndTime() + 1;
1247 viewer.setSelectedTimeNotify(newTime, true);
1248 stackInterval = ss.querySingleState(Math.min(ss.getCurrentEndTime(), newTime), quark);
1249 int stackLevel = stackInterval.getStateValue().unboxInt();
a3188982 1250 ITimeGraphEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
e8251298
PT
1251 fTimeGraphCombo.setSelection(selectedEntry);
1252 viewer.getTimeGraphControl().fireSelectionChanged();
1253 startZoomThread(viewer.getTime0(), viewer.getTime1());
50659279 1254
bac9c0df 1255 } catch (AttributeNotFoundException | TimeRangeException | StateSystemDisposedException | StateValueTypeException e) {
52974e38 1256 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
e8251298
PT
1257 }
1258 }
1259 }
1260 };
1261
1262 fNextEventAction.setText(Messages.TmfTimeGraphViewer_NextEventActionNameText);
1263 fNextEventAction.setToolTipText(Messages.TmfTimeGraphViewer_NextEventActionToolTipText);
1264 fNextEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_NEXT_EVENT));
1265 }
1266
1267 return fNextEventAction;
1268 }
1269
1270 /**
1271 * Get the previous event action.
1272 *
1273 * @return The Action object
1274 */
1275 private Action getPreviousEventAction() {
1276 if (fPrevEventAction == null) {
1277 fPrevEventAction = new Action() {
1278 @Override
1279 public void run() {
1280 TimeGraphViewer viewer = fTimeGraphCombo.getTimeGraphViewer();
1281 ITimeGraphEntry entry = viewer.getSelection();
1282 if (entry instanceof CallStackEntry) {
1283 try {
1284 CallStackEntry callStackEntry = (CallStackEntry) entry;
da27e43a 1285 ITmfStateSystem ss = callStackEntry.getStateSystem();
0fcf3b09 1286 long time = Math.max(ss.getStartTime(), Math.min(ss.getCurrentEndTime(), viewer.getSelectionBegin()));
e8251298 1287 ThreadEntry threadEntry = (ThreadEntry) callStackEntry.getParent();
da27e43a 1288 int quark = ss.getParentAttributeQuark(callStackEntry.getQuark());
e8251298
PT
1289 ITmfStateInterval stackInterval = ss.querySingleState(time, quark);
1290 if (stackInterval.getStartTime() == time && time > ss.getStartTime()) {
1291 stackInterval = ss.querySingleState(time - 1, quark);
1292 }
1293 viewer.setSelectedTimeNotify(stackInterval.getStartTime(), true);
1294 int stackLevel = stackInterval.getStateValue().unboxInt();
a3188982 1295 ITimeGraphEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
e8251298
PT
1296 fTimeGraphCombo.setSelection(selectedEntry);
1297 viewer.getTimeGraphControl().fireSelectionChanged();
1298 startZoomThread(viewer.getTime0(), viewer.getTime1());
50659279 1299
bac9c0df 1300 } catch (AttributeNotFoundException | TimeRangeException | StateSystemDisposedException | StateValueTypeException e) {
52974e38 1301 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
e8251298
PT
1302 }
1303 }
1304 }
1305 };
1306
1307 fPrevEventAction.setText(Messages.TmfTimeGraphViewer_PreviousEventActionNameText);
1308 fPrevEventAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousEventActionToolTipText);
1309 fPrevEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_PREV_EVENT));
1310 }
1311
1312 return fPrevEventAction;
1313 }
1314
da27e43a 1315 private static @Nullable AbstractCallStackAnalysis getCallStackModule(ITmfTrace trace) {
50659279
AM
1316 /*
1317 * Since we cannot know the exact analysis ID (in separate plugins), we
1318 * will search using the analysis type.
1319 */
1320 Iterable<AbstractCallStackAnalysis> modules =
1321 trace.getAnalysisModulesOfClass(AbstractCallStackAnalysis.class);
1322 Iterator<AbstractCallStackAnalysis> it = modules.iterator();
1323 if (!it.hasNext()) {
1324 /* This trace does not provide a call-stack analysis */
1325 return null;
1326 }
1327
1328 /*
1329 * We only look at the first module we find.
1330 *
1331 * TODO Handle the advanced case where one trace provides more than one
1332 * call-stack analysis.
1333 */
1334 AbstractCallStackAnalysis module = it.next();
1335 /* This analysis is not automatic, we need to schedule it on-demand */
1336 module.schedule();
1337 module.waitForInitialization();
da27e43a 1338 return module;
50659279
AM
1339 }
1340
5da83da5
AM
1341 // ------------------------------------------------------------------------
1342 // Methods related to function name mapping
1343 // ------------------------------------------------------------------------
1344
41d9ce5b
MAL
1345 /**
1346 * Common code for all import file mapping actions
1347 */
1348 private abstract class AbstractImportFileMappingAction extends Action {
1349 private final String fDialogTitle;
1350
1351 private AbstractImportFileMappingAction(String dialogTitle) {
1352 fDialogTitle = dialogTitle;
1353 }
1354
1355 @Override
1356 public void run() {
1357 FileDialog dialog = new FileDialog(getViewSite().getShell());
1358 dialog.setText(fDialogTitle);
1359 final String filePath = dialog.open();
1360 if (filePath == null) {
1361 /* No file was selected, don't change anything */
1362 return;
1363 }
1364
1365 /*
bac9c0df
MK
1366 * Start the mapping import in a separate thread (we do not want to
1367 * UI thread to do this).
41d9ce5b
MAL
1368 */
1369 Job job = new Job(Messages.CallStackView_ImportMappingJobName) {
1370 @Override
1371 public IStatus run(IProgressMonitor monitor) {
1372 fNameMapping = doMapping(new File(filePath));
1373
26c33ee2
PT
1374 /* Refresh call stack entries and event labels */
1375 Display.getDefault().asyncExec(new Runnable() {
1376 @Override
1377 public void run() {
1378 synchingToTime(fTimeGraphCombo.getTimeGraphViewer().getSelectionBegin());
1379 }
1380 });
41d9ce5b
MAL
1381 return Status.OK_STATUS;
1382 }
1383 };
1384 job.schedule();
1385 }
1386
1387 abstract Map<String, String> doMapping(File file);
1388 }
1389
5da83da5
AM
1390 /**
1391 * Toolbar icon to import the function address-to-name mapping file.
1392 */
1393 private Action getImportMappingAction() {
1394 if (fImportMappingAction != null) {
1395 return fImportMappingAction;
1396 }
41d9ce5b 1397 fImportMappingAction = new AbstractImportFileMappingAction(Messages.CallStackView_ImportMappingDialogTitle) {
5da83da5 1398 @Override
41d9ce5b
MAL
1399 Map<String, String> doMapping(File file) {
1400 return FunctionNameMapper.mapFromNmTextFile(file);
5da83da5
AM
1401 }
1402 };
1403
1404 fImportMappingAction.setText(Messages.CallStackView_ImportMappingButtonText);
1405 fImportMappingAction.setToolTipText(Messages.CallStackView_ImportMappingButtonTooltip);
1406 fImportMappingAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(IMPORT_MAPPING_ICON_PATH));
1407
1408 return fImportMappingAction;
1409 }
1410
46cc1ade
PT
1411 private Action getSortByNameAction() {
1412 if (fSortByNameAction == null) {
1413 fSortByNameAction = new Action(Messages.CallStackView_SortByThreadName, IAction.AS_CHECK_BOX) {
1414 @Override
1415 public void run() {
1416 if (fSortOption == SortOption.BY_NAME) {
1417 saveSortOption(SortOption.BY_NAME_REV);
1418 } else {
1419 saveSortOption(SortOption.BY_NAME);
1420 }
1421 }
1422 };
1423 fSortByNameAction.setToolTipText(Messages.CallStackView_SortByThreadName);
6aea3caa 1424 fSortByNameAction.setImageDescriptor(SORT_BY_NAME_ICON);
46cc1ade
PT
1425 }
1426 return fSortByNameAction;
1427 }
1428
1429 private Action getSortByIdAction() {
1430 if (fSortByIdAction == null) {
1431 fSortByIdAction = new Action(Messages.CallStackView_SortByThreadId, IAction.AS_CHECK_BOX) {
1432 @Override
1433 public void run() {
1434 if (fSortOption == SortOption.BY_ID) {
1435 saveSortOption(SortOption.BY_ID_REV);
1436 } else {
1437 saveSortOption(SortOption.BY_ID);
1438 }
1439 }
1440 };
1441 fSortByIdAction.setToolTipText(Messages.CallStackView_SortByThreadId);
6aea3caa 1442 fSortByIdAction.setImageDescriptor(SORT_BY_ID_ICON);
46cc1ade
PT
1443 }
1444 return fSortByIdAction;
1445 }
1446
1447 private Action getSortByTimeAction() {
1448 if (fSortByTimeAction == null) {
1449 fSortByTimeAction = new Action(Messages.CallStackView_SortByThreadTime, IAction.AS_CHECK_BOX) {
1450 @Override
1451 public void run() {
1452 if (fSortOption == SortOption.BY_TIME) {
1453 saveSortOption(SortOption.BY_TIME_REV);
1454 } else {
1455 saveSortOption(SortOption.BY_TIME);
1456 }
1457 }
1458 };
1459 fSortByTimeAction.setToolTipText(Messages.CallStackView_SortByThreadTime);
6aea3caa 1460 fSortByTimeAction.setImageDescriptor(SORT_BY_TIME_ICON);
46cc1ade
PT
1461 }
1462 return fSortByTimeAction;
1463 }
1464
1465 private void loadSortOption() {
1466 IDialogSettings settings = Activator.getDefault().getDialogSettings();
1467 IDialogSettings section = settings.getSection(getClass().getName());
1468 if (section == null) {
1469 return;
1470 }
1471 String sortOption = section.get(SORT_OPTION_KEY);
6aea3caa
PT
1472 if (sortOption == null) {
1473 return;
1474 }
46cc1ade
PT
1475
1476 // reset defaults
1477 getSortByNameAction().setChecked(false);
1478 getSortByNameAction().setImageDescriptor(SORT_BY_NAME_ICON);
1479 getSortByIdAction().setChecked(false);
1480 getSortByIdAction().setImageDescriptor(SORT_BY_ID_ICON);
1481 getSortByTimeAction().setChecked(false);
1482 getSortByTimeAction().setImageDescriptor(SORT_BY_TIME_ICON);
1483
1484 if (sortOption.equals(SortOption.BY_NAME.name())) {
1485 fSortOption = SortOption.BY_NAME;
1486 fThreadComparator = new ThreadNameComparator(false);
1487 getSortByNameAction().setChecked(true);
1488 } else if (sortOption.equals(SortOption.BY_NAME_REV.name())) {
1489 fSortOption = SortOption.BY_NAME_REV;
1490 fThreadComparator = new ThreadNameComparator(true);
1491 getSortByNameAction().setChecked(true);
1492 getSortByNameAction().setImageDescriptor(SORT_BY_NAME_REV_ICON);
1493 } else if (sortOption.equals(SortOption.BY_ID.name())) {
1494 fSortOption = SortOption.BY_ID;
1495 fThreadComparator = new ThreadIdComparator(false);
1496 getSortByIdAction().setChecked(true);
1497 } else if (sortOption.equals(SortOption.BY_ID_REV.name())) {
1498 fSortOption = SortOption.BY_ID_REV;
1499 fThreadComparator = new ThreadIdComparator(true);
1500 getSortByIdAction().setChecked(true);
1501 getSortByIdAction().setImageDescriptor(SORT_BY_ID_REV_ICON);
1502 } else if (sortOption.equals(SortOption.BY_TIME.name())) {
1503 fSortOption = SortOption.BY_TIME;
1504 fThreadComparator = new ThreadTimeComparator(false);
1505 getSortByTimeAction().setChecked(true);
1506 } else if (sortOption.equals(SortOption.BY_TIME_REV.name())) {
1507 fSortOption = SortOption.BY_TIME_REV;
1508 fThreadComparator = new ThreadTimeComparator(true);
1509 getSortByTimeAction().setChecked(true);
1510 getSortByTimeAction().setImageDescriptor(SORT_BY_TIME_REV_ICON);
1511 }
1512 }
1513
1514 private void saveSortOption(SortOption sortOption) {
1515 IDialogSettings settings = Activator.getDefault().getDialogSettings();
1516 IDialogSettings section = settings.getSection(getClass().getName());
1517 if (section == null) {
1518 section = settings.addNewSection(getClass().getName());
1519 }
1520 section.put(SORT_OPTION_KEY, sortOption.name());
1521 loadSortOption();
1522 if (fEntryList == null) {
1523 return;
1524 }
1525 for (TraceEntry traceEntry : fEntryList) {
1526 traceEntry.sortChildren(fThreadComparator);
1527 }
1528 refresh();
1529 }
1530
41d9ce5b
MAL
1531 /**
1532 * Toolbar icon to import the function address-to-name mapping binary file.
1533 */
1534 private Action getImportBinaryAction() {
1535 if (fImportBinaryFileMappingAction != null) {
1536 return fImportBinaryFileMappingAction;
5da83da5
AM
1537 }
1538
41d9ce5b
MAL
1539 fImportBinaryFileMappingAction = new AbstractImportFileMappingAction(Messages.CallStackView_ImportBinaryFileDialogTitle) {
1540 @Override
1541 Map<String, String> doMapping(File file) {
1542 return FunctionNameMapper.mapFromBinaryFile(file);
1543 }
1544 };
5da83da5 1545
41d9ce5b
MAL
1546 fImportBinaryFileMappingAction.setText(Messages.CallStackView_ImportBinaryFileButtonText);
1547 fImportBinaryFileMappingAction.setToolTipText(Messages.CallStackView_ImportBinaryFileButtonTooltip);
1548 fImportBinaryFileMappingAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(IMPORT_BINARY_ICON_PATH));
5da83da5 1549
41d9ce5b 1550 return fImportBinaryFileMappingAction;
5da83da5
AM
1551 }
1552
1553 String getFunctionName(String address) {
1554 if (fNameMapping == null) {
1555 /* No mapping available, just print the addresses */
1556 return address;
1557 }
1558 String ret = fNameMapping.get(address);
1559 if (ret == null) {
bac9c0df
MK
1560 /*
1561 * We didn't find this address in the mapping file, just use the
1562 * address
1563 */
5da83da5
AM
1564 return address;
1565 }
1566 return ret;
1567 }
1568
e8251298 1569}
This page took 0.143927 seconds and 5 git commands to generate.