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