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