1 /*******************************************************************************
2 * Copyright (c) 2013 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 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.tmf
.ui
.views
.callstack
;
15 import java
.util
.ArrayList
;
16 import java
.util
.HashMap
;
17 import java
.util
.Iterator
;
18 import java
.util
.List
;
20 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
21 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
22 import org
.eclipse
.jface
.action
.Action
;
23 import org
.eclipse
.jface
.action
.IAction
;
24 import org
.eclipse
.jface
.action
.IToolBarManager
;
25 import org
.eclipse
.jface
.action
.Separator
;
26 import org
.eclipse
.jface
.util
.IPropertyChangeListener
;
27 import org
.eclipse
.jface
.util
.PropertyChangeEvent
;
28 import org
.eclipse
.jface
.viewers
.DoubleClickEvent
;
29 import org
.eclipse
.jface
.viewers
.IDoubleClickListener
;
30 import org
.eclipse
.jface
.viewers
.ILabelProviderListener
;
31 import org
.eclipse
.jface
.viewers
.ISelection
;
32 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
33 import org
.eclipse
.jface
.viewers
.ITableLabelProvider
;
34 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
35 import org
.eclipse
.jface
.viewers
.Viewer
;
36 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.Activator
;
37 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.ITmfImageConstants
;
38 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.Messages
;
39 import org
.eclipse
.linuxtools
.tmf
.core
.callstack
.CallStackStateProvider
;
40 import org
.eclipse
.linuxtools
.tmf
.core
.ctfadaptor
.CtfTmfTimestamp
;
41 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.AttributeNotFoundException
;
42 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.StateSystemDisposedException
;
43 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.StateValueTypeException
;
44 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.TimeRangeException
;
45 import org
.eclipse
.linuxtools
.tmf
.core
.interval
.ITmfStateInterval
;
46 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfRangeSynchSignal
;
47 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfSignalHandler
;
48 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTimeSynchSignal
;
49 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceClosedSignal
;
50 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
51 import org
.eclipse
.linuxtools
.tmf
.core
.statesystem
.ITmfStateSystem
;
52 import org
.eclipse
.linuxtools
.tmf
.core
.statevalue
.ITmfStateValue
;
53 import org
.eclipse
.linuxtools
.tmf
.core
.statevalue
.ITmfStateValue
.Type
;
54 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.ITmfTimestamp
;
55 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.TmfTimeRange
;
56 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.TmfTimestamp
;
57 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.TmfTimestampDelta
;
58 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
59 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfExperiment
;
60 import org
.eclipse
.linuxtools
.tmf
.ui
.editors
.ITmfTraceEditor
;
61 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.TmfView
;
62 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphRangeListener
;
63 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphTimeListener
;
64 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphCombo
;
65 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphRangeUpdateEvent
;
66 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphTimeEvent
;
67 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphViewer
;
68 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
69 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
70 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.NullTimeEvent
;
71 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.TimeEvent
;
72 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.TimeGraphControl
;
73 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.TimeGraphSelection
;
74 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.TimeFormat
;
75 import org
.eclipse
.swt
.SWT
;
76 import org
.eclipse
.swt
.events
.ControlAdapter
;
77 import org
.eclipse
.swt
.events
.ControlEvent
;
78 import org
.eclipse
.swt
.events
.MouseAdapter
;
79 import org
.eclipse
.swt
.events
.MouseEvent
;
80 import org
.eclipse
.swt
.graphics
.Image
;
81 import org
.eclipse
.swt
.widgets
.Composite
;
82 import org
.eclipse
.swt
.widgets
.Display
;
83 import org
.eclipse
.ui
.IActionBars
;
84 import org
.eclipse
.ui
.IEditorPart
;
87 * Main implementation for the Call Stack view
89 * @author Patrick Tasse
92 public class CallStackView
extends TmfView
{
94 // ------------------------------------------------------------------------
96 // ------------------------------------------------------------------------
99 public static final String ID
= "org.eclipse.linuxtools.tmf.ui.views.callstack"; //$NON-NLS-1$
104 private enum State
{ IDLE
, BUSY
, PENDING
}
106 private final String
[] COLUMN_NAMES
= new String
[] {
107 Messages
.CallStackView_FunctionColumn
,
108 Messages
.CallStackView_DepthColumn
,
109 Messages
.CallStackView_EntryTimeColumn
,
110 Messages
.CallStackView_ExitTimeColumn
,
111 Messages
.CallStackView_DurationColumn
114 private static final Image THREAD_IMAGE
= Activator
.getDefault().getImageFromPath("icons/obj16/thread_obj.gif"); //$NON-NLS-1$
115 private static final Image STACKFRAME_IMAGE
= Activator
.getDefault().getImageFromPath("icons/obj16/stckframe_obj.gif"); //$NON-NLS-1$
117 // ------------------------------------------------------------------------
119 // ------------------------------------------------------------------------
121 // The time graph combo
122 TimeGraphCombo fTimeGraphCombo
;
124 // The selected trace
125 private ITmfTrace fTrace
;
127 // The selected thread map
128 final private HashMap
<ITmfTrace
, String
> fSelectedThreadMap
= new HashMap
<ITmfTrace
, String
>();
130 // The time graph entry list
131 private ArrayList
<ThreadEntry
> fEntryList
;
133 // The trace to entry list hash map
134 final private HashMap
<ITmfTrace
, ArrayList
<ThreadEntry
>> fEntryListMap
= new HashMap
<ITmfTrace
, ArrayList
<ThreadEntry
>>();
136 // The trace to build thread hash map
137 final private HashMap
<ITmfTrace
, BuildThread
> fBuildThreadMap
= new HashMap
<ITmfTrace
, BuildThread
>();
140 private long fStartTime
;
143 private long fEndTime
;
146 private int fDisplayWidth
;
148 // The next event action
149 private Action fNextEventAction
;
151 // The previous event action
152 private Action fPrevEventAction
;
154 // The next item action
155 private Action fNextItemAction
;
157 // The previous item action
158 private Action fPreviousItemAction
;
161 private ZoomThread fZoomThread
;
163 // The redraw state used to prevent unnecessary queuing of display runnables
164 private State fRedrawState
= State
.IDLE
;
166 // The redraw synchronization object
167 final private Object fSyncObj
= new Object();
169 // The saved time sync. signal used when switching off the pinning of a view
170 private TmfTimeSynchSignal fSavedTimeSyncSignal
;
172 // The saved time range sync. signal used when switching off the pinning of a view
173 private TmfRangeSynchSignal fSavedRangeSyncSignal
;
175 // ------------------------------------------------------------------------
177 // ------------------------------------------------------------------------
179 private class ThreadEntry
implements ITimeGraphEntry
{
181 private final ITmfTrace fThreadTrace
;
183 private final long fTraceStartTime
;
185 private final long fTraceEndTime
;
186 // The children of the entry
187 private ArrayList
<CallStackEntry
> fChildren
;
189 private final String fName
;
190 // The thread attribute quark
191 private final int fThreadQuark
;
193 public ThreadEntry(ITmfTrace trace
, String name
, int threadQuark
, long startTime
, long endTime
) {
194 fThreadTrace
= trace
;
195 fChildren
= new ArrayList
<CallStackEntry
>();
197 fTraceStartTime
= startTime
;
198 fTraceEndTime
= endTime
;
199 fThreadQuark
= threadQuark
;
203 public ITimeGraphEntry
getParent() {
208 public boolean hasChildren() {
209 if (fChildren
== null) {
210 ITmfStateSystem ss
= fThreadTrace
.getStateSystems().get(CallStackStateProvider
.ID
);
212 int eventStackQuark
= ss
.getQuarkRelative(fThreadQuark
, CallStackStateProvider
.CALL_STACK
);
213 ITmfStateInterval eventStackInterval
= ss
.querySingleState(ss
.getStartTime(), eventStackQuark
);
214 return ! eventStackInterval
.getStateValue().isNull() || eventStackInterval
.getEndTime() != ss
.getCurrentEndTime();
215 } catch (AttributeNotFoundException e
) {
217 } catch (TimeRangeException e
) {
219 } catch (StateSystemDisposedException e
) {
223 return fChildren
!= null && fChildren
.size() > 0;
227 public List
<CallStackEntry
> getChildren() {
232 public String
getName() {
237 public long getStartTime() {
238 return fTraceStartTime
;
242 public long getEndTime() {
243 return fTraceEndTime
;
247 public boolean hasTimeEvents() {
252 public Iterator
<ITimeEvent
> getTimeEventsIterator() {
257 public <T
extends ITimeEvent
> Iterator
<T
> getTimeEventsIterator(long startTime
, long stopTime
, long visibleDuration
) {
261 public int getThreadQuark() {
265 public ITmfTrace
getTrace() {
269 public void addChild(CallStackEntry entry
) {
270 entry
.setParent(this);
271 fChildren
.add(entry
);
275 private class TreeContentProvider
implements ITreeContentProvider
{
278 public void dispose() {
282 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
286 public Object
[] getElements(Object inputElement
) {
287 return (ITimeGraphEntry
[]) inputElement
;
291 public Object
[] getChildren(Object parentElement
) {
292 ITimeGraphEntry entry
= (ITimeGraphEntry
) parentElement
;
293 return entry
.getChildren().toArray();
297 public Object
getParent(Object element
) {
298 ITimeGraphEntry entry
= (ITimeGraphEntry
) element
;
299 return entry
.getParent();
303 public boolean hasChildren(Object element
) {
304 ITimeGraphEntry entry
= (ITimeGraphEntry
) element
;
305 return entry
.hasChildren();
310 private class TreeLabelProvider
implements ITableLabelProvider
{
313 public void addListener(ILabelProviderListener listener
) {
317 public void dispose() {
321 public boolean isLabelProperty(Object element
, String property
) {
326 public void removeListener(ILabelProviderListener listener
) {
330 public Image
getColumnImage(Object element
, int columnIndex
) {
331 if (columnIndex
== 0) {
332 if (element
instanceof ThreadEntry
) {
334 } else if (element
instanceof CallStackEntry
) {
335 CallStackEntry entry
= (CallStackEntry
) element
;
336 if (entry
.getFunctionName().length() > 0) {
337 return STACKFRAME_IMAGE
;
345 public String
getColumnText(Object element
, int columnIndex
) {
346 if (element
instanceof ThreadEntry
) {
347 if (columnIndex
== 0) {
348 return ((ThreadEntry
) element
).getName();
350 } else if (element
instanceof CallStackEntry
) {
351 CallStackEntry entry
= (CallStackEntry
) element
;
352 if (columnIndex
== 0) {
353 return entry
.getFunctionName();
354 } else if (columnIndex
== 1) {
355 if (entry
.getFunctionName().length() > 0) {
356 int depth
= entry
.getStackLevel();
357 return Integer
.toString(depth
);
359 } else if (columnIndex
== 2) {
360 if (entry
.getFunctionName().length() > 0) {
361 ITmfTimestamp ts
= new TmfTimestamp(entry
.getStartTime(), ITmfTimestamp
.NANOSECOND_SCALE
);
362 return ts
.toString();
364 } else if (columnIndex
== 3) {
365 if (entry
.getFunctionName().length() > 0) {
366 ITmfTimestamp ts
= new TmfTimestamp(entry
.getEndTime(), ITmfTimestamp
.NANOSECOND_SCALE
);
367 return ts
.toString();
369 } else if (columnIndex
== 4) {
370 if (entry
.getFunctionName().length() > 0) {
371 ITmfTimestamp ts
= new TmfTimestampDelta(entry
.getEndTime() - entry
.getStartTime(), ITmfTimestamp
.NANOSECOND_SCALE
);
372 return ts
.toString();
376 return ""; //$NON-NLS-1$
381 private class BuildThread
extends Thread
{
382 private final ITmfTrace fBuildTrace
;
383 private final IProgressMonitor fMonitor
;
385 public BuildThread(ITmfTrace trace
) {
386 super("CallStackView build"); //$NON-NLS-1$
388 fMonitor
= new NullProgressMonitor();
393 buildThreadList(fBuildTrace
, fMonitor
);
394 synchronized (fBuildThreadMap
) {
395 fBuildThreadMap
.remove(this);
399 public void cancel() {
400 fMonitor
.setCanceled(true);
404 private class ZoomThread
extends Thread
{
405 private final ArrayList
<ThreadEntry
> fZoomEntryList
;
406 private final long fZoomStartTime
;
407 private final long fZoomEndTime
;
408 private final IProgressMonitor fMonitor
;
410 public ZoomThread(ArrayList
<ThreadEntry
> entryList
, long startTime
, long endTime
) {
411 super("ResourcesView zoom"); //$NON-NLS-1$
412 fZoomEntryList
= entryList
;
413 fZoomStartTime
= startTime
;
414 fZoomEndTime
= endTime
;
415 fMonitor
= new NullProgressMonitor();
420 if (fZoomEntryList
== null) {
423 long resolution
= Math
.max(1, (fZoomEndTime
- fZoomStartTime
) / fDisplayWidth
);
424 for (ThreadEntry threadEntry
: fZoomEntryList
) {
425 ITmfStateSystem ss
= threadEntry
.fThreadTrace
.getStateSystems().get(CallStackStateProvider
.ID
);
426 if (ss
== null || !ss
.waitUntilBuilt()) {
429 for (ITimeGraphEntry child
: threadEntry
.getChildren()) {
430 if (fMonitor
.isCanceled()) {
433 CallStackEntry entry
= (CallStackEntry
) child
;
434 if (fZoomStartTime
<= fStartTime
&& fZoomEndTime
>= fEndTime
) {
435 entry
.setZoomedEventList(null);
437 List
<ITimeEvent
> zoomedEventList
= getEventList(entry
, fZoomStartTime
, fZoomEndTime
, resolution
, fMonitor
);
438 if (zoomedEventList
!= null) {
439 entry
.setZoomedEventList(zoomedEventList
);
447 public void cancel() {
448 fMonitor
.setCanceled(true);
452 // ------------------------------------------------------------------------
454 // ------------------------------------------------------------------------
457 * Default constructor
459 public CallStackView() {
461 fDisplayWidth
= Display
.getDefault().getBounds().width
;
464 // ------------------------------------------------------------------------
466 // ------------------------------------------------------------------------
469 public void createPartControl(Composite parent
) {
470 fTimeGraphCombo
= new TimeGraphCombo(parent
, SWT
.NONE
);
472 fTimeGraphCombo
.setTreeContentProvider(new TreeContentProvider());
474 fTimeGraphCombo
.setTreeLabelProvider(new TreeLabelProvider());
476 fTimeGraphCombo
.setTreeColumns(COLUMN_NAMES
);
478 fTimeGraphCombo
.getTreeViewer().getTree().getColumn(0).setWidth(200);
479 fTimeGraphCombo
.getTreeViewer().getTree().getColumn(1).setWidth(50);
480 fTimeGraphCombo
.getTreeViewer().getTree().getColumn(2).setWidth(120);
481 fTimeGraphCombo
.getTreeViewer().getTree().getColumn(3).setWidth(120);
482 fTimeGraphCombo
.getTreeViewer().getTree().getColumn(4).setWidth(120);
484 fTimeGraphCombo
.setTimeGraphProvider(new CallStackPresentationProvider());
485 fTimeGraphCombo
.getTimeGraphViewer().setTimeFormat(TimeFormat
.CALENDAR
);
487 fTimeGraphCombo
.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
489 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event
) {
490 long startTime
= event
.getStartTime();
491 long endTime
= event
.getEndTime();
492 TmfTimeRange range
= new TmfTimeRange(new CtfTmfTimestamp(startTime
), new CtfTmfTimestamp(endTime
));
493 TmfTimestamp time
= new CtfTmfTimestamp(fTimeGraphCombo
.getTimeGraphViewer().getSelectedTime());
494 broadcast(new TmfRangeSynchSignal(CallStackView
.this, range
, time
));
495 startZoomThread(startTime
, endTime
);
499 fTimeGraphCombo
.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
501 public void timeSelected(TimeGraphTimeEvent event
) {
502 long time
= event
.getTime();
504 broadcast(new TmfTimeSynchSignal(CallStackView
.this, new CtfTmfTimestamp(time
)));
508 fTimeGraphCombo
.getTimeGraphViewer().getControl().addControlListener(new ControlAdapter() {
510 public void controlResized(ControlEvent e
) {
511 fDisplayWidth
= fTimeGraphCombo
.getTimeGraphViewer().getControl().getSize().x
;
512 if (fEntryList
!= null) {
513 startZoomThread(fTimeGraphCombo
.getTimeGraphViewer().getTime0(), fTimeGraphCombo
.getTimeGraphViewer().getTime1());
518 fTimeGraphCombo
.getTreeViewer().addDoubleClickListener(new IDoubleClickListener() {
520 public void doubleClick(DoubleClickEvent event
) {
521 Object selection
= ((IStructuredSelection
) event
.getSelection()).getFirstElement();
522 if (selection
instanceof CallStackEntry
) {
523 CallStackEntry entry
= (CallStackEntry
) selection
;
524 if (entry
.getFunctionName().length() > 0) {
525 long startTime
= entry
.getStartTime();
526 long endTime
= entry
.getEndTime();
527 long spacingTime
= (long) ((endTime
- startTime
) * 0.01);
528 startTime
-= spacingTime
;
529 endTime
+= spacingTime
;
530 TmfTimeRange range
= new TmfTimeRange(new CtfTmfTimestamp(startTime
), new CtfTmfTimestamp(endTime
));
531 TmfTimestamp time
= new CtfTmfTimestamp(fTimeGraphCombo
.getTimeGraphViewer().getSelectedTime());
532 broadcast(new TmfRangeSynchSignal(CallStackView
.this, range
, time
));
533 fTimeGraphCombo
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
534 startZoomThread(startTime
, endTime
);
540 fTimeGraphCombo
.getTimeGraphViewer().getTimeGraphControl().addMouseListener(new MouseAdapter() {
542 public void mouseDoubleClick(MouseEvent e
) {
543 TimeGraphControl timeGraphControl
= fTimeGraphCombo
.getTimeGraphViewer().getTimeGraphControl();
544 ISelection selection
= timeGraphControl
.getSelection();
545 if (selection
instanceof TimeGraphSelection
) {
546 Object o
= ((TimeGraphSelection
) selection
).getFirstElement();
547 if (o
instanceof CallStackEvent
) {
548 CallStackEvent event
= (CallStackEvent
) o
;
549 long startTime
= event
.getTime();
550 long endTime
= startTime
+ event
.getDuration();
551 long spacingTime
= (long) ((endTime
- startTime
) * 0.01);
552 startTime
-= spacingTime
;
553 endTime
+= spacingTime
;
554 TmfTimeRange range
= new TmfTimeRange(new CtfTmfTimestamp(startTime
), new CtfTmfTimestamp(endTime
));
555 TmfTimestamp time
= new CtfTmfTimestamp(fTimeGraphCombo
.getTimeGraphViewer().getSelectedTime());
556 broadcast(new TmfRangeSynchSignal(CallStackView
.this, range
, time
));
557 fTimeGraphCombo
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
558 startZoomThread(startTime
, endTime
);
564 // View Action Handling
566 contributeToActionBars();
568 IEditorPart editor
= getSite().getPage().getActiveEditor();
569 if (editor
instanceof ITmfTraceEditor
) {
570 ITmfTrace trace
= ((ITmfTraceEditor
) editor
).getTrace();
572 traceSelected(new TmfTraceSelectedSignal(this, trace
));
578 public void setFocus() {
579 fTimeGraphCombo
.setFocus();
582 // ------------------------------------------------------------------------
584 // ------------------------------------------------------------------------
587 * Handler for the trace selected signal
590 * The incoming signal
593 public void traceSelected(final TmfTraceSelectedSignal signal
) {
594 if (signal
.getTrace() == fTrace
) {
597 fTrace
= signal
.getTrace();
599 synchronized (fEntryListMap
) {
600 fEntryList
= fEntryListMap
.get(fTrace
);
601 if (fEntryList
== null) {
602 synchronized (fBuildThreadMap
) {
603 BuildThread buildThread
= new BuildThread(fTrace
);
604 fBuildThreadMap
.put(fTrace
, buildThread
);
608 fStartTime
= fTrace
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
609 fEndTime
= fTrace
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
616 * Trace is closed: clear the data structures and the view
618 * @param signal the signal received
621 public void traceClosed(final TmfTraceClosedSignal signal
) {
622 synchronized (fBuildThreadMap
) {
623 BuildThread buildThread
= fBuildThreadMap
.remove(signal
.getTrace());
624 if (buildThread
!= null) {
625 buildThread
.cancel();
628 synchronized (fEntryListMap
) {
629 fEntryListMap
.remove(signal
.getTrace());
631 fSelectedThreadMap
.remove(signal
.getTrace());
632 if (signal
.getTrace() == fTrace
) {
641 * Handler for the TimeSynch signal
644 * The incoming signal
647 public void synchToTime(final TmfTimeSynchSignal signal
) {
649 fSavedTimeSyncSignal
= isPinned() ?
new TmfTimeSynchSignal(signal
.getSource(), signal
.getCurrentTime()) : null;
651 if (signal
.getSource() == this || fTrace
== null || isPinned()) {
654 final long time
= signal
.getCurrentTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
655 Display
.getDefault().asyncExec(new Runnable() {
658 if (fTimeGraphCombo
.isDisposed()) {
662 startZoomThread(fTimeGraphCombo
.getTimeGraphViewer().getTime0(), fTimeGraphCombo
.getTimeGraphViewer().getTime1());
663 if (fEntryList
== null) {
666 TimeGraphViewer viewer
= fTimeGraphCombo
.getTimeGraphViewer();
667 for (ThreadEntry threadEntry
: fEntryList
) {
668 ITmfStateSystem ss
= threadEntry
.getTrace().getStateSystems().get(CallStackStateProvider
.ID
);
669 if (ss
== null || time
< ss
.getStartTime() || time
> ss
.getCurrentEndTime()) {
673 int quark
= ss
.getQuarkRelative(threadEntry
.getThreadQuark(), CallStackStateProvider
.CALL_STACK
);
674 ITmfStateInterval stackInterval
= ss
.querySingleState(time
, quark
);
675 if (time
== stackInterval
.getStartTime()) {
676 int stackLevel
= stackInterval
.getStateValue().unboxInt();
677 CallStackEntry selectedEntry
= threadEntry
.getChildren().get(Math
.max(0, stackLevel
- 1));
678 fTimeGraphCombo
.setSelection(selectedEntry
);
679 viewer
.getTimeGraphControl().fireSelectionChanged();
682 } catch (AttributeNotFoundException e
) {
684 } catch (TimeRangeException e
) {
686 } catch (StateSystemDisposedException e
) {
688 } catch (StateValueTypeException e
) {
697 * Handler for the RangeSynch signal
700 * The incoming signal
703 public void synchToRange(final TmfRangeSynchSignal signal
) {
706 fSavedRangeSyncSignal
=
707 new TmfRangeSynchSignal(signal
.getSource(), new TmfTimeRange(signal
.getCurrentRange().getStartTime(), signal
.getCurrentRange().getEndTime()), signal
.getCurrentTime());
709 fSavedTimeSyncSignal
= null;
712 if (signal
.getSource() == this || fTrace
== null || isPinned()) {
715 if (signal
.getCurrentRange().getIntersection(fTrace
.getTimeRange()) == null) {
718 final long startTime
= signal
.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
719 final long endTime
= signal
.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
720 final long time
= signal
.getCurrentTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
721 Display
.getDefault().asyncExec(new Runnable() {
724 if (fTimeGraphCombo
.isDisposed()) {
727 fTimeGraphCombo
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
728 fTimeGraphCombo
.getTimeGraphViewer().setSelectedTime(time
, false);
729 startZoomThread(startTime
, endTime
);
734 // ------------------------------------------------------------------------
736 // ------------------------------------------------------------------------
738 private void buildThreadList(final ITmfTrace trace
, IProgressMonitor monitor
) {
739 fStartTime
= Long
.MAX_VALUE
;
740 fEndTime
= Long
.MIN_VALUE
;
742 if (trace
instanceof TmfExperiment
) {
743 TmfExperiment experiment
= (TmfExperiment
) trace
;
744 traces
= experiment
.getTraces();
746 traces
= new ITmfTrace
[] { trace
};
748 ArrayList
<ThreadEntry
> entryList
= new ArrayList
<ThreadEntry
>();
749 for (ITmfTrace aTrace
: traces
) {
750 if (monitor
.isCanceled()) {
753 ITmfStateSystem ss
= aTrace
.getStateSystems().get(CallStackStateProvider
.ID
);
754 if (ss
== null || !ss
.waitUntilBuilt()) {
755 String threadName
= Messages
.CallStackView_StackInfoNotAvailable
+ ' ' + '(' + aTrace
.getName() + ')';
756 ThreadEntry threadEntry
= new ThreadEntry(aTrace
, threadName
, -1, 0, 0);
757 entryList
.add(threadEntry
);
760 long startTime
= ss
.getStartTime();
761 long endTime
= ss
.getCurrentEndTime() + 1;
762 fStartTime
= Math
.min(fStartTime
, startTime
);
763 fEndTime
= Math
.max(fEndTime
, endTime
);
764 List
<Integer
> threadQuarks
= ss
.getQuarks(CallStackStateProvider
.THREADS
, "*"); //$NON-NLS-1$
765 for (int i
= 0; i
< threadQuarks
.size(); i
++) {
766 if (monitor
.isCanceled()) {
769 int threadQuark
= threadQuarks
.get(i
);
770 String thread
= ss
.getAttributeName(threadQuark
);
771 String threadEntryName
= thread
+ ' ' + '(' + aTrace
.getName() + ')';
772 ThreadEntry threadEntry
= new ThreadEntry(aTrace
, threadEntryName
, threadQuark
, startTime
, endTime
);
773 entryList
.add(threadEntry
);
776 eventStackQuark
= ss
.getQuarkRelative(threadQuark
, CallStackStateProvider
.CALL_STACK
);
778 for (int stackLevelQuark
: ss
.getSubAttributes(eventStackQuark
, false)) {
779 CallStackEntry callStackEntry
= new CallStackEntry(stackLevelQuark
, level
++, aTrace
);
780 threadEntry
.addChild(callStackEntry
);
782 } catch (AttributeNotFoundException e
) {
787 synchronized (fEntryListMap
) {
788 fEntryListMap
.put(trace
, (ArrayList
<ThreadEntry
>) entryList
.clone());
790 if (trace
== fTrace
) {
793 for (ThreadEntry threadEntry
: entryList
) {
794 for (CallStackEntry callStackEntry
: threadEntry
.getChildren()) {
795 if (monitor
.isCanceled()) {
798 buildStatusEvents(trace
, callStackEntry
, monitor
);
803 private void buildStatusEvents(ITmfTrace trace
, CallStackEntry entry
, IProgressMonitor monitor
) {
804 ITmfStateSystem ss
= entry
.getTrace().getStateSystems().get(CallStackStateProvider
.ID
);
805 long start
= ss
.getStartTime();
806 long end
= ss
.getCurrentEndTime() + 1;
807 long resolution
= Math
.max(1, (end
- start
) / fDisplayWidth
);
808 List
<ITimeEvent
> eventList
= getEventList(entry
, start
, end
, resolution
, monitor
);
809 if (monitor
.isCanceled()) {
812 entry
.setEventList(eventList
);
813 if (trace
== fTrace
) {
818 private static List
<ITimeEvent
> getEventList(CallStackEntry entry
,
819 long startTime
, long endTime
, long resolution
,
820 IProgressMonitor monitor
) {
821 ITmfStateSystem ss
= entry
.getTrace().getStateSystems().get(CallStackStateProvider
.ID
);
822 long start
= Math
.max(startTime
, ss
.getStartTime());
823 long end
= Math
.min(endTime
, ss
.getCurrentEndTime() + 1);
827 List
<ITimeEvent
> eventList
= null;
829 List
<ITmfStateInterval
> stackIntervals
= ss
.queryHistoryRange(entry
.getQuark(), start
, end
- 1, resolution
, monitor
);
830 eventList
= new ArrayList
<ITimeEvent
>(stackIntervals
.size());
831 long lastEndTime
= -1;
832 boolean lastIsNull
= true;
833 for (ITmfStateInterval statusInterval
: stackIntervals
) {
834 if (monitor
.isCanceled()) {
837 long time
= statusInterval
.getStartTime();
838 long duration
= statusInterval
.getEndTime() - time
+ 1;
839 if (!statusInterval
.getStateValue().isNull()) {
840 final int MODULO
= CallStackPresentationProvider
.NUM_COLORS
/ 2;
841 int value
= statusInterval
.getStateValue().toString().hashCode() % MODULO
+ MODULO
;
842 eventList
.add(new CallStackEvent(entry
, time
, duration
, value
));
845 if (lastEndTime
!= time
&& lastEndTime
!= -1 && lastIsNull
) {
846 eventList
.add(new TimeEvent(entry
, lastEndTime
, time
- lastEndTime
));
848 eventList
.add(new NullTimeEvent(entry
, time
, duration
));
851 lastEndTime
= time
+ duration
;
853 } catch (AttributeNotFoundException e
) {
855 } catch (TimeRangeException e
) {
857 } catch (StateSystemDisposedException e
) {
863 private void selectTime(long time
) {
864 if (fEntryList
== null) {
867 fTimeGraphCombo
.getTimeGraphViewer().setSelectedTime(time
, true);
868 for (ThreadEntry threadEntry
: fEntryList
) {
869 ITmfStateSystem ss
= threadEntry
.fThreadTrace
.getStateSystems().get(CallStackStateProvider
.ID
);
870 if (ss
== null || !ss
.waitUntilBuilt()) {
873 long queryTime
= Math
.max(ss
.getStartTime(), Math
.min(ss
.getCurrentEndTime(), time
));
874 for (CallStackEntry callStackEntry
: threadEntry
.getChildren()) {
876 ITmfStateInterval stackLevelInterval
= ss
.querySingleState(queryTime
, callStackEntry
.getQuark());
877 ITmfStateValue nameValue
= stackLevelInterval
.getStateValue();
878 String name
= ""; //$NON-NLS-1$
880 if (nameValue
.getType() == Type
.STRING
) {
881 name
= nameValue
.unboxStr();
882 } else if (nameValue
.getType() == Type
.INTEGER
) {
883 name
= "0x" + Integer
.toHexString(nameValue
.unboxInt()); //$NON-NLS-1$
884 } else if (nameValue
.getType() == Type
.LONG
) {
885 name
= "0x" + Long
.toHexString(nameValue
.unboxLong()); //$NON-NLS-1$
887 } catch (StateValueTypeException e
) {
889 callStackEntry
.setFunctionName(name
);
890 if (name
.length() > 0) {
891 callStackEntry
.setStartTime(stackLevelInterval
.getStartTime());
892 callStackEntry
.setEndTime(stackLevelInterval
.getEndTime() + 1);
894 } catch (AttributeNotFoundException e
) {
896 } catch (TimeRangeException e
) {
898 } catch (StateSystemDisposedException e
) {
903 fTimeGraphCombo
.refresh();
904 fTimeGraphCombo
.getTimeGraphViewer().setSelectedTime(time
, true);
907 private void refresh() {
908 Display
.getDefault().asyncExec(new Runnable() {
911 if (fTimeGraphCombo
.isDisposed()) {
914 ITimeGraphEntry
[] entries
= null;
915 synchronized (fEntryListMap
) {
916 fEntryList
= fEntryListMap
.get(fTrace
);
917 if (fEntryList
== null) {
918 fEntryList
= new ArrayList
<ThreadEntry
>();
920 entries
= fEntryList
.toArray(new ITimeGraphEntry
[0]);
922 fTimeGraphCombo
.setInput(entries
);
923 fTimeGraphCombo
.getTimeGraphViewer().setTimeBounds(fStartTime
, fEndTime
);
925 long timestamp
= fTrace
== null ?
0 : fTraceManager
.getCurrentTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
926 long startTime
= fTrace
== null ?
0 : fTraceManager
.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
927 long endTime
= fTrace
== null ?
0 : fTraceManager
.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
928 startTime
= Math
.max(startTime
, fStartTime
);
929 endTime
= Math
.min(endTime
, fEndTime
);
930 selectTime(timestamp
);
931 fTimeGraphCombo
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
932 startZoomThread(startTime
, endTime
);
937 private void redraw() {
938 synchronized (fSyncObj
) {
939 if (fRedrawState
== State
.IDLE
) {
940 fRedrawState
= State
.BUSY
;
942 fRedrawState
= State
.PENDING
;
946 Display
.getDefault().asyncExec(new Runnable() {
949 if (fTimeGraphCombo
.isDisposed()) {
952 fTimeGraphCombo
.redraw();
953 fTimeGraphCombo
.update();
954 synchronized (fSyncObj
) {
955 if (fRedrawState
== State
.PENDING
) {
956 fRedrawState
= State
.IDLE
;
959 fRedrawState
= State
.IDLE
;
966 private void startZoomThread(long startTime
, long endTime
) {
967 if (fZoomThread
!= null) {
968 fZoomThread
.cancel();
970 fZoomThread
= new ZoomThread(fEntryList
, startTime
, endTime
);
974 private void makeActions() {
975 fPreviousItemAction
= fTimeGraphCombo
.getTimeGraphViewer().getPreviousItemAction();
976 fPreviousItemAction
.setText(Messages
.TmfTimeGraphViewer_PreviousItemActionNameText
);
977 fPreviousItemAction
.setToolTipText(Messages
.TmfTimeGraphViewer_PreviousItemActionToolTipText
);
978 fNextItemAction
= fTimeGraphCombo
.getTimeGraphViewer().getNextItemAction();
979 fNextItemAction
.setText(Messages
.TmfTimeGraphViewer_NextItemActionNameText
);
980 fNextItemAction
.setToolTipText(Messages
.TmfTimeGraphViewer_NextItemActionToolTipText
);
983 private void contributeToActionBars() {
984 IActionBars bars
= getViewSite().getActionBars();
985 fillLocalToolBar(bars
.getToolBarManager());
988 contributePinActionToToolBar();
989 fPinAction
.addPropertyChangeListener(new IPropertyChangeListener(){
991 public void propertyChange(PropertyChangeEvent event
) {
992 if (IAction
.CHECKED
.equals(event
.getProperty())) {
994 if (fSavedRangeSyncSignal
!= null) {
995 synchToRange(fSavedRangeSyncSignal
);
996 fSavedRangeSyncSignal
= null;
999 if (fSavedTimeSyncSignal
!= null) {
1000 synchToTime(fSavedTimeSyncSignal
);
1001 fSavedTimeSyncSignal
= null;
1009 private void fillLocalToolBar(IToolBarManager manager
) {
1010 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getResetScaleAction());
1011 manager
.add(getPreviousEventAction());
1012 manager
.add(getNextEventAction());
1013 manager
.add(fPreviousItemAction
);
1014 manager
.add(fNextItemAction
);
1015 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getZoomInAction());
1016 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getZoomOutAction());
1017 manager
.add(new Separator());
1021 * Get the the next event action.
1023 * @return The action object
1025 private Action
getNextEventAction() {
1026 if (fNextEventAction
== null) {
1027 fNextEventAction
= new Action() {
1030 TimeGraphViewer viewer
= fTimeGraphCombo
.getTimeGraphViewer();
1031 ITimeGraphEntry entry
= viewer
.getSelection();
1032 if (entry
instanceof CallStackEntry
) {
1034 CallStackEntry callStackEntry
= (CallStackEntry
) entry
;
1035 ITmfTrace trace
= callStackEntry
.getTrace();
1036 ITmfStateSystem ss
= trace
.getStateSystems().get(CallStackStateProvider
.ID
);
1037 long time
= Math
.max(ss
.getStartTime(), Math
.min(ss
.getCurrentEndTime(), viewer
.getSelectedTime()));
1038 ThreadEntry threadEntry
= (ThreadEntry
) callStackEntry
.getParent();
1039 int quark
= ss
.getQuarkRelative(threadEntry
.getThreadQuark(), CallStackStateProvider
.CALL_STACK
);
1040 ITmfStateInterval stackInterval
= ss
.querySingleState(time
, quark
);
1041 long newTime
= stackInterval
.getEndTime() + 1;
1042 viewer
.setSelectedTimeNotify(newTime
, true);
1043 stackInterval
= ss
.querySingleState(Math
.min(ss
.getCurrentEndTime(), newTime
), quark
);
1044 int stackLevel
= stackInterval
.getStateValue().unboxInt();
1045 CallStackEntry selectedEntry
= threadEntry
.getChildren().get(Math
.max(0, stackLevel
- 1));
1046 fTimeGraphCombo
.setSelection(selectedEntry
);
1047 viewer
.getTimeGraphControl().fireSelectionChanged();
1048 startZoomThread(viewer
.getTime0(), viewer
.getTime1());
1049 } catch (AttributeNotFoundException e
) {
1050 e
.printStackTrace();
1051 } catch (TimeRangeException e
) {
1052 e
.printStackTrace();
1053 } catch (StateSystemDisposedException e
) {
1054 e
.printStackTrace();
1055 } catch (StateValueTypeException e
) {
1056 e
.printStackTrace();
1062 fNextEventAction
.setText(Messages
.TmfTimeGraphViewer_NextEventActionNameText
);
1063 fNextEventAction
.setToolTipText(Messages
.TmfTimeGraphViewer_NextEventActionToolTipText
);
1064 fNextEventAction
.setImageDescriptor(Activator
.getDefault().getImageDescripterFromPath(ITmfImageConstants
.IMG_UI_NEXT_EVENT
));
1067 return fNextEventAction
;
1071 * Get the previous event action.
1073 * @return The Action object
1075 private Action
getPreviousEventAction() {
1076 if (fPrevEventAction
== null) {
1077 fPrevEventAction
= new Action() {
1080 TimeGraphViewer viewer
= fTimeGraphCombo
.getTimeGraphViewer();
1081 ITimeGraphEntry entry
= viewer
.getSelection();
1082 if (entry
instanceof CallStackEntry
) {
1084 CallStackEntry callStackEntry
= (CallStackEntry
) entry
;
1085 ITmfTrace trace
= callStackEntry
.getTrace();
1086 ITmfStateSystem ss
= trace
.getStateSystems().get(CallStackStateProvider
.ID
);
1087 long time
= Math
.max(ss
.getStartTime(), Math
.min(ss
.getCurrentEndTime(), viewer
.getSelectedTime()));
1088 ThreadEntry threadEntry
= (ThreadEntry
) callStackEntry
.getParent();
1089 int quark
= ss
.getQuarkRelative(threadEntry
.getThreadQuark(), CallStackStateProvider
.CALL_STACK
);
1090 ITmfStateInterval stackInterval
= ss
.querySingleState(time
, quark
);
1091 if (stackInterval
.getStartTime() == time
&& time
> ss
.getStartTime()) {
1092 stackInterval
= ss
.querySingleState(time
- 1, quark
);
1094 viewer
.setSelectedTimeNotify(stackInterval
.getStartTime(), true);
1095 int stackLevel
= stackInterval
.getStateValue().unboxInt();
1096 CallStackEntry selectedEntry
= threadEntry
.getChildren().get(Math
.max(0, stackLevel
- 1));
1097 fTimeGraphCombo
.setSelection(selectedEntry
);
1098 viewer
.getTimeGraphControl().fireSelectionChanged();
1099 startZoomThread(viewer
.getTime0(), viewer
.getTime1());
1100 } catch (AttributeNotFoundException e
) {
1101 e
.printStackTrace();
1102 } catch (TimeRangeException e
) {
1103 e
.printStackTrace();
1104 } catch (StateSystemDisposedException e
) {
1105 e
.printStackTrace();
1106 } catch (StateValueTypeException e
) {
1107 e
.printStackTrace();
1113 fPrevEventAction
.setText(Messages
.TmfTimeGraphViewer_PreviousEventActionNameText
);
1114 fPrevEventAction
.setToolTipText(Messages
.TmfTimeGraphViewer_PreviousEventActionToolTipText
);
1115 fPrevEventAction
.setImageDescriptor(Activator
.getDefault().getImageDescripterFromPath(ITmfImageConstants
.IMG_UI_PREV_EVENT
));
1118 return fPrevEventAction
;