tmf: Fix unnecessary unknown state at beginning of call stack event list
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / views / callstack / CallStackView.java
CommitLineData
e8251298 1/*******************************************************************************
d2fb9e0f 2 * Copyright (c) 2013, 2016 Ericsson and others.
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
PT
16
17import java.util.ArrayList;
26c33ee2 18import java.util.Collections;
46cc1ade 19import java.util.Comparator;
e8251298
PT
20import java.util.HashMap;
21import java.util.Iterator;
22import java.util.List;
52974e38 23import java.util.Map;
e8251298
PT
24
25import org.eclipse.core.runtime.IProgressMonitor;
1d83ed07 26import org.eclipse.jdt.annotation.NonNull;
50659279 27import org.eclipse.jdt.annotation.Nullable;
e8251298 28import org.eclipse.jface.action.Action;
d2fb9e0f 29import org.eclipse.jface.action.GroupMarker;
e8251298 30import org.eclipse.jface.action.IAction;
90bb3a0c 31import org.eclipse.jface.action.IMenuManager;
e8251298
PT
32import org.eclipse.jface.action.IToolBarManager;
33import org.eclipse.jface.action.Separator;
d90ae2a5 34import org.eclipse.jface.dialogs.IDialogConstants;
46cc1ade
PT
35import org.eclipse.jface.dialogs.IDialogSettings;
36import org.eclipse.jface.resource.ImageDescriptor;
e8251298
PT
37import org.eclipse.jface.util.IPropertyChangeListener;
38import org.eclipse.jface.util.PropertyChangeEvent;
39import org.eclipse.jface.viewers.DoubleClickEvent;
40import org.eclipse.jface.viewers.IDoubleClickListener;
e8251298
PT
41import org.eclipse.jface.viewers.ISelection;
42import org.eclipse.jface.viewers.IStructuredSelection;
e8251298 43import org.eclipse.swt.SWT;
e8251298
PT
44import org.eclipse.swt.events.MouseAdapter;
45import org.eclipse.swt.events.MouseEvent;
46import org.eclipse.swt.graphics.Image;
47import org.eclipse.swt.widgets.Composite;
48import org.eclipse.swt.widgets.Display;
2bdf0193
AM
49import org.eclipse.tracecompass.internal.tmf.ui.Activator;
50import org.eclipse.tracecompass.internal.tmf.ui.ITmfImageConstants;
51import org.eclipse.tracecompass.internal.tmf.ui.Messages;
e894a508 52import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
1dd75589 53import org.eclipse.tracecompass.statesystem.core.StateSystemUtils;
e894a508
AM
54import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
55import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
56import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
57import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
58import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
59import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
60import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue.Type;
97c71024 61import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
17a54620 62import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
d90ae2a5 63import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
2bdf0193 64import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
17a54620 65import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
2bdf0193 66import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
2bdf0193 67import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
b2c971ec 68import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
e4bbed4b 69import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampDelta;
2bdf0193 70import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
b8585c7c 71import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
2bdf0193 72import org.eclipse.tracecompass.tmf.ui.editors.ITmfTraceEditor;
d90ae2a5
RK
73import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProvider;
74import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProviderPreferencePage;
75import org.eclipse.tracecompass.tmf.ui.symbols.SymbolProviderConfigDialog;
76import org.eclipse.tracecompass.tmf.ui.symbols.SymbolProviderManager;
ade0a3c5 77import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractTimeGraphView;
2bdf0193 78import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
d8a230f8 79import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphContentProvider;
2bdf0193
AM
80import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
81import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphViewer;
82import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
83import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
84import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent;
85import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
86import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
87import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl;
88import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphSelection;
e8251298 89import org.eclipse.ui.IEditorPart;
d2fb9e0f 90import org.eclipse.ui.IWorkbenchActionConstants;
e8251298
PT
91
92/**
93 * Main implementation for the Call Stack view
94 *
95 * @author Patrick Tasse
e8251298 96 */
ade0a3c5 97public class CallStackView extends AbstractTimeGraphView {
e8251298
PT
98
99 // ------------------------------------------------------------------------
100 // Constants
101 // ------------------------------------------------------------------------
102
103 /** View ID. */
104 public static final String ID = "org.eclipse.linuxtools.tmf.ui.views.callstack"; //$NON-NLS-1$
105
ade0a3c5 106 private static final String[] COLUMN_NAMES = new String[] {
e8251298
PT
107 Messages.CallStackView_FunctionColumn,
108 Messages.CallStackView_DepthColumn,
109 Messages.CallStackView_EntryTimeColumn,
110 Messages.CallStackView_ExitTimeColumn,
111 Messages.CallStackView_DurationColumn
112 };
113
ade0a3c5
PT
114 private static final String[] FILTER_COLUMN_NAMES = new String[] {
115 Messages.CallStackView_ThreadColumn
52974e38
PT
116 };
117
26c33ee2
PT
118 /** Timeout between updates in the build thread in ms */
119 private static final long BUILD_UPDATE_TIMEOUT = 500;
120
52974e38
PT
121 // Fraction of a function duration to be added as spacing
122 private static final double SPACING_RATIO = 0.01;
123
e8251298
PT
124 private static final Image THREAD_IMAGE = Activator.getDefault().getImageFromPath("icons/obj16/thread_obj.gif"); //$NON-NLS-1$
125 private static final Image STACKFRAME_IMAGE = Activator.getDefault().getImageFromPath("icons/obj16/stckframe_obj.gif"); //$NON-NLS-1$
126
41d9ce5b 127 private static final String IMPORT_BINARY_ICON_PATH = "icons/obj16/binaries_obj.gif"; //$NON-NLS-1$
5da83da5 128
46cc1ade
PT
129 private static final ImageDescriptor SORT_BY_NAME_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_alpha.gif"); //$NON-NLS-1$
130 private static final ImageDescriptor SORT_BY_NAME_REV_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_alpha_rev.gif"); //$NON-NLS-1$
131 private static final ImageDescriptor SORT_BY_ID_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_num.gif"); //$NON-NLS-1$
132 private static final ImageDescriptor SORT_BY_ID_REV_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_num_rev.gif"); //$NON-NLS-1$
133 private static final ImageDescriptor SORT_BY_TIME_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_time.gif"); //$NON-NLS-1$
134 private static final ImageDescriptor SORT_BY_TIME_REV_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_time_rev.gif"); //$NON-NLS-1$
135 private static final String SORT_OPTION_KEY = "sort.option"; //$NON-NLS-1$
bac9c0df
MK
136
137 private enum SortOption {
138 BY_NAME, BY_NAME_REV, BY_ID, BY_ID_REV, BY_TIME, BY_TIME_REV
139 }
140
ade0a3c5
PT
141 private @NonNull SortOption fSortOption = SortOption.BY_NAME;
142 private @NonNull Comparator<ITimeGraphEntry> fThreadComparator = new ThreadNameComparator(false);
46cc1ade
PT
143 private Action fSortByNameAction;
144 private Action fSortByIdAction;
145 private Action fSortByTimeAction;
146
e8251298
PT
147 // ------------------------------------------------------------------------
148 // Fields
149 // ------------------------------------------------------------------------
150
d90ae2a5 151 private final Map<ITmfTrace, ISymbolProvider> fSymbolProviders = new HashMap<>();
5da83da5 152
e8251298
PT
153 // The next event action
154 private Action fNextEventAction;
155
156 // The previous event action
157 private Action fPrevEventAction;
158
159 // The next item action
160 private Action fNextItemAction;
161
162 // The previous item action
163 private Action fPreviousItemAction;
164
41d9ce5b 165 // The action to import a binary file mapping */
d90ae2a5 166 private Action fConfigureSymbolsAction;
41d9ce5b 167
e8251298 168 // The saved time sync. signal used when switching off the pinning of a view
97c71024 169 private TmfSelectionRangeUpdatedSignal fSavedTimeSyncSignal;
e8251298 170
97c71024 171 // The saved window range signal used when switching off the pinning of
bac9c0df 172 // a view
97c71024 173 private TmfWindowRangeUpdatedSignal fSavedRangeSyncSignal;
e8251298
PT
174
175 // ------------------------------------------------------------------------
176 // Classes
177 // ------------------------------------------------------------------------
178
658e0268 179 private static class TraceEntry extends TimeGraphEntry {
60b4d44c
PT
180 public TraceEntry(String name, long startTime, long endTime) {
181 super(name, startTime, endTime);
182 }
183
184 @Override
185 public boolean hasTimeEvents() {
186 return false;
187 }
188 }
189
7f86b721
AM
190 private static class ProcessEntry extends TimeGraphEntry {
191
4ce4d8af
AM
192 private final int fProcessId;
193
194 public ProcessEntry(String name, int processId, long startTime, long endTime) {
7f86b721 195 super(name, startTime, endTime);
4ce4d8af
AM
196 fProcessId = processId;
197 }
198
199 public int getProcessId() {
200 return fProcessId;
7f86b721
AM
201 }
202
203 @Override
204 public boolean hasTimeEvents() {
205 return false;
206 }
207 }
208
658e0268 209 private static class ThreadEntry extends TimeGraphEntry {
da27e43a
PT
210 // The call stack quark
211 private final int fCallStackQuark;
50659279
AM
212 // The state system from which this entry comes
213 private final ITmfStateSystem fSS;
46cc1ade
PT
214 // The thread id
215 private final long fThreadId;
e8251298 216
46cc1ade 217 public ThreadEntry(ITmfStateSystem ss, String name, long threadId, int callStackQuark, long startTime, long endTime) {
60b4d44c 218 super(name, startTime, endTime);
da27e43a 219 fCallStackQuark = callStackQuark;
46cc1ade 220 fThreadId = threadId;
da27e43a 221 fSS = ss;
e8251298
PT
222 }
223
e8251298
PT
224 @Override
225 public boolean hasTimeEvents() {
226 return false;
227 }
228
da27e43a
PT
229 public int getCallStackQuark() {
230 return fCallStackQuark;
e8251298
PT
231 }
232
46cc1ade
PT
233 public long getThreadId() {
234 return fThreadId;
235 }
236
50659279
AM
237 @Nullable
238 public ITmfStateSystem getStateSystem() {
239 return fSS;
e8251298 240 }
e8251298
PT
241 }
242
ade0a3c5
PT
243 private class CallStackComparator implements Comparator<ITimeGraphEntry> {
244 @Override
245 public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) {
246 if (o1 instanceof ThreadEntry && o2 instanceof ThreadEntry) {
247 return fThreadComparator.compare(o1, o2);
4ce4d8af
AM
248 } else if (o1 instanceof ProcessEntry && o2 instanceof ProcessEntry) {
249 return Integer.compare(((ProcessEntry) o1).fProcessId, ((ProcessEntry) o2).fProcessId);
ade0a3c5
PT
250 }
251 return 0;
252 }
253 }
254
658e0268 255 private static class ThreadNameComparator implements Comparator<ITimeGraphEntry> {
46cc1ade 256 private boolean reverse;
bac9c0df 257
46cc1ade
PT
258 public ThreadNameComparator(boolean reverse) {
259 this.reverse = reverse;
260 }
bac9c0df 261
46cc1ade
PT
262 @Override
263 public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) {
264 return reverse ? o2.getName().compareTo(o1.getName()) :
bac9c0df 265 o1.getName().compareTo(o2.getName());
46cc1ade
PT
266 }
267 }
268
658e0268 269 private static class ThreadIdComparator implements Comparator<ITimeGraphEntry> {
46cc1ade 270 private boolean reverse;
bac9c0df 271
46cc1ade
PT
272 public ThreadIdComparator(boolean reverse) {
273 this.reverse = reverse;
274 }
bac9c0df 275
46cc1ade
PT
276 @Override
277 public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) {
7e0d06ba
PT
278 if (o1 instanceof ThreadEntry && o2 instanceof ThreadEntry) {
279 ThreadEntry t1 = (ThreadEntry) o1;
280 ThreadEntry t2 = (ThreadEntry) o2;
281 return reverse ? Long.compare(t2.getThreadId(), t1.getThreadId()) :
bac9c0df 282 Long.compare(t1.getThreadId(), t2.getThreadId());
7e0d06ba
PT
283 }
284 return 0;
46cc1ade
PT
285 }
286 }
287
658e0268 288 private static class ThreadTimeComparator implements Comparator<ITimeGraphEntry> {
46cc1ade 289 private boolean reverse;
bac9c0df 290
46cc1ade
PT
291 public ThreadTimeComparator(boolean reverse) {
292 this.reverse = reverse;
293 }
bac9c0df 294
46cc1ade
PT
295 @Override
296 public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) {
297 return reverse ? Long.compare(o2.getStartTime(), o1.getStartTime()) :
bac9c0df 298 Long.compare(o1.getStartTime(), o2.getStartTime());
46cc1ade
PT
299 }
300 }
301
658e0268 302 private static class CallStackTreeLabelProvider extends TreeLabelProvider {
e8251298
PT
303
304 @Override
305 public Image getColumnImage(Object element, int columnIndex) {
306 if (columnIndex == 0) {
307 if (element instanceof ThreadEntry) {
308 return THREAD_IMAGE;
309 } else if (element instanceof CallStackEntry) {
310 CallStackEntry entry = (CallStackEntry) element;
311 if (entry.getFunctionName().length() > 0) {
312 return STACKFRAME_IMAGE;
313 }
314 }
315 }
316 return null;
317 }
318
319 @Override
320 public String getColumnText(Object element, int columnIndex) {
60b4d44c 321 if (element instanceof CallStackEntry) {
e8251298
PT
322 CallStackEntry entry = (CallStackEntry) element;
323 if (columnIndex == 0) {
324 return entry.getFunctionName();
52974e38
PT
325 } else if (columnIndex == 1 && entry.getFunctionName().length() > 0) {
326 int depth = entry.getStackLevel();
327 return Integer.toString(depth);
328 } else if (columnIndex == 2 && entry.getFunctionName().length() > 0) {
b2c971ec 329 ITmfTimestamp ts = TmfTimestamp.fromNanos(entry.getFunctionEntryTime());
52974e38
PT
330 return ts.toString();
331 } else if (columnIndex == 3 && entry.getFunctionName().length() > 0) {
b2c971ec 332 ITmfTimestamp ts = TmfTimestamp.fromNanos(entry.getFunctionExitTime());
52974e38
PT
333 return ts.toString();
334 } else if (columnIndex == 4 && entry.getFunctionName().length() > 0) {
60b4d44c 335 ITmfTimestamp ts = new TmfTimestampDelta(entry.getFunctionExitTime() - entry.getFunctionEntryTime(), ITmfTimestamp.NANOSECOND_SCALE);
52974e38 336 return ts.toString();
e8251298 337 }
60b4d44c
PT
338 } else if (element instanceof ITimeGraphEntry) {
339 if (columnIndex == 0) {
340 return ((ITimeGraphEntry) element).getName();
341 }
e8251298
PT
342 }
343 return ""; //$NON-NLS-1$
344 }
345
346 }
347
ade0a3c5 348 private class CallStackFilterContentProvider extends TimeGraphContentProvider {
e8251298 349 @Override
ade0a3c5
PT
350 public boolean hasChildren(Object element) {
351 if (element instanceof TraceEntry) {
352 return super.hasChildren(element);
e8251298 353 }
ade0a3c5 354 return false;
e8251298
PT
355 }
356
357 @Override
ade0a3c5
PT
358 public ITimeGraphEntry[] getChildren(Object parentElement) {
359 if (parentElement instanceof TraceEntry) {
360 return super.getChildren(parentElement);
e8251298 361 }
ade0a3c5 362 return new ITimeGraphEntry[0];
e8251298
PT
363 }
364 }
365
366 // ------------------------------------------------------------------------
367 // Constructors
368 // ------------------------------------------------------------------------
369
370 /**
371 * Default constructor
372 */
373 public CallStackView() {
ade0a3c5
PT
374 super(ID, new CallStackPresentationProvider());
375 ((CallStackPresentationProvider) getPresentationProvider()).setCallStackView(this);
376 setTreeColumns(COLUMN_NAMES);
377 setTreeLabelProvider(new CallStackTreeLabelProvider());
378 setEntryComparator(new CallStackComparator());
379 setFilterColumns(FILTER_COLUMN_NAMES);
380 setFilterContentProvider(new CallStackFilterContentProvider());
381 setFilterLabelProvider(new CallStackTreeLabelProvider());
e8251298
PT
382 }
383
384 // ------------------------------------------------------------------------
385 // ViewPart
386 // ------------------------------------------------------------------------
387
388 @Override
389 public void createPartControl(Composite parent) {
d2e4afa7 390 super.createPartControl(parent);
e8251298 391
ade0a3c5 392 getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
e8251298
PT
393 @Override
394 public void timeSelected(TimeGraphTimeEvent event) {
ade0a3c5 395 synchingToTime(event.getBeginTime());
e8251298
PT
396 }
397 });
398
ade0a3c5 399 getTimeGraphCombo().getTreeViewer().addDoubleClickListener(new IDoubleClickListener() {
e8251298
PT
400 @Override
401 public void doubleClick(DoubleClickEvent event) {
402 Object selection = ((IStructuredSelection) event.getSelection()).getFirstElement();
403 if (selection instanceof CallStackEntry) {
404 CallStackEntry entry = (CallStackEntry) selection;
405 if (entry.getFunctionName().length() > 0) {
60b4d44c
PT
406 long entryTime = entry.getFunctionEntryTime();
407 long exitTime = entry.getFunctionExitTime();
408 long spacingTime = (long) ((exitTime - entryTime) * SPACING_RATIO);
409 entryTime -= spacingTime;
410 exitTime += spacingTime;
b2c971ec 411 TmfTimeRange range = new TmfTimeRange(TmfTimestamp.fromNanos(entryTime), TmfTimestamp.fromNanos(exitTime));
97c71024 412 broadcast(new TmfWindowRangeUpdatedSignal(CallStackView.this, range));
ade0a3c5 413 getTimeGraphViewer().setStartFinishTime(entryTime, exitTime);
60b4d44c 414 startZoomThread(entryTime, exitTime);
e8251298
PT
415 }
416 }
417 }
418 });
419
ade0a3c5 420 getTimeGraphViewer().getTimeGraphControl().addMouseListener(new MouseAdapter() {
e8251298
PT
421 @Override
422 public void mouseDoubleClick(MouseEvent e) {
ade0a3c5 423 TimeGraphControl timeGraphControl = getTimeGraphViewer().getTimeGraphControl();
e8251298
PT
424 ISelection selection = timeGraphControl.getSelection();
425 if (selection instanceof TimeGraphSelection) {
426 Object o = ((TimeGraphSelection) selection).getFirstElement();
427 if (o instanceof CallStackEvent) {
428 CallStackEvent event = (CallStackEvent) o;
429 long startTime = event.getTime();
430 long endTime = startTime + event.getDuration();
52974e38 431 long spacingTime = (long) ((endTime - startTime) * SPACING_RATIO);
e8251298
PT
432 startTime -= spacingTime;
433 endTime += spacingTime;
b2c971ec 434 TmfTimeRange range = new TmfTimeRange(TmfTimestamp.fromNanos(startTime), TmfTimestamp.fromNanos(endTime));
97c71024 435 broadcast(new TmfWindowRangeUpdatedSignal(CallStackView.this, range));
ade0a3c5 436 getTimeGraphViewer().setStartFinishTime(startTime, endTime);
e8251298
PT
437 startZoomThread(startTime, endTime);
438 }
439 }
440 }
441 });
442
e8251298 443 contributeToActionBars();
46cc1ade 444 loadSortOption();
e8251298
PT
445
446 IEditorPart editor = getSite().getPage().getActiveEditor();
447 if (editor instanceof ITmfTraceEditor) {
448 ITmfTrace trace = ((ITmfTraceEditor) editor).getTrace();
449 if (trace != null) {
450 traceSelected(new TmfTraceSelectedSignal(this, trace));
451 }
452 }
453 }
454
e8251298 455 /**
97c71024 456 * Handler for the selection range signal.
e8251298
PT
457 *
458 * @param signal
459 * The incoming signal
97c71024 460 * @since 1.0
e8251298 461 */
ade0a3c5 462 @Override
e8251298 463 @TmfSignalHandler
97c71024 464 public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal) {
e8251298 465
97c71024 466 fSavedTimeSyncSignal = isPinned() ? new TmfSelectionRangeUpdatedSignal(signal.getSource(), signal.getBeginTime(), signal.getEndTime()) : null;
e8251298 467
ade0a3c5 468 if (signal.getSource() == this || getTrace() == null || isPinned()) {
e8251298
PT
469 return;
470 }
16801c72
MK
471 final long beginTime = signal.getBeginTime().toNanos();
472 final long endTime = signal.getEndTime().toNanos();
e8251298
PT
473 Display.getDefault().asyncExec(new Runnable() {
474 @Override
475 public void run() {
ade0a3c5 476 if (getTimeGraphCombo().isDisposed()) {
e8251298
PT
477 return;
478 }
0fcf3b09 479 if (beginTime == endTime) {
ade0a3c5 480 getTimeGraphViewer().setSelectedTime(beginTime, true);
0fcf3b09 481 } else {
ade0a3c5 482 getTimeGraphViewer().setSelectionRange(beginTime, endTime, true);
0fcf3b09 483 }
26c33ee2 484 synchingToTime(beginTime);
ade0a3c5 485 startZoomThread(getTimeGraphViewer().getTime0(), getTimeGraphViewer().getTime1());
7f86b721
AM
486 List<TimeGraphEntry> traceEntries = getEntryList(getTrace());
487 if (traceEntries == null) {
e8251298
PT
488 return;
489 }
ade0a3c5 490 TimeGraphViewer viewer = getTimeGraphViewer();
7f86b721
AM
491 for (TimeGraphEntry traceEntry : traceEntries) {
492 for (ITimeGraphEntry processEntry : traceEntry.getChildren()) {
493 for (ITimeGraphEntry aThreadEntry : processEntry.getChildren()) {
494 ThreadEntry threadEntry = (ThreadEntry) aThreadEntry;
495 ITmfStateSystem ss = threadEntry.getStateSystem();
496 if (ss == null || beginTime < ss.getStartTime() || beginTime > ss.getCurrentEndTime()) {
497 continue;
498 }
499 try {
500 int quark = threadEntry.getCallStackQuark();
501 ITmfStateInterval stackInterval = ss.querySingleState(beginTime, quark);
502 if (beginTime == stackInterval.getStartTime()) {
503 int stackLevel = stackInterval.getStateValue().unboxInt();
504 ITimeGraphEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
505 getTimeGraphCombo().setSelection(selectedEntry);
506 viewer.getTimeGraphControl().fireSelectionChanged();
507 break;
508 }
509 } catch (AttributeNotFoundException | TimeRangeException | StateSystemDisposedException | StateValueTypeException e) {
510 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
60b4d44c 511 }
e8251298 512 }
e8251298
PT
513 }
514 }
515 }
516 });
7f86b721 517
e8251298
PT
518 }
519
37838e00
BH
520 /**
521 * @since 2.0
522 */
523 @Override
524 @TmfSignalHandler
525 public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal) {
526
527 if (isPinned()) {
528 fSavedRangeSyncSignal = new TmfWindowRangeUpdatedSignal(signal.getSource(), signal.getCurrentRange());
529 fSavedTimeSyncSignal = null;
530 }
531
532 if ((signal.getSource() == this) || isPinned()) {
533 return;
534 }
535 super.windowRangeUpdated(signal);
536 }
537
e8251298
PT
538 // ------------------------------------------------------------------------
539 // Internal
540 // ------------------------------------------------------------------------
5da83da5 541
d90ae2a5
RK
542 @Override
543 @TmfSignalHandler
544 public void traceClosed(TmfTraceClosedSignal signal) {
545 super.traceClosed(signal);
546 synchronized(fSymbolProviders){
547 for(ITmfTrace trace : getTracesToBuild(signal.getTrace())){
548 fSymbolProviders.remove(trace);
549 }
550 }
551 }
552
553 /**
554 * @since 2.0
555 */
556 @Override
557 protected void refresh() {
558 super.refresh();
559 updateConfigureSymbolsAction();
560 }
561
ade0a3c5 562 @Override
f8f46a52 563 protected void buildEntryList(final ITmfTrace trace, final ITmfTrace parentTrace, final IProgressMonitor monitor) {
26c33ee2
PT
564 if (monitor.isCanceled()) {
565 return;
566 }
567 AbstractCallStackAnalysis module = getCallStackModule(trace);
568 if (module == null) {
569 addUnavailableEntry(trace, parentTrace);
570 return;
571 }
572 ITmfStateSystem ss = module.getStateSystem();
573 if (ss == null) {
574 addUnavailableEntry(trace, parentTrace);
575 return;
576 }
577
578 Map<ITmfTrace, TraceEntry> traceEntryMap = new HashMap<>();
7f86b721 579 Map<Integer, ProcessEntry> processEntryMap = new HashMap<>();
26c33ee2 580 Map<Integer, ThreadEntry> threadEntryMap = new HashMap<>();
26c33ee2
PT
581
582 long start = ss.getStartTime();
583
584 boolean complete = false;
585 while (!complete) {
e8251298
PT
586 if (monitor.isCanceled()) {
587 return;
588 }
26c33ee2
PT
589 complete = ss.waitUntilBuilt(BUILD_UPDATE_TIMEOUT);
590 if (ss.isCancelled()) {
da27e43a
PT
591 return;
592 }
26c33ee2
PT
593 long end = ss.getCurrentEndTime();
594 if (start == end && !complete) { // when complete execute one last time regardless of end time
e8251298
PT
595 continue;
596 }
d90ae2a5
RK
597
598 ISymbolProvider provider = fSymbolProviders.get(trace);
599 if (provider == null) {
600 provider = SymbolProviderManager.getInstance().getSymbolProvider(trace);
601 provider.loadConfiguration(monitor);
602 fSymbolProviders.put(trace, provider);
603 }
604
605 getConfigureSymbolsAction().setEnabled(true);
606
7f86b721 607
26c33ee2
PT
608 TraceEntry traceEntry = traceEntryMap.get(trace);
609 if (traceEntry == null) {
610 traceEntry = new TraceEntry(trace.getName(), start, end + 1);
611 traceEntryMap.put(trace, traceEntry);
612 traceEntry.sortChildren(fThreadComparator);
613 addToEntryList(parentTrace, Collections.singletonList(traceEntry));
614 } else {
615 traceEntry.updateEndTime(end);
616 }
1a0ff02c 617
7f86b721
AM
618 List<Integer> processQuarks = ss.getQuarks(module.getProcessesPattern());
619 for (Integer processQuark : processQuarks) {
620
621 /* Create the entry for the process */
622 ProcessEntry processEntry = processEntryMap.get(processQuark);
623 if (processEntry == null) {
624 String name = ss.getAttributeName(processQuark.intValue());
4ce4d8af
AM
625 /* The attribute name should already be parseable to integer */
626 int processId = Integer.parseInt(name);
627 processEntry = new ProcessEntry(name, processId, start, end);
7f86b721
AM
628 processEntryMap.put(processQuark, processEntry);
629 traceEntry.addChild(processEntry);
630 } else {
631 processEntry.updateEndTime(end);
632 }
633
634 /* Create the threads under the process */
635 try {
636 List<Integer> threadQuarks = ss.getSubAttributes(processQuark, false, module.getThreadsForProcessPattern());
637
638 /*
639 * Only query startStates if necessary (threadEntry == null)
640 */
641 List<ITmfStateInterval> startStates = null;
642 List<ITmfStateInterval> endStates = ss.queryFullState(ss.getCurrentEndTime());
643 for (int i = 0; i < threadQuarks.size(); i++) {
644 if (monitor.isCanceled()) {
645 return;
1a0ff02c 646 }
7f86b721
AM
647 int threadQuark = threadQuarks.get(i);
648
649 String[] callStackPath = module.getCallStackPathForThread();
650 int callStackQuark = ss.getQuarkRelative(threadQuark, callStackPath);
651 String threadName = ss.getAttributeName(threadQuark);
652 long threadEnd = end + 1;
653 ITmfStateInterval endInterval = endStates.get(callStackQuark);
654 if (endInterval.getStateValue().isNull() && endInterval.getStartTime() != ss.getStartTime()) {
655 threadEnd = endInterval.getStartTime();
26c33ee2 656 }
7f86b721
AM
657 ThreadEntry threadEntry = threadEntryMap.get(threadQuark);
658 if (threadEntry == null) {
659 if (startStates == null) {
660 startStates = ss.queryFullState(ss.getStartTime());
661 }
e4bbed4b 662 long threadId = endStates.get(threadQuark).getStateValue().unboxLong();
7f86b721
AM
663 long threadStart = start;
664 ITmfStateInterval startInterval = startStates.get(callStackQuark);
665 if (startInterval.getStateValue().isNull()) {
666 threadStart = Math.min(startInterval.getEndTime() + 1, end + 1);
667 }
668 threadEntry = new ThreadEntry(ss, threadName, threadId, callStackQuark, threadStart, threadEnd);
669 threadEntryMap.put(threadQuark, threadEntry);
670 processEntry.addChild(threadEntry);
671 } else {
672 threadEntry.updateEndTime(threadEnd);
673 }
674 int level = 1;
675 for (int stackLevelQuark : ss.getSubAttributes(callStackQuark, false)) {
676 if (level > threadEntry.getChildren().size()) {
4ce4d8af
AM
677 int processId = processEntry.getProcessId();
678 CallStackEntry callStackEntry = new CallStackEntry(threadName, stackLevelQuark, level, processId, trace, ss);
7f86b721
AM
679 threadEntry.addChild(callStackEntry);
680 }
681 level++;
26c33ee2 682 }
e8251298 683 }
7f86b721
AM
684 } catch (AttributeNotFoundException e) {
685 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
686 } catch (StateSystemDisposedException e) {
687 /* Ignored */
e8251298
PT
688 }
689 }
7f86b721 690
ade0a3c5
PT
691 if (parentTrace == getTrace()) {
692 synchronized (this) {
693 setStartTime(getStartTime() == SWT.DEFAULT ? start : Math.min(getStartTime(), start));
694 setEndTime(getEndTime() == SWT.DEFAULT ? end + 1 : Math.max(getEndTime(), end + 1));
26c33ee2 695 }
ade0a3c5 696 synchingToTime(getTimeGraphViewer().getSelectionBegin());
26c33ee2
PT
697 refresh();
698 }
7f86b721
AM
699
700 for (ITimeGraphEntry processEntry : traceEntry.getChildren()) {
701 for (ITimeGraphEntry threadEntry : processEntry.getChildren()) {
702 for (ITimeGraphEntry callStackEntry : threadEntry.getChildren()) {
703 if (monitor.isCanceled()) {
704 return;
705 }
706 buildStatusEvents(parentTrace, (CallStackEntry) callStackEntry, monitor, ss.getStartTime(), end);
60b4d44c 707 }
e8251298 708 }
e8251298 709 }
26c33ee2 710 start = end;
e8251298
PT
711 }
712 }
713
26c33ee2 714 private void addUnavailableEntry(ITmfTrace trace, ITmfTrace parentTrace) {
60b4d44c
PT
715 String name = Messages.CallStackView_StackInfoNotAvailable + ' ' + '(' + trace.getName() + ')';
716 TraceEntry unavailableEntry = new TraceEntry(name, 0, 0);
26c33ee2 717 addToEntryList(parentTrace, Collections.singletonList(unavailableEntry));
ade0a3c5 718 if (parentTrace == getTrace()) {
26c33ee2
PT
719 refresh();
720 }
2002c638
AM
721 }
722
ade0a3c5 723 private void buildStatusEvents(ITmfTrace trace, CallStackEntry entry, @NonNull IProgressMonitor monitor, long start, long end) {
da27e43a 724 ITmfStateSystem ss = entry.getStateSystem();
ade0a3c5 725 long resolution = Math.max(1, (end - ss.getStartTime()) / getDisplayWidth());
26c33ee2
PT
726 List<ITimeEvent> eventList = getEventList(entry, start, end + 1, resolution, monitor);
727 if (eventList != null) {
8d5d4aa4 728 entry.setEventList(eventList);
e8251298 729 }
ade0a3c5 730 if (trace == getTrace()) {
e8251298
PT
731 redraw();
732 }
733 }
734
ade0a3c5
PT
735 /**
736 * @since 2.0
737 */
738 @Override
739 protected final List<ITimeEvent> getEventList(TimeGraphEntry tgentry, long startTime, long endTime, long resolution, IProgressMonitor monitor) {
740 if (!(tgentry instanceof CallStackEntry)) {
741 return null;
742 }
743 CallStackEntry entry = (CallStackEntry) tgentry;
da27e43a 744 ITmfStateSystem ss = entry.getStateSystem();
e8251298
PT
745 long start = Math.max(startTime, ss.getStartTime());
746 long end = Math.min(endTime, ss.getCurrentEndTime() + 1);
747 if (end <= start) {
748 return null;
749 }
8d5d4aa4 750 boolean isZoomThread = Thread.currentThread() instanceof ZoomThread;
e8251298
PT
751 List<ITimeEvent> eventList = null;
752 try {
1dd75589 753 List<ITmfStateInterval> stackIntervals = StateSystemUtils.queryHistoryRange(ss, entry.getQuark(), start, end - 1, resolution, monitor);
507b1336 754 eventList = new ArrayList<>(stackIntervals.size());
e8251298 755 long lastEndTime = -1;
fb70173e 756 boolean lastIsNull = false;
e8251298
PT
757 for (ITmfStateInterval statusInterval : stackIntervals) {
758 if (monitor.isCanceled()) {
759 return null;
760 }
761 long time = statusInterval.getStartTime();
762 long duration = statusInterval.getEndTime() - time + 1;
763 if (!statusInterval.getStateValue().isNull()) {
52974e38
PT
764 final int modulo = CallStackPresentationProvider.NUM_COLORS / 2;
765 int value = statusInterval.getStateValue().toString().hashCode() % modulo + modulo;
e8251298
PT
766 eventList.add(new CallStackEvent(entry, time, duration, value));
767 lastIsNull = false;
768 } else {
8d5d4aa4 769 if (lastEndTime == -1 && isZoomThread) {
beb1b921
PT
770 // add null event if it intersects the start time
771 eventList.add(new NullTimeEvent(entry, time, duration));
772 } else {
773 if (lastEndTime != time && lastIsNull) {
774 // add unknown event if between two null states
775 eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
776 }
8d5d4aa4 777 if (time + duration >= endTime && isZoomThread) {
beb1b921
PT
778 // add null event if it intersects the end time
779 eventList.add(new NullTimeEvent(entry, time, duration));
780 }
e8251298 781 }
e8251298
PT
782 lastIsNull = true;
783 }
784 lastEndTime = time + duration;
785 }
786 } catch (AttributeNotFoundException e) {
52974e38 787 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
e8251298 788 } catch (TimeRangeException e) {
52974e38 789 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
e8251298
PT
790 } catch (StateSystemDisposedException e) {
791 /* Ignored */
792 }
793 return eventList;
794 }
795
ade0a3c5
PT
796 /**
797 * @since 2.0
798 */
799 @Override
800 protected void synchingToTime(long time) {
801 List<TimeGraphEntry> entryList = getEntryList(getTrace());
802 if (entryList == null) {
e8251298
PT
803 return;
804 }
ade0a3c5 805 for (TimeGraphEntry traceEntry : entryList) {
7f86b721 806 for (ITimeGraphEntry processEntry : traceEntry.getChildren()) {
4ce4d8af
AM
807 /* The entries should all be parseable to an integer. */
808 int pid = Integer.parseInt(processEntry.getName());
809
7f86b721
AM
810 for (ITimeGraphEntry threadEntry : processEntry.getChildren()) {
811 ITmfStateSystem ss = ((ThreadEntry) threadEntry).getStateSystem();
812 if (ss == null) {
813 continue;
814 }
815 if (ss.isCancelled()) {
816 continue;
817 }
818 if (time < ss.getStartTime() || time > ss.getCurrentEndTime()) {
819 continue;
820 }
821 for (ITimeGraphEntry child : threadEntry.getChildren()) {
822 CallStackEntry callStackEntry = (CallStackEntry) child;
823 ITmfTrace trace = callStackEntry.getTrace();
824 try {
825 ITmfStateInterval stackLevelInterval = ss.querySingleState(time, callStackEntry.getQuark());
826 ITmfStateValue nameValue = stackLevelInterval.getStateValue();
4ce4d8af
AM
827
828 String name = getFunctionName(trace, pid, time, nameValue);
7f86b721
AM
829 callStackEntry.setFunctionName(name);
830 if (name.length() > 0) {
831 callStackEntry.setFunctionEntryTime(stackLevelInterval.getStartTime());
832 callStackEntry.setFunctionExitTime(stackLevelInterval.getEndTime() + 1);
833 }
834 } catch (AttributeNotFoundException e) {
835 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
836 } catch (StateSystemDisposedException e) {
837 /* Ignored */
60b4d44c 838 }
e8251298 839 }
e8251298
PT
840 }
841 }
842 }
ade0a3c5
PT
843 if (Display.getCurrent() != null) {
844 getTimeGraphCombo().refresh();
e8251298 845 }
e8251298
PT
846 }
847
4ce4d8af 848 String getFunctionName(ITmfTrace trace, int processId, long timestamp, ITmfStateValue nameValue) {
d90ae2a5
RK
849 long address = Long.MAX_VALUE;
850 String name = ""; //$NON-NLS-1$
851 try {
852 if (nameValue.getType() == Type.STRING) {
853 name = nameValue.unboxStr();
854 try {
855 address = Long.parseLong(name, 16);
856 } catch (NumberFormatException e) {
857 // ignore
858 }
859 } else if (nameValue.getType() == Type.INTEGER) {
860 name = "0x" + Integer.toHexString(nameValue.unboxInt()); //$NON-NLS-1$
861 address = nameValue.unboxInt();
862 } else if (nameValue.getType() == Type.LONG) {
863 name = "0x" + Long.toHexString(nameValue.unboxLong()); //$NON-NLS-1$
864 address = nameValue.unboxLong();
865 }
866 } catch (StateValueTypeException e) {
867 }
868 if (address != Long.MAX_VALUE) {
869 ISymbolProvider provider = fSymbolProviders.get(trace);
870 if (provider != null) {
4ce4d8af 871 String symbol = provider.getSymbolText(processId, timestamp, address);
d90ae2a5
RK
872 if (symbol != null) {
873 name = symbol;
874 }
875 }
876 }
877 return name;
878 }
879
e8251298 880 private void makeActions() {
ade0a3c5 881 fPreviousItemAction = getTimeGraphViewer().getPreviousItemAction();
e8251298
PT
882 fPreviousItemAction.setText(Messages.TmfTimeGraphViewer_PreviousItemActionNameText);
883 fPreviousItemAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousItemActionToolTipText);
ade0a3c5 884 fNextItemAction = getTimeGraphViewer().getNextItemAction();
e8251298
PT
885 fNextItemAction.setText(Messages.TmfTimeGraphViewer_NextItemActionNameText);
886 fNextItemAction.setToolTipText(Messages.TmfTimeGraphViewer_NextItemActionToolTipText);
887 }
888
889 private void contributeToActionBars() {
e8251298
PT
890 // Create pin action
891 contributePinActionToToolBar();
bac9c0df 892 fPinAction.addPropertyChangeListener(new IPropertyChangeListener() {
e8251298
PT
893 @Override
894 public void propertyChange(PropertyChangeEvent event) {
52974e38
PT
895 if (IAction.CHECKED.equals(event.getProperty()) && !isPinned()) {
896 if (fSavedRangeSyncSignal != null) {
97c71024 897 windowRangeUpdated(fSavedRangeSyncSignal);
52974e38
PT
898 fSavedRangeSyncSignal = null;
899 }
e8251298 900
52974e38 901 if (fSavedTimeSyncSignal != null) {
97c71024 902 selectionRangeUpdated(fSavedTimeSyncSignal);
52974e38 903 fSavedTimeSyncSignal = null;
e8251298
PT
904 }
905 }
906 }
907 });
908 }
909
ade0a3c5
PT
910 /**
911 * @since 2.0
912 */
913 @Override
914 protected void fillLocalToolBar(IToolBarManager manager) {
915 makeActions();
d90ae2a5 916 manager.add(getConfigureSymbolsAction());
46cc1ade
PT
917 manager.add(new Separator());
918 manager.add(getSortByNameAction());
919 manager.add(getSortByIdAction());
920 manager.add(getSortByTimeAction());
921 manager.add(new Separator());
ade0a3c5
PT
922 manager.add(getTimeGraphCombo().getShowFilterDialogAction());
923 manager.add(new Separator());
924 manager.add(getTimeGraphViewer().getResetScaleAction());
e8251298
PT
925 manager.add(getPreviousEventAction());
926 manager.add(getNextEventAction());
ade0a3c5
PT
927 manager.add(new Separator());
928 manager.add(getTimeGraphViewer().getToggleBookmarkAction());
929 manager.add(getTimeGraphViewer().getPreviousMarkerAction());
930 manager.add(getTimeGraphViewer().getNextMarkerAction());
931 manager.add(new Separator());
e8251298
PT
932 manager.add(fPreviousItemAction);
933 manager.add(fNextItemAction);
ade0a3c5
PT
934 manager.add(getTimeGraphViewer().getZoomInAction());
935 manager.add(getTimeGraphViewer().getZoomOutAction());
e8251298
PT
936 }
937
90bb3a0c
BH
938 /**
939 * @since 2.0
940 */
941 @Override
942 protected void fillTimeGraphEntryContextMenu(IMenuManager contextMenu) {
d2fb9e0f 943 contextMenu.add(new GroupMarker(IWorkbenchActionConstants.GROUP_REORGANIZE));
46cc1ade
PT
944 contextMenu.add(getSortByNameAction());
945 contextMenu.add(getSortByIdAction());
946 contextMenu.add(getSortByTimeAction());
46cc1ade
PT
947 }
948
e8251298
PT
949 /**
950 * Get the the next event action.
951 *
952 * @return The action object
953 */
954 private Action getNextEventAction() {
955 if (fNextEventAction == null) {
956 fNextEventAction = new Action() {
957 @Override
958 public void run() {
ade0a3c5 959 TimeGraphViewer viewer = getTimeGraphViewer();
e8251298
PT
960 ITimeGraphEntry entry = viewer.getSelection();
961 if (entry instanceof CallStackEntry) {
962 try {
963 CallStackEntry callStackEntry = (CallStackEntry) entry;
da27e43a 964 ITmfStateSystem ss = callStackEntry.getStateSystem();
0fcf3b09 965 long time = Math.max(ss.getStartTime(), Math.min(ss.getCurrentEndTime(), viewer.getSelectionBegin()));
e8251298 966 ThreadEntry threadEntry = (ThreadEntry) callStackEntry.getParent();
da27e43a 967 int quark = ss.getParentAttributeQuark(callStackEntry.getQuark());
e8251298
PT
968 ITmfStateInterval stackInterval = ss.querySingleState(time, quark);
969 long newTime = stackInterval.getEndTime() + 1;
970 viewer.setSelectedTimeNotify(newTime, true);
971 stackInterval = ss.querySingleState(Math.min(ss.getCurrentEndTime(), newTime), quark);
972 int stackLevel = stackInterval.getStateValue().unboxInt();
a3188982 973 ITimeGraphEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
ade0a3c5 974 getTimeGraphCombo().setSelection(selectedEntry);
e8251298
PT
975 viewer.getTimeGraphControl().fireSelectionChanged();
976 startZoomThread(viewer.getTime0(), viewer.getTime1());
50659279 977
bac9c0df 978 } catch (AttributeNotFoundException | TimeRangeException | StateSystemDisposedException | StateValueTypeException e) {
52974e38 979 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
e8251298
PT
980 }
981 }
982 }
983 };
984
985 fNextEventAction.setText(Messages.TmfTimeGraphViewer_NextEventActionNameText);
986 fNextEventAction.setToolTipText(Messages.TmfTimeGraphViewer_NextEventActionToolTipText);
987 fNextEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_NEXT_EVENT));
988 }
989
990 return fNextEventAction;
991 }
992
993 /**
994 * Get the previous event action.
995 *
996 * @return The Action object
997 */
998 private Action getPreviousEventAction() {
999 if (fPrevEventAction == null) {
1000 fPrevEventAction = new Action() {
1001 @Override
1002 public void run() {
ade0a3c5 1003 TimeGraphViewer viewer = getTimeGraphCombo().getTimeGraphViewer();
e8251298
PT
1004 ITimeGraphEntry entry = viewer.getSelection();
1005 if (entry instanceof CallStackEntry) {
1006 try {
1007 CallStackEntry callStackEntry = (CallStackEntry) entry;
da27e43a 1008 ITmfStateSystem ss = callStackEntry.getStateSystem();
0fcf3b09 1009 long time = Math.max(ss.getStartTime(), Math.min(ss.getCurrentEndTime(), viewer.getSelectionBegin()));
e8251298 1010 ThreadEntry threadEntry = (ThreadEntry) callStackEntry.getParent();
da27e43a 1011 int quark = ss.getParentAttributeQuark(callStackEntry.getQuark());
e8251298
PT
1012 ITmfStateInterval stackInterval = ss.querySingleState(time, quark);
1013 if (stackInterval.getStartTime() == time && time > ss.getStartTime()) {
1014 stackInterval = ss.querySingleState(time - 1, quark);
1015 }
1016 viewer.setSelectedTimeNotify(stackInterval.getStartTime(), true);
1017 int stackLevel = stackInterval.getStateValue().unboxInt();
a3188982 1018 ITimeGraphEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
ade0a3c5 1019 getTimeGraphCombo().setSelection(selectedEntry);
e8251298
PT
1020 viewer.getTimeGraphControl().fireSelectionChanged();
1021 startZoomThread(viewer.getTime0(), viewer.getTime1());
50659279 1022
bac9c0df 1023 } catch (AttributeNotFoundException | TimeRangeException | StateSystemDisposedException | StateValueTypeException e) {
52974e38 1024 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
e8251298
PT
1025 }
1026 }
1027 }
1028 };
1029
1030 fPrevEventAction.setText(Messages.TmfTimeGraphViewer_PreviousEventActionNameText);
1031 fPrevEventAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousEventActionToolTipText);
1032 fPrevEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_PREV_EVENT));
1033 }
1034
1035 return fPrevEventAction;
1036 }
1037
1d83ed07 1038 private static @Nullable AbstractCallStackAnalysis getCallStackModule(@NonNull ITmfTrace trace) {
50659279
AM
1039 /*
1040 * Since we cannot know the exact analysis ID (in separate plugins), we
1041 * will search using the analysis type.
1042 */
1043 Iterable<AbstractCallStackAnalysis> modules =
b8585c7c 1044 TmfTraceUtils.getAnalysisModulesOfClass(trace, AbstractCallStackAnalysis.class);
50659279
AM
1045 Iterator<AbstractCallStackAnalysis> it = modules.iterator();
1046 if (!it.hasNext()) {
1047 /* This trace does not provide a call-stack analysis */
1048 return null;
1049 }
1050
1051 /*
1052 * We only look at the first module we find.
1053 *
1054 * TODO Handle the advanced case where one trace provides more than one
1055 * call-stack analysis.
1056 */
1057 AbstractCallStackAnalysis module = it.next();
1058 /* This analysis is not automatic, we need to schedule it on-demand */
1059 module.schedule();
c81ffdf2
JCK
1060 if (!module.waitForInitialization()) {
1061 /* The initialization did not succeed */
1062 return null;
1063 }
da27e43a 1064 return module;
50659279
AM
1065 }
1066
5da83da5
AM
1067 // ------------------------------------------------------------------------
1068 // Methods related to function name mapping
1069 // ------------------------------------------------------------------------
1070
46cc1ade
PT
1071 private Action getSortByNameAction() {
1072 if (fSortByNameAction == null) {
1073 fSortByNameAction = new Action(Messages.CallStackView_SortByThreadName, IAction.AS_CHECK_BOX) {
1074 @Override
1075 public void run() {
1076 if (fSortOption == SortOption.BY_NAME) {
1077 saveSortOption(SortOption.BY_NAME_REV);
1078 } else {
1079 saveSortOption(SortOption.BY_NAME);
1080 }
1081 }
1082 };
1083 fSortByNameAction.setToolTipText(Messages.CallStackView_SortByThreadName);
6aea3caa 1084 fSortByNameAction.setImageDescriptor(SORT_BY_NAME_ICON);
46cc1ade
PT
1085 }
1086 return fSortByNameAction;
1087 }
1088
1089 private Action getSortByIdAction() {
1090 if (fSortByIdAction == null) {
1091 fSortByIdAction = new Action(Messages.CallStackView_SortByThreadId, IAction.AS_CHECK_BOX) {
1092 @Override
1093 public void run() {
1094 if (fSortOption == SortOption.BY_ID) {
1095 saveSortOption(SortOption.BY_ID_REV);
1096 } else {
1097 saveSortOption(SortOption.BY_ID);
1098 }
1099 }
1100 };
1101 fSortByIdAction.setToolTipText(Messages.CallStackView_SortByThreadId);
6aea3caa 1102 fSortByIdAction.setImageDescriptor(SORT_BY_ID_ICON);
46cc1ade
PT
1103 }
1104 return fSortByIdAction;
1105 }
1106
1107 private Action getSortByTimeAction() {
1108 if (fSortByTimeAction == null) {
1109 fSortByTimeAction = new Action(Messages.CallStackView_SortByThreadTime, IAction.AS_CHECK_BOX) {
1110 @Override
1111 public void run() {
1112 if (fSortOption == SortOption.BY_TIME) {
1113 saveSortOption(SortOption.BY_TIME_REV);
1114 } else {
1115 saveSortOption(SortOption.BY_TIME);
1116 }
1117 }
1118 };
1119 fSortByTimeAction.setToolTipText(Messages.CallStackView_SortByThreadTime);
6aea3caa 1120 fSortByTimeAction.setImageDescriptor(SORT_BY_TIME_ICON);
46cc1ade
PT
1121 }
1122 return fSortByTimeAction;
1123 }
1124
1125 private void loadSortOption() {
1126 IDialogSettings settings = Activator.getDefault().getDialogSettings();
1127 IDialogSettings section = settings.getSection(getClass().getName());
1128 if (section == null) {
1129 return;
1130 }
1131 String sortOption = section.get(SORT_OPTION_KEY);
6aea3caa
PT
1132 if (sortOption == null) {
1133 return;
1134 }
46cc1ade
PT
1135
1136 // reset defaults
1137 getSortByNameAction().setChecked(false);
1138 getSortByNameAction().setImageDescriptor(SORT_BY_NAME_ICON);
1139 getSortByIdAction().setChecked(false);
1140 getSortByIdAction().setImageDescriptor(SORT_BY_ID_ICON);
1141 getSortByTimeAction().setChecked(false);
1142 getSortByTimeAction().setImageDescriptor(SORT_BY_TIME_ICON);
1143
1144 if (sortOption.equals(SortOption.BY_NAME.name())) {
1145 fSortOption = SortOption.BY_NAME;
1146 fThreadComparator = new ThreadNameComparator(false);
1147 getSortByNameAction().setChecked(true);
1148 } else if (sortOption.equals(SortOption.BY_NAME_REV.name())) {
1149 fSortOption = SortOption.BY_NAME_REV;
1150 fThreadComparator = new ThreadNameComparator(true);
1151 getSortByNameAction().setChecked(true);
1152 getSortByNameAction().setImageDescriptor(SORT_BY_NAME_REV_ICON);
1153 } else if (sortOption.equals(SortOption.BY_ID.name())) {
1154 fSortOption = SortOption.BY_ID;
1155 fThreadComparator = new ThreadIdComparator(false);
1156 getSortByIdAction().setChecked(true);
1157 } else if (sortOption.equals(SortOption.BY_ID_REV.name())) {
1158 fSortOption = SortOption.BY_ID_REV;
1159 fThreadComparator = new ThreadIdComparator(true);
1160 getSortByIdAction().setChecked(true);
1161 getSortByIdAction().setImageDescriptor(SORT_BY_ID_REV_ICON);
1162 } else if (sortOption.equals(SortOption.BY_TIME.name())) {
1163 fSortOption = SortOption.BY_TIME;
1164 fThreadComparator = new ThreadTimeComparator(false);
1165 getSortByTimeAction().setChecked(true);
1166 } else if (sortOption.equals(SortOption.BY_TIME_REV.name())) {
1167 fSortOption = SortOption.BY_TIME_REV;
1168 fThreadComparator = new ThreadTimeComparator(true);
1169 getSortByTimeAction().setChecked(true);
1170 getSortByTimeAction().setImageDescriptor(SORT_BY_TIME_REV_ICON);
1171 }
1172 }
1173
1174 private void saveSortOption(SortOption sortOption) {
1175 IDialogSettings settings = Activator.getDefault().getDialogSettings();
1176 IDialogSettings section = settings.getSection(getClass().getName());
1177 if (section == null) {
1178 section = settings.addNewSection(getClass().getName());
1179 }
1180 section.put(SORT_OPTION_KEY, sortOption.name());
1181 loadSortOption();
ade0a3c5
PT
1182 List<TimeGraphEntry> entryList = getEntryList(getTrace());
1183 if (entryList == null) {
46cc1ade
PT
1184 return;
1185 }
ade0a3c5 1186 for (TimeGraphEntry traceEntry : entryList) {
46cc1ade
PT
1187 traceEntry.sortChildren(fThreadComparator);
1188 }
1189 refresh();
1190 }
1191
d90ae2a5
RK
1192 private Action getConfigureSymbolsAction() {
1193 if (fConfigureSymbolsAction != null) {
1194 return fConfigureSymbolsAction;
5da83da5
AM
1195 }
1196
d90ae2a5 1197 fConfigureSymbolsAction = new Action(Messages.CallStackView_ConfigureSymbolProvidersText) {
41d9ce5b 1198 @Override
d90ae2a5
RK
1199 public void run() {
1200 SymbolProviderConfigDialog dialog = new SymbolProviderConfigDialog(getSite().getShell(), getProviderPages());
1201 if (dialog.open() == IDialogConstants.OK_ID) {
1202 refresh();
1203 }
41d9ce5b
MAL
1204 }
1205 };
5da83da5 1206
d90ae2a5
RK
1207 fConfigureSymbolsAction.setToolTipText(Messages.CallStackView_ConfigureSymbolProvidersTooltip);
1208 fConfigureSymbolsAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(IMPORT_BINARY_ICON_PATH));
1209 fConfigureSymbolsAction.setEnabled(false);
5da83da5 1210
d90ae2a5 1211 return fConfigureSymbolsAction;
5da83da5
AM
1212 }
1213
d90ae2a5
RK
1214 /**
1215 * @return an array of {@link ISymbolProviderPreferencePage} that will
1216 * configure the current traces
1217 */
1218 private ISymbolProviderPreferencePage[] getProviderPages() {
1219 List<ISymbolProviderPreferencePage> pages = new ArrayList<>();
1220 ITmfTrace trace = getTrace();
1221 if (trace != null) {
1222 for (ITmfTrace subTrace : getTracesToBuild(trace)) {
1223 ISymbolProvider provider = fSymbolProviders.get(subTrace);
1224 if (provider != null) {
1225 ISymbolProviderPreferencePage page = provider.createPreferencePage();
1226 if (page != null) {
1227 pages.add(page);
1228 }
1229 }
1230 }
5da83da5 1231 }
d90ae2a5
RK
1232 return pages.toArray(new ISymbolProviderPreferencePage[pages.size()]);
1233 }
1234
1235 /**
1236 * Update the enable status of the configure symbols action
1237 */
1238 private void updateConfigureSymbolsAction() {
1239 ISymbolProviderPreferencePage[] providerPages = getProviderPages();
1240 getConfigureSymbolsAction().setEnabled(providerPages.length > 0);
5da83da5
AM
1241 }
1242
e8251298 1243}
This page took 0.149855 seconds and 5 git commands to generate.