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