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