1 /*******************************************************************************
2 * Copyright (c) 2013, 2014 Ericsson
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
10 * Patrick Tasse - Initial API and implementation
11 * Bernd Hufmann - Updated signal handling
12 *******************************************************************************/
14 package org
.eclipse
.linuxtools
.tmf
.ui
.views
.callstack
;
17 import java
.util
.ArrayList
;
18 import java
.util
.HashMap
;
19 import java
.util
.Iterator
;
20 import java
.util
.List
;
23 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
24 import org
.eclipse
.core
.runtime
.IStatus
;
25 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
26 import org
.eclipse
.core
.runtime
.Status
;
27 import org
.eclipse
.core
.runtime
.jobs
.Job
;
28 import org
.eclipse
.jdt
.annotation
.Nullable
;
29 import org
.eclipse
.jface
.action
.Action
;
30 import org
.eclipse
.jface
.action
.IAction
;
31 import org
.eclipse
.jface
.action
.IStatusLineManager
;
32 import org
.eclipse
.jface
.action
.IToolBarManager
;
33 import org
.eclipse
.jface
.action
.Separator
;
34 import org
.eclipse
.jface
.util
.IPropertyChangeListener
;
35 import org
.eclipse
.jface
.util
.PropertyChangeEvent
;
36 import org
.eclipse
.jface
.viewers
.DoubleClickEvent
;
37 import org
.eclipse
.jface
.viewers
.IDoubleClickListener
;
38 import org
.eclipse
.jface
.viewers
.ILabelProviderListener
;
39 import org
.eclipse
.jface
.viewers
.ISelection
;
40 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
41 import org
.eclipse
.jface
.viewers
.ITableLabelProvider
;
42 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
43 import org
.eclipse
.jface
.viewers
.Viewer
;
44 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.Activator
;
45 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.ITmfImageConstants
;
46 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.Messages
;
47 import org
.eclipse
.linuxtools
.tmf
.core
.callstack
.CallStackStateProvider
;
48 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.AttributeNotFoundException
;
49 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.StateSystemDisposedException
;
50 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.StateValueTypeException
;
51 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.TimeRangeException
;
52 import org
.eclipse
.linuxtools
.tmf
.core
.interval
.ITmfStateInterval
;
53 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfRangeSynchSignal
;
54 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfSignalHandler
;
55 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTimeSynchSignal
;
56 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceClosedSignal
;
57 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceOpenedSignal
;
58 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
59 import org
.eclipse
.linuxtools
.tmf
.core
.statesystem
.ITmfStateSystem
;
60 import org
.eclipse
.linuxtools
.tmf
.core
.statevalue
.ITmfStateValue
;
61 import org
.eclipse
.linuxtools
.tmf
.core
.statevalue
.ITmfStateValue
.Type
;
62 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.ITmfTimestamp
;
63 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.TmfNanoTimestamp
;
64 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.TmfTimeRange
;
65 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.TmfTimestamp
;
66 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.TmfTimestampDelta
;
67 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
68 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfExperiment
;
69 import org
.eclipse
.linuxtools
.tmf
.ui
.editors
.ITmfTraceEditor
;
70 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.TmfView
;
71 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphRangeListener
;
72 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphTimeListener
;
73 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphCombo
;
74 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphRangeUpdateEvent
;
75 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphTimeEvent
;
76 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphViewer
;
77 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
78 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
79 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.NullTimeEvent
;
80 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.TimeEvent
;
81 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.TimeGraphControl
;
82 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.TimeGraphSelection
;
83 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.TimeFormat
;
84 import org
.eclipse
.swt
.SWT
;
85 import org
.eclipse
.swt
.events
.ControlAdapter
;
86 import org
.eclipse
.swt
.events
.ControlEvent
;
87 import org
.eclipse
.swt
.events
.MouseAdapter
;
88 import org
.eclipse
.swt
.events
.MouseEvent
;
89 import org
.eclipse
.swt
.graphics
.Image
;
90 import org
.eclipse
.swt
.widgets
.Composite
;
91 import org
.eclipse
.swt
.widgets
.Display
;
92 import org
.eclipse
.swt
.widgets
.FileDialog
;
93 import org
.eclipse
.ui
.IActionBars
;
94 import org
.eclipse
.ui
.IEditorPart
;
97 * Main implementation for the Call Stack view
99 * @author Patrick Tasse
102 public class CallStackView
extends TmfView
{
104 // ------------------------------------------------------------------------
106 // ------------------------------------------------------------------------
109 public static final String ID
= "org.eclipse.linuxtools.tmf.ui.views.callstack"; //$NON-NLS-1$
114 private enum State
{ IDLE
, BUSY
, PENDING
}
116 private static final String
[] COLUMN_NAMES
= new String
[] {
117 Messages
.CallStackView_FunctionColumn
,
118 Messages
.CallStackView_DepthColumn
,
119 Messages
.CallStackView_EntryTimeColumn
,
120 Messages
.CallStackView_ExitTimeColumn
,
121 Messages
.CallStackView_DurationColumn
124 private static final int[] COLUMN_WIDTHS
= new int[] {
132 // Fraction of a function duration to be added as spacing
133 private static final double SPACING_RATIO
= 0.01;
135 private static final Image THREAD_IMAGE
= Activator
.getDefault().getImageFromPath("icons/obj16/thread_obj.gif"); //$NON-NLS-1$
136 private static final Image STACKFRAME_IMAGE
= Activator
.getDefault().getImageFromPath("icons/obj16/stckframe_obj.gif"); //$NON-NLS-1$
138 private static final String IMPORT_MAPPING_ICON_PATH
= "icons/etool16/import.gif"; //$NON-NLS-1$
140 // ------------------------------------------------------------------------
142 // ------------------------------------------------------------------------
144 // The time graph combo
145 private TimeGraphCombo fTimeGraphCombo
;
147 // The selected trace
148 private ITmfTrace fTrace
;
150 // The selected thread map
151 private final Map
<ITmfTrace
, String
> fSelectedThreadMap
= new HashMap
<>();
153 // The time graph entry list
154 private List
<ThreadEntry
> fEntryList
;
156 // The trace to entry list hash map
157 private final Map
<ITmfTrace
, ArrayList
<ThreadEntry
>> fEntryListMap
= new HashMap
<>();
159 // The trace to build thread hash map
160 private final Map
<ITmfTrace
, BuildThread
> fBuildThreadMap
= new HashMap
<>();
162 /** The map to map function addresses to function names */
163 private Map
<String
, String
> fNameMapping
;
166 private long fStartTime
;
169 private long fEndTime
;
172 private int fDisplayWidth
;
174 // The next event action
175 private Action fNextEventAction
;
177 // The previous event action
178 private Action fPrevEventAction
;
180 // The next item action
181 private Action fNextItemAction
;
183 // The previous item action
184 private Action fPreviousItemAction
;
186 /** The action to import a function-name mapping file */
187 private Action fImportMappingAction
;
190 private ZoomThread fZoomThread
;
192 // The redraw state used to prevent unnecessary queuing of display runnables
193 private State fRedrawState
= State
.IDLE
;
195 // The redraw synchronization object
196 private final Object fSyncObj
= new Object();
198 // The saved time sync. signal used when switching off the pinning of a view
199 private TmfTimeSynchSignal fSavedTimeSyncSignal
;
201 // The saved time range sync. signal used when switching off the pinning of a view
202 private TmfRangeSynchSignal fSavedRangeSyncSignal
;
204 // ------------------------------------------------------------------------
206 // ------------------------------------------------------------------------
208 private class ThreadEntry
implements ITimeGraphEntry
{
210 private final long fTraceStartTime
;
212 private final long fTraceEndTime
;
213 // The children of the entry
214 private ArrayList
<CallStackEntry
> fChildren
;
216 private final String fName
;
217 // The thread attribute quark
218 private final int fThreadQuark
;
219 // The state system from which this entry comes
220 private final ITmfStateSystem fSS
;
222 public ThreadEntry(ITmfTrace trace
, String name
, int threadQuark
, long startTime
, long endTime
) {
223 fChildren
= new ArrayList
<>();
225 fTraceStartTime
= startTime
;
226 fTraceEndTime
= endTime
;
227 fThreadQuark
= threadQuark
;
229 fSS
= getCallStackStateSystem(trace
);
233 public ITimeGraphEntry
getParent() {
238 public boolean hasChildren() {
239 if (fChildren
== null) {
240 ITmfStateSystem ss
= getStateSystem();
245 int eventStackQuark
= ss
.getQuarkRelative(fThreadQuark
, CallStackStateProvider
.CALL_STACK
);
246 ITmfStateInterval eventStackInterval
= ss
.querySingleState(ss
.getStartTime(), eventStackQuark
);
247 return ! eventStackInterval
.getStateValue().isNull() || eventStackInterval
.getEndTime() != ss
.getCurrentEndTime();
248 } catch (AttributeNotFoundException e
) {
249 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
250 } catch (TimeRangeException e
) {
251 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
252 } catch (StateSystemDisposedException e
) {
256 return fChildren
!= null && fChildren
.size() > 0;
260 public List
<CallStackEntry
> getChildren() {
265 public String
getName() {
270 public long getStartTime() {
271 return fTraceStartTime
;
275 public long getEndTime() {
276 return fTraceEndTime
;
280 public boolean hasTimeEvents() {
285 public Iterator
<ITimeEvent
> getTimeEventsIterator() {
290 public <T
extends ITimeEvent
> Iterator
<T
> getTimeEventsIterator(long startTime
, long stopTime
, long visibleDuration
) {
294 public int getThreadQuark() {
299 public ITmfStateSystem
getStateSystem() {
303 public void addChild(CallStackEntry entry
) {
304 entry
.setParent(this);
305 fChildren
.add(entry
);
309 private class TreeContentProvider
implements ITreeContentProvider
{
312 public void dispose() {
316 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
320 public Object
[] getElements(Object inputElement
) {
321 return (ITimeGraphEntry
[]) inputElement
;
325 public Object
[] getChildren(Object parentElement
) {
326 ITimeGraphEntry entry
= (ITimeGraphEntry
) parentElement
;
327 return entry
.getChildren().toArray();
331 public Object
getParent(Object element
) {
332 ITimeGraphEntry entry
= (ITimeGraphEntry
) element
;
333 return entry
.getParent();
337 public boolean hasChildren(Object element
) {
338 ITimeGraphEntry entry
= (ITimeGraphEntry
) element
;
339 return entry
.hasChildren();
344 private class TreeLabelProvider
implements ITableLabelProvider
{
347 public void addListener(ILabelProviderListener listener
) {
351 public void dispose() {
355 public boolean isLabelProperty(Object element
, String property
) {
360 public void removeListener(ILabelProviderListener listener
) {
364 public Image
getColumnImage(Object element
, int columnIndex
) {
365 if (columnIndex
== 0) {
366 if (element
instanceof ThreadEntry
) {
368 } else if (element
instanceof CallStackEntry
) {
369 CallStackEntry entry
= (CallStackEntry
) element
;
370 if (entry
.getFunctionName().length() > 0) {
371 return STACKFRAME_IMAGE
;
379 public String
getColumnText(Object element
, int columnIndex
) {
380 if (element
instanceof ThreadEntry
) {
381 if (columnIndex
== 0) {
382 return ((ThreadEntry
) element
).getName();
384 } else if (element
instanceof CallStackEntry
) {
385 CallStackEntry entry
= (CallStackEntry
) element
;
386 if (columnIndex
== 0) {
387 return entry
.getFunctionName();
388 } else if (columnIndex
== 1 && entry
.getFunctionName().length() > 0) {
389 int depth
= entry
.getStackLevel();
390 return Integer
.toString(depth
);
391 } else if (columnIndex
== 2 && entry
.getFunctionName().length() > 0) {
392 ITmfTimestamp ts
= new TmfTimestamp(entry
.getStartTime(), ITmfTimestamp
.NANOSECOND_SCALE
);
393 return ts
.toString();
394 } else if (columnIndex
== 3 && entry
.getFunctionName().length() > 0) {
395 ITmfTimestamp ts
= new TmfTimestamp(entry
.getEndTime(), ITmfTimestamp
.NANOSECOND_SCALE
);
396 return ts
.toString();
397 } else if (columnIndex
== 4 && entry
.getFunctionName().length() > 0) {
398 ITmfTimestamp ts
= new TmfTimestampDelta(entry
.getEndTime() - entry
.getStartTime(), ITmfTimestamp
.NANOSECOND_SCALE
);
399 return ts
.toString();
402 return ""; //$NON-NLS-1$
407 private class BuildThread
extends Thread
{
408 private final ITmfTrace fBuildTrace
;
409 private final IProgressMonitor fMonitor
;
411 public BuildThread(ITmfTrace trace
) {
412 super("CallStackView build"); //$NON-NLS-1$
414 fMonitor
= new NullProgressMonitor();
419 buildThreadList(fBuildTrace
, fMonitor
);
420 synchronized (fBuildThreadMap
) {
421 fBuildThreadMap
.remove(this);
425 public void cancel() {
426 fMonitor
.setCanceled(true);
430 private class ZoomThread
extends Thread
{
431 private final List
<ThreadEntry
> fZoomEntryList
;
432 private final long fZoomStartTime
;
433 private final long fZoomEndTime
;
434 private final IProgressMonitor fMonitor
;
436 public ZoomThread(List
<ThreadEntry
> entryList
, long startTime
, long endTime
) {
437 super("ResourcesView zoom"); //$NON-NLS-1$
438 fZoomEntryList
= entryList
;
439 fZoomStartTime
= startTime
;
440 fZoomEndTime
= endTime
;
441 fMonitor
= new NullProgressMonitor();
446 if (fZoomEntryList
== null) {
449 long resolution
= Math
.max(1, (fZoomEndTime
- fZoomStartTime
) / fDisplayWidth
);
450 for (ThreadEntry threadEntry
: fZoomEntryList
) {
451 ITmfStateSystem ss
= threadEntry
.getStateSystem();
456 if (ss
.isCancelled()) {
459 for (ITimeGraphEntry child
: threadEntry
.getChildren()) {
460 if (fMonitor
.isCanceled()) {
463 CallStackEntry entry
= (CallStackEntry
) child
;
464 if (fZoomStartTime
<= fStartTime
&& fZoomEndTime
>= fEndTime
) {
465 entry
.setZoomedEventList(null);
467 List
<ITimeEvent
> zoomedEventList
= getEventList(entry
, fZoomStartTime
, fZoomEndTime
, resolution
, fMonitor
);
468 if (zoomedEventList
!= null) {
469 entry
.setZoomedEventList(zoomedEventList
);
477 public void cancel() {
478 fMonitor
.setCanceled(true);
482 // ------------------------------------------------------------------------
484 // ------------------------------------------------------------------------
487 * Default constructor
489 public CallStackView() {
491 fDisplayWidth
= Display
.getDefault().getBounds().width
;
494 // ------------------------------------------------------------------------
496 // ------------------------------------------------------------------------
499 public void createPartControl(Composite parent
) {
500 fTimeGraphCombo
= new TimeGraphCombo(parent
, SWT
.NONE
);
502 fTimeGraphCombo
.setTreeContentProvider(new TreeContentProvider());
504 fTimeGraphCombo
.setTreeLabelProvider(new TreeLabelProvider());
506 fTimeGraphCombo
.setTreeColumns(COLUMN_NAMES
);
508 fTimeGraphCombo
.getTreeViewer().getTree().getColumn(0).setWidth(COLUMN_WIDTHS
[0]);
509 fTimeGraphCombo
.getTreeViewer().getTree().getColumn(1).setWidth(COLUMN_WIDTHS
[1]);
510 fTimeGraphCombo
.getTreeViewer().getTree().getColumn(2).setWidth(COLUMN_WIDTHS
[2]);
511 fTimeGraphCombo
.getTreeViewer().getTree().getColumn(3).setWidth(COLUMN_WIDTHS
[3]);
512 fTimeGraphCombo
.getTreeViewer().getTree().getColumn(4).setWidth(COLUMN_WIDTHS
[4]);
514 fTimeGraphCombo
.setTimeGraphProvider(new CallStackPresentationProvider(this));
515 fTimeGraphCombo
.getTimeGraphViewer().setTimeFormat(TimeFormat
.CALENDAR
);
517 fTimeGraphCombo
.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
519 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event
) {
520 long startTime
= event
.getStartTime();
521 long endTime
= event
.getEndTime();
522 TmfTimeRange range
= new TmfTimeRange(new TmfNanoTimestamp(startTime
), new TmfNanoTimestamp(endTime
));
523 broadcast(new TmfRangeSynchSignal(CallStackView
.this, range
));
524 startZoomThread(startTime
, endTime
);
528 fTimeGraphCombo
.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
530 public void timeSelected(TimeGraphTimeEvent event
) {
531 long beginTime
= event
.getBeginTime();
532 long endTime
= event
.getEndTime();
533 selectTime(beginTime
);
534 broadcast(new TmfTimeSynchSignal(CallStackView
.this, new TmfNanoTimestamp(beginTime
), new TmfNanoTimestamp(endTime
)));
538 fTimeGraphCombo
.getTimeGraphViewer().getControl().addControlListener(new ControlAdapter() {
540 public void controlResized(ControlEvent e
) {
541 fDisplayWidth
= fTimeGraphCombo
.getTimeGraphViewer().getControl().getSize().x
;
542 if (fEntryList
!= null) {
543 startZoomThread(fTimeGraphCombo
.getTimeGraphViewer().getTime0(), fTimeGraphCombo
.getTimeGraphViewer().getTime1());
548 fTimeGraphCombo
.getTreeViewer().addDoubleClickListener(new IDoubleClickListener() {
550 public void doubleClick(DoubleClickEvent event
) {
551 Object selection
= ((IStructuredSelection
) event
.getSelection()).getFirstElement();
552 if (selection
instanceof CallStackEntry
) {
553 CallStackEntry entry
= (CallStackEntry
) selection
;
554 if (entry
.getFunctionName().length() > 0) {
555 long startTime
= entry
.getStartTime();
556 long endTime
= entry
.getEndTime();
557 long spacingTime
= (long) ((endTime
- startTime
) * SPACING_RATIO
);
558 startTime
-= spacingTime
;
559 endTime
+= spacingTime
;
560 TmfTimeRange range
= new TmfTimeRange(new TmfNanoTimestamp(startTime
), new TmfNanoTimestamp(endTime
));
561 broadcast(new TmfRangeSynchSignal(CallStackView
.this, range
));
562 fTimeGraphCombo
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
563 startZoomThread(startTime
, endTime
);
569 fTimeGraphCombo
.getTimeGraphViewer().getTimeGraphControl().addMouseListener(new MouseAdapter() {
571 public void mouseDoubleClick(MouseEvent e
) {
572 TimeGraphControl timeGraphControl
= fTimeGraphCombo
.getTimeGraphViewer().getTimeGraphControl();
573 ISelection selection
= timeGraphControl
.getSelection();
574 if (selection
instanceof TimeGraphSelection
) {
575 Object o
= ((TimeGraphSelection
) selection
).getFirstElement();
576 if (o
instanceof CallStackEvent
) {
577 CallStackEvent event
= (CallStackEvent
) o
;
578 long startTime
= event
.getTime();
579 long endTime
= startTime
+ event
.getDuration();
580 long spacingTime
= (long) ((endTime
- startTime
) * SPACING_RATIO
);
581 startTime
-= spacingTime
;
582 endTime
+= spacingTime
;
583 TmfTimeRange range
= new TmfTimeRange(new TmfNanoTimestamp(startTime
), new TmfNanoTimestamp(endTime
));
584 broadcast(new TmfRangeSynchSignal(CallStackView
.this, range
));
585 fTimeGraphCombo
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
586 startZoomThread(startTime
, endTime
);
592 IStatusLineManager statusLineManager
= getViewSite().getActionBars().getStatusLineManager();
593 fTimeGraphCombo
.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager
);
595 // View Action Handling
597 contributeToActionBars();
599 IEditorPart editor
= getSite().getPage().getActiveEditor();
600 if (editor
instanceof ITmfTraceEditor
) {
601 ITmfTrace trace
= ((ITmfTraceEditor
) editor
).getTrace();
603 traceSelected(new TmfTraceSelectedSignal(this, trace
));
609 public void setFocus() {
610 fTimeGraphCombo
.setFocus();
613 // ------------------------------------------------------------------------
615 // ------------------------------------------------------------------------
617 * Handler for the trace opened signal.
619 * The incoming signal
623 public void traceOpened(TmfTraceOpenedSignal signal
) {
624 fTrace
= signal
.getTrace();
629 * Handler for the trace selected signal
632 * The incoming signal
635 public void traceSelected(final TmfTraceSelectedSignal signal
) {
636 if (signal
.getTrace() == fTrace
) {
639 fTrace
= signal
.getTrace();
644 * Trace is closed: clear the data structures and the view
646 * @param signal the signal received
649 public void traceClosed(final TmfTraceClosedSignal signal
) {
650 synchronized (fBuildThreadMap
) {
651 BuildThread buildThread
= fBuildThreadMap
.remove(signal
.getTrace());
652 if (buildThread
!= null) {
653 buildThread
.cancel();
656 synchronized (fEntryListMap
) {
657 fEntryListMap
.remove(signal
.getTrace());
659 fSelectedThreadMap
.remove(signal
.getTrace());
660 if (signal
.getTrace() == fTrace
) {
669 * Handler for the TimeSynch signal
672 * The incoming signal
675 public void synchToTime(final TmfTimeSynchSignal signal
) {
677 fSavedTimeSyncSignal
= isPinned() ?
new TmfTimeSynchSignal(signal
.getSource(), signal
.getBeginTime(), signal
.getEndTime()) : null;
679 if (signal
.getSource() == this || fTrace
== null || isPinned()) {
682 final long beginTime
= signal
.getBeginTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
683 final long endTime
= signal
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
684 Display
.getDefault().asyncExec(new Runnable() {
687 if (fTimeGraphCombo
.isDisposed()) {
690 if (beginTime
== endTime
) {
691 fTimeGraphCombo
.getTimeGraphViewer().setSelectedTime(beginTime
, true);
693 fTimeGraphCombo
.getTimeGraphViewer().setSelectionRange(beginTime
, endTime
);
695 selectTime(beginTime
);
696 startZoomThread(fTimeGraphCombo
.getTimeGraphViewer().getTime0(), fTimeGraphCombo
.getTimeGraphViewer().getTime1());
697 if (fEntryList
== null) {
700 TimeGraphViewer viewer
= fTimeGraphCombo
.getTimeGraphViewer();
701 for (ThreadEntry threadEntry
: fEntryList
) {
702 ITmfStateSystem ss
= threadEntry
.getStateSystem();
703 if (ss
== null || beginTime
< ss
.getStartTime() || beginTime
> ss
.getCurrentEndTime()) {
707 int quark
= ss
.getQuarkRelative(threadEntry
.getThreadQuark(), CallStackStateProvider
.CALL_STACK
);
708 ITmfStateInterval stackInterval
= ss
.querySingleState(beginTime
, quark
);
709 if (beginTime
== stackInterval
.getStartTime()) {
710 int stackLevel
= stackInterval
.getStateValue().unboxInt();
711 CallStackEntry selectedEntry
= threadEntry
.getChildren().get(Math
.max(0, stackLevel
- 1));
712 fTimeGraphCombo
.setSelection(selectedEntry
);
713 viewer
.getTimeGraphControl().fireSelectionChanged();
716 } catch (AttributeNotFoundException e
) {
717 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
718 } catch (TimeRangeException e
) {
719 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
720 } catch (StateSystemDisposedException e
) {
721 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
722 } catch (StateValueTypeException e
) {
723 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
731 * Handler for the RangeSynch signal
734 * The incoming signal
737 public void synchToRange(final TmfRangeSynchSignal signal
) {
740 fSavedRangeSyncSignal
=
741 new TmfRangeSynchSignal(signal
.getSource(), new TmfTimeRange(signal
.getCurrentRange().getStartTime(), signal
.getCurrentRange().getEndTime()));
743 fSavedTimeSyncSignal
= null;
746 if (signal
.getSource() == this || fTrace
== null || isPinned()) {
749 if (signal
.getCurrentRange().getIntersection(fTrace
.getTimeRange()) == null) {
752 final long startTime
= signal
.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
753 final long endTime
= signal
.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
754 Display
.getDefault().asyncExec(new Runnable() {
757 if (fTimeGraphCombo
.isDisposed()) {
760 fTimeGraphCombo
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
761 startZoomThread(startTime
, endTime
);
766 // ------------------------------------------------------------------------
768 // ------------------------------------------------------------------------
770 private void loadTrace() {
771 synchronized (fEntryListMap
) {
772 fEntryList
= fEntryListMap
.get(fTrace
);
773 if (fEntryList
== null) {
774 synchronized (fBuildThreadMap
) {
775 BuildThread buildThread
= new BuildThread(fTrace
);
776 fBuildThreadMap
.put(fTrace
, buildThread
);
780 fStartTime
= fTrace
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
781 fEndTime
= fTrace
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
787 private void buildThreadList(final ITmfTrace trace
, IProgressMonitor monitor
) {
788 fStartTime
= Long
.MAX_VALUE
;
789 fEndTime
= Long
.MIN_VALUE
;
791 if (trace
instanceof TmfExperiment
) {
792 TmfExperiment experiment
= (TmfExperiment
) trace
;
793 traces
= experiment
.getTraces();
795 traces
= new ITmfTrace
[] { trace
};
797 ArrayList
<ThreadEntry
> entryList
= new ArrayList
<>();
798 for (ITmfTrace aTrace
: traces
) {
799 if (monitor
.isCanceled()) {
802 ITmfStateSystem ss
= getCallStackStateSystem(aTrace
);
804 addUnavailableEntry(aTrace
, entryList
);
808 if (ss
.isCancelled()) {
809 addUnavailableEntry(aTrace
, entryList
);
812 long startTime
= ss
.getStartTime();
813 long endTime
= ss
.getCurrentEndTime() + 1;
814 fStartTime
= Math
.min(fStartTime
, startTime
);
815 fEndTime
= Math
.max(fEndTime
, endTime
);
816 List
<Integer
> threadQuarks
= ss
.getQuarks(CallStackStateProvider
.THREADS
, "*"); //$NON-NLS-1$
817 for (int i
= 0; i
< threadQuarks
.size(); i
++) {
818 if (monitor
.isCanceled()) {
821 int threadQuark
= threadQuarks
.get(i
);
822 String thread
= ss
.getAttributeName(threadQuark
);
823 String threadEntryName
= thread
+ ' ' + '(' + aTrace
.getName() + ')';
824 ThreadEntry threadEntry
= new ThreadEntry(aTrace
, threadEntryName
, threadQuark
, startTime
, endTime
);
825 entryList
.add(threadEntry
);
828 eventStackQuark
= ss
.getQuarkRelative(threadQuark
, CallStackStateProvider
.CALL_STACK
);
830 for (int stackLevelQuark
: ss
.getSubAttributes(eventStackQuark
, false)) {
831 CallStackEntry callStackEntry
= new CallStackEntry(stackLevelQuark
, level
++, aTrace
);
832 threadEntry
.addChild(callStackEntry
);
834 } catch (AttributeNotFoundException e
) {
835 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
839 synchronized (fEntryListMap
) {
840 fEntryListMap
.put(trace
, new ArrayList
<>(entryList
));
842 if (trace
== fTrace
) {
845 for (ThreadEntry threadEntry
: entryList
) {
846 for (CallStackEntry callStackEntry
: threadEntry
.getChildren()) {
847 if (monitor
.isCanceled()) {
850 buildStatusEvents(trace
, callStackEntry
, monitor
);
855 private void addUnavailableEntry(ITmfTrace trace
, List
<ThreadEntry
> list
) {
856 String threadName
= Messages
.CallStackView_StackInfoNotAvailable
+ ' ' + '(' + trace
.getName() + ')';
857 ThreadEntry threadEntry
= new ThreadEntry(trace
, threadName
, -1, 0, 0);
858 list
.add(threadEntry
);
861 private void buildStatusEvents(ITmfTrace trace
, CallStackEntry entry
, IProgressMonitor monitor
) {
862 ITmfStateSystem ss
= getCallStackStateSystem(entry
.getTrace());
866 long start
= ss
.getStartTime();
867 long end
= ss
.getCurrentEndTime() + 1;
868 long resolution
= Math
.max(1, (end
- start
) / fDisplayWidth
);
869 List
<ITimeEvent
> eventList
= getEventList(entry
, start
, end
, resolution
, monitor
);
870 if (monitor
.isCanceled()) {
873 entry
.setEventList(eventList
);
874 if (trace
== fTrace
) {
879 private static List
<ITimeEvent
> getEventList(CallStackEntry entry
,
880 long startTime
, long endTime
, long resolution
,
881 IProgressMonitor monitor
) {
882 ITmfStateSystem ss
= getCallStackStateSystem(entry
.getTrace());
886 long start
= Math
.max(startTime
, ss
.getStartTime());
887 long end
= Math
.min(endTime
, ss
.getCurrentEndTime() + 1);
891 List
<ITimeEvent
> eventList
= null;
893 List
<ITmfStateInterval
> stackIntervals
= ss
.queryHistoryRange(entry
.getQuark(), start
, end
- 1, resolution
, monitor
);
894 eventList
= new ArrayList
<>(stackIntervals
.size());
895 long lastEndTime
= -1;
896 boolean lastIsNull
= true;
897 for (ITmfStateInterval statusInterval
: stackIntervals
) {
898 if (monitor
.isCanceled()) {
901 long time
= statusInterval
.getStartTime();
902 long duration
= statusInterval
.getEndTime() - time
+ 1;
903 if (!statusInterval
.getStateValue().isNull()) {
904 final int modulo
= CallStackPresentationProvider
.NUM_COLORS
/ 2;
905 int value
= statusInterval
.getStateValue().toString().hashCode() % modulo
+ modulo
;
906 eventList
.add(new CallStackEvent(entry
, time
, duration
, value
));
909 if (lastEndTime
== -1) {
910 // add null event if it intersects the start time
911 eventList
.add(new NullTimeEvent(entry
, time
, duration
));
913 if (lastEndTime
!= time
&& lastIsNull
) {
914 // add unknown event if between two null states
915 eventList
.add(new TimeEvent(entry
, lastEndTime
, time
- lastEndTime
));
917 if (time
+ duration
>= endTime
) {
918 // add null event if it intersects the end time
919 eventList
.add(new NullTimeEvent(entry
, time
, duration
));
924 lastEndTime
= time
+ duration
;
926 } catch (AttributeNotFoundException e
) {
927 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
928 } catch (TimeRangeException e
) {
929 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
930 } catch (StateSystemDisposedException e
) {
936 private void selectTime(long time
) {
937 if (fEntryList
== null) {
940 for (ThreadEntry threadEntry
: fEntryList
) {
941 ITmfStateSystem ss
= threadEntry
.getStateSystem();
946 if (ss
.isCancelled()) {
949 long queryTime
= Math
.max(ss
.getStartTime(), Math
.min(ss
.getCurrentEndTime(), time
));
950 for (CallStackEntry callStackEntry
: threadEntry
.getChildren()) {
952 ITmfStateInterval stackLevelInterval
= ss
.querySingleState(queryTime
, callStackEntry
.getQuark());
953 ITmfStateValue nameValue
= stackLevelInterval
.getStateValue();
954 String name
= ""; //$NON-NLS-1$
956 if (nameValue
.getType() == Type
.STRING
) {
957 String address
= nameValue
.unboxStr();
958 name
= getFunctionName(address
);
959 } else if (nameValue
.getType() == Type
.INTEGER
) {
960 name
= "0x" + Integer
.toHexString(nameValue
.unboxInt()); //$NON-NLS-1$
961 } else if (nameValue
.getType() == Type
.LONG
) {
962 name
= "0x" + Long
.toHexString(nameValue
.unboxLong()); //$NON-NLS-1$
964 } catch (StateValueTypeException e
) {
966 callStackEntry
.setFunctionName(name
);
967 if (name
.length() > 0) {
968 callStackEntry
.setStartTime(stackLevelInterval
.getStartTime());
969 callStackEntry
.setEndTime(stackLevelInterval
.getEndTime() + 1);
971 } catch (AttributeNotFoundException e
) {
972 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
973 } catch (TimeRangeException e
) {
974 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
975 } catch (StateSystemDisposedException e
) {
976 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
980 fTimeGraphCombo
.refresh();
983 private void refresh() {
984 Display
.getDefault().asyncExec(new Runnable() {
987 if (fTimeGraphCombo
.isDisposed()) {
990 ITimeGraphEntry
[] entries
= null;
991 synchronized (fEntryListMap
) {
992 fEntryList
= fEntryListMap
.get(fTrace
);
993 if (fEntryList
== null) {
994 fEntryList
= new ArrayList
<>();
996 entries
= fEntryList
.toArray(new ITimeGraphEntry
[0]);
998 fTimeGraphCombo
.setInput(entries
);
999 fTimeGraphCombo
.getTimeGraphViewer().setTimeBounds(fStartTime
, fEndTime
);
1001 long selectionBeginTime
= fTrace
== null ?
0 : fTraceManager
.getSelectionBeginTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1002 long selectionEndTime
= fTrace
== null ?
0 : fTraceManager
.getSelectionEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1003 long startTime
= fTrace
== null ?
0 : fTraceManager
.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1004 long endTime
= fTrace
== null ?
0 : fTraceManager
.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1005 startTime
= Math
.max(startTime
, fStartTime
);
1006 endTime
= Math
.min(endTime
, fEndTime
);
1007 fTimeGraphCombo
.getTimeGraphViewer().setSelectionRange(selectionBeginTime
, selectionEndTime
);
1008 selectTime(selectionBeginTime
);
1009 fTimeGraphCombo
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
1010 startZoomThread(startTime
, endTime
);
1015 private void redraw() {
1016 synchronized (fSyncObj
) {
1017 if (fRedrawState
== State
.IDLE
) {
1018 fRedrawState
= State
.BUSY
;
1020 fRedrawState
= State
.PENDING
;
1024 Display
.getDefault().asyncExec(new Runnable() {
1027 if (fTimeGraphCombo
.isDisposed()) {
1030 fTimeGraphCombo
.redraw();
1031 fTimeGraphCombo
.update();
1032 synchronized (fSyncObj
) {
1033 if (fRedrawState
== State
.PENDING
) {
1034 fRedrawState
= State
.IDLE
;
1037 fRedrawState
= State
.IDLE
;
1044 private void startZoomThread(long startTime
, long endTime
) {
1045 if (fZoomThread
!= null) {
1046 fZoomThread
.cancel();
1048 fZoomThread
= new ZoomThread(fEntryList
, startTime
, endTime
);
1049 fZoomThread
.start();
1052 private void makeActions() {
1053 fPreviousItemAction
= fTimeGraphCombo
.getTimeGraphViewer().getPreviousItemAction();
1054 fPreviousItemAction
.setText(Messages
.TmfTimeGraphViewer_PreviousItemActionNameText
);
1055 fPreviousItemAction
.setToolTipText(Messages
.TmfTimeGraphViewer_PreviousItemActionToolTipText
);
1056 fNextItemAction
= fTimeGraphCombo
.getTimeGraphViewer().getNextItemAction();
1057 fNextItemAction
.setText(Messages
.TmfTimeGraphViewer_NextItemActionNameText
);
1058 fNextItemAction
.setToolTipText(Messages
.TmfTimeGraphViewer_NextItemActionToolTipText
);
1061 private void contributeToActionBars() {
1062 IActionBars bars
= getViewSite().getActionBars();
1063 fillLocalToolBar(bars
.getToolBarManager());
1065 // Create pin action
1066 contributePinActionToToolBar();
1067 fPinAction
.addPropertyChangeListener(new IPropertyChangeListener(){
1069 public void propertyChange(PropertyChangeEvent event
) {
1070 if (IAction
.CHECKED
.equals(event
.getProperty()) && !isPinned()) {
1071 if (fSavedRangeSyncSignal
!= null) {
1072 synchToRange(fSavedRangeSyncSignal
);
1073 fSavedRangeSyncSignal
= null;
1076 if (fSavedTimeSyncSignal
!= null) {
1077 synchToTime(fSavedTimeSyncSignal
);
1078 fSavedTimeSyncSignal
= null;
1085 private void fillLocalToolBar(IToolBarManager manager
) {
1086 manager
.add(getImportMappingAction());
1087 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getResetScaleAction());
1088 manager
.add(getPreviousEventAction());
1089 manager
.add(getNextEventAction());
1090 manager
.add(fPreviousItemAction
);
1091 manager
.add(fNextItemAction
);
1092 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getZoomInAction());
1093 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getZoomOutAction());
1094 manager
.add(new Separator());
1098 * Get the the next event action.
1100 * @return The action object
1102 private Action
getNextEventAction() {
1103 if (fNextEventAction
== null) {
1104 fNextEventAction
= new Action() {
1107 TimeGraphViewer viewer
= fTimeGraphCombo
.getTimeGraphViewer();
1108 ITimeGraphEntry entry
= viewer
.getSelection();
1109 if (entry
instanceof CallStackEntry
) {
1111 CallStackEntry callStackEntry
= (CallStackEntry
) entry
;
1112 ITmfTrace trace
= callStackEntry
.getTrace();
1113 ITmfStateSystem ss
= getCallStackStateSystem(trace
);
1117 long time
= Math
.max(ss
.getStartTime(), Math
.min(ss
.getCurrentEndTime(), viewer
.getSelectionBegin()));
1118 ThreadEntry threadEntry
= (ThreadEntry
) callStackEntry
.getParent();
1119 int quark
= ss
.getQuarkRelative(threadEntry
.getThreadQuark(), CallStackStateProvider
.CALL_STACK
);
1120 ITmfStateInterval stackInterval
= ss
.querySingleState(time
, quark
);
1121 long newTime
= stackInterval
.getEndTime() + 1;
1122 viewer
.setSelectedTimeNotify(newTime
, true);
1123 stackInterval
= ss
.querySingleState(Math
.min(ss
.getCurrentEndTime(), newTime
), quark
);
1124 int stackLevel
= stackInterval
.getStateValue().unboxInt();
1125 CallStackEntry selectedEntry
= threadEntry
.getChildren().get(Math
.max(0, stackLevel
- 1));
1126 fTimeGraphCombo
.setSelection(selectedEntry
);
1127 viewer
.getTimeGraphControl().fireSelectionChanged();
1128 startZoomThread(viewer
.getTime0(), viewer
.getTime1());
1130 } catch (AttributeNotFoundException e
) {
1131 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
1132 } catch (TimeRangeException e
) {
1133 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
1134 } catch (StateSystemDisposedException e
) {
1135 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
1136 } catch (StateValueTypeException e
) {
1137 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
1143 fNextEventAction
.setText(Messages
.TmfTimeGraphViewer_NextEventActionNameText
);
1144 fNextEventAction
.setToolTipText(Messages
.TmfTimeGraphViewer_NextEventActionToolTipText
);
1145 fNextEventAction
.setImageDescriptor(Activator
.getDefault().getImageDescripterFromPath(ITmfImageConstants
.IMG_UI_NEXT_EVENT
));
1148 return fNextEventAction
;
1152 * Get the previous event action.
1154 * @return The Action object
1156 private Action
getPreviousEventAction() {
1157 if (fPrevEventAction
== null) {
1158 fPrevEventAction
= new Action() {
1161 TimeGraphViewer viewer
= fTimeGraphCombo
.getTimeGraphViewer();
1162 ITimeGraphEntry entry
= viewer
.getSelection();
1163 if (entry
instanceof CallStackEntry
) {
1165 CallStackEntry callStackEntry
= (CallStackEntry
) entry
;
1166 ITmfTrace trace
= callStackEntry
.getTrace();
1167 ITmfStateSystem ss
= getCallStackStateSystem(trace
);
1171 long time
= Math
.max(ss
.getStartTime(), Math
.min(ss
.getCurrentEndTime(), viewer
.getSelectionBegin()));
1172 ThreadEntry threadEntry
= (ThreadEntry
) callStackEntry
.getParent();
1173 int quark
= ss
.getQuarkRelative(threadEntry
.getThreadQuark(), CallStackStateProvider
.CALL_STACK
);
1174 ITmfStateInterval stackInterval
= ss
.querySingleState(time
, quark
);
1175 if (stackInterval
.getStartTime() == time
&& time
> ss
.getStartTime()) {
1176 stackInterval
= ss
.querySingleState(time
- 1, quark
);
1178 viewer
.setSelectedTimeNotify(stackInterval
.getStartTime(), true);
1179 int stackLevel
= stackInterval
.getStateValue().unboxInt();
1180 CallStackEntry selectedEntry
= threadEntry
.getChildren().get(Math
.max(0, stackLevel
- 1));
1181 fTimeGraphCombo
.setSelection(selectedEntry
);
1182 viewer
.getTimeGraphControl().fireSelectionChanged();
1183 startZoomThread(viewer
.getTime0(), viewer
.getTime1());
1185 } catch (AttributeNotFoundException e
) {
1186 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
1187 } catch (TimeRangeException e
) {
1188 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
1189 } catch (StateSystemDisposedException e
) {
1190 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
1191 } catch (StateValueTypeException e
) {
1192 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
1198 fPrevEventAction
.setText(Messages
.TmfTimeGraphViewer_PreviousEventActionNameText
);
1199 fPrevEventAction
.setToolTipText(Messages
.TmfTimeGraphViewer_PreviousEventActionToolTipText
);
1200 fPrevEventAction
.setImageDescriptor(Activator
.getDefault().getImageDescripterFromPath(ITmfImageConstants
.IMG_UI_PREV_EVENT
));
1203 return fPrevEventAction
;
1207 static ITmfStateSystem
getCallStackStateSystem(ITmfTrace trace
) {
1209 * Since we cannot know the exact analysis ID (in separate plugins), we
1210 * will search using the analysis type.
1212 Iterable
<AbstractCallStackAnalysis
> modules
=
1213 trace
.getAnalysisModulesOfClass(AbstractCallStackAnalysis
.class);
1214 Iterator
<AbstractCallStackAnalysis
> it
= modules
.iterator();
1215 if (!it
.hasNext()) {
1216 /* This trace does not provide a call-stack analysis */
1221 * We only look at the first module we find.
1223 * TODO Handle the advanced case where one trace provides more than one
1224 * call-stack analysis.
1226 AbstractCallStackAnalysis module
= it
.next();
1227 /* This analysis is not automatic, we need to schedule it on-demand */
1229 module
.waitForInitialization();
1230 ITmfStateSystem ss
= module
.getStateSystem();
1232 /* If we've waited for initialization, 'ss' should not be null */
1233 throw new IllegalStateException();
1238 // ------------------------------------------------------------------------
1239 // Methods related to function name mapping
1240 // ------------------------------------------------------------------------
1243 * Toolbar icon to import the function address-to-name mapping file.
1245 private Action
getImportMappingAction() {
1246 if (fImportMappingAction
!= null) {
1247 return fImportMappingAction
;
1249 fImportMappingAction
= new Action() {
1252 FileDialog dialog
= new FileDialog(getViewSite().getShell());
1253 dialog
.setText(Messages
.CallStackView_ImportMappingDialogTitle
);
1254 String filePath
= dialog
.open();
1255 if (filePath
== null) {
1256 /* No file was selected, don't change anything */
1260 * Start the mapping import in a separate thread (we do not want
1261 * to UI thread to do this).
1263 Job job
= new ImportMappingJob(new File(filePath
));
1268 fImportMappingAction
.setText(Messages
.CallStackView_ImportMappingButtonText
);
1269 fImportMappingAction
.setToolTipText(Messages
.CallStackView_ImportMappingButtonTooltip
);
1270 fImportMappingAction
.setImageDescriptor(Activator
.getDefault().getImageDescripterFromPath(IMPORT_MAPPING_ICON_PATH
));
1272 return fImportMappingAction
;
1275 private class ImportMappingJob
extends Job
{
1276 private final File fMappingFile
;
1278 public ImportMappingJob(File mappingFile
) {
1279 super(Messages
.CallStackView_ImportMappingJobName
);
1280 fMappingFile
= mappingFile
;
1284 public IStatus
run(IProgressMonitor monitor
) {
1285 fNameMapping
= FunctionNameMapper
.mapFromNmTextFile(fMappingFile
);
1287 /* Refresh the time graph and the list of entries */
1288 buildThreadList(fTrace
, new NullProgressMonitor());
1291 return Status
.OK_STATUS
;
1295 String
getFunctionName(String address
) {
1296 if (fNameMapping
== null) {
1297 /* No mapping available, just print the addresses */
1300 String ret
= fNameMapping
.get(address
);
1302 /* We didn't find this address in the mapping file, just use the address */