1 /*******************************************************************************
2 * Copyright (c) 2012, 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 * Bernd Hufmann - Updated signal handling
12 *******************************************************************************/
14 package org
.eclipse
.linuxtools
.internal
.lttng2
.kernel
.ui
.views
.controlflow
;
16 import java
.util
.ArrayList
;
17 import java
.util
.Arrays
;
18 import java
.util
.Collections
;
19 import java
.util
.Comparator
;
20 import java
.util
.HashMap
;
21 import java
.util
.List
;
23 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
24 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
25 import org
.eclipse
.jface
.action
.Action
;
26 import org
.eclipse
.jface
.action
.IToolBarManager
;
27 import org
.eclipse
.jface
.action
.Separator
;
28 import org
.eclipse
.jface
.viewers
.ILabelProviderListener
;
29 import org
.eclipse
.jface
.viewers
.ITableLabelProvider
;
30 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
31 import org
.eclipse
.jface
.viewers
.Viewer
;
32 import org
.eclipse
.linuxtools
.internal
.lttng2
.kernel
.core
.Attributes
;
33 import org
.eclipse
.linuxtools
.internal
.lttng2
.kernel
.ui
.Messages
;
34 import org
.eclipse
.linuxtools
.lttng2
.kernel
.core
.trace
.LttngKernelTrace
;
35 import org
.eclipse
.linuxtools
.tmf
.core
.ctfadaptor
.CtfTmfTimestamp
;
36 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.AttributeNotFoundException
;
37 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.StateSystemDisposedException
;
38 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.StateValueTypeException
;
39 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.TimeRangeException
;
40 import org
.eclipse
.linuxtools
.tmf
.core
.interval
.ITmfStateInterval
;
41 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfRangeSynchSignal
;
42 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfSignalHandler
;
43 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTimeSynchSignal
;
44 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceClosedSignal
;
45 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceOpenedSignal
;
46 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
47 import org
.eclipse
.linuxtools
.tmf
.core
.statesystem
.ITmfStateSystem
;
48 import org
.eclipse
.linuxtools
.tmf
.core
.statevalue
.ITmfStateValue
;
49 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.ITmfTimestamp
;
50 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.TmfTimeRange
;
51 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.TmfTimestamp
;
52 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
53 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfTraceManager
;
54 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.TmfView
;
55 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphRangeListener
;
56 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphSelectionListener
;
57 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphTimeListener
;
58 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphCombo
;
59 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphRangeUpdateEvent
;
60 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphSelectionEvent
;
61 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphTimeEvent
;
62 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
63 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
64 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.TimeEvent
;
65 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
;
66 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.Resolution
;
67 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.TimeFormat
;
68 import org
.eclipse
.swt
.SWT
;
69 import org
.eclipse
.swt
.graphics
.Image
;
70 import org
.eclipse
.swt
.widgets
.Composite
;
71 import org
.eclipse
.swt
.widgets
.Display
;
72 import org
.eclipse
.swt
.widgets
.TreeColumn
;
73 import org
.eclipse
.ui
.IActionBars
;
76 * The Control Flow view main object
79 public class ControlFlowView
extends TmfView
{
81 // ------------------------------------------------------------------------
83 // ------------------------------------------------------------------------
88 public static final String ID
= "org.eclipse.linuxtools.lttng2.kernel.ui.views.controlflow"; //$NON-NLS-1$
90 private static final String PROCESS_COLUMN
= Messages
.ControlFlowView_processColumn
;
91 private static final String TID_COLUMN
= Messages
.ControlFlowView_tidColumn
;
92 private static final String PTID_COLUMN
= Messages
.ControlFlowView_ptidColumn
;
93 private static final String BIRTH_TIME_COLUMN
= Messages
.ControlFlowView_birthTimeColumn
;
94 private static final String TRACE_COLUMN
= Messages
.ControlFlowView_traceColumn
;
96 private final String
[] COLUMN_NAMES
= new String
[] {
104 private final String
[] FILTER_COLUMN_NAMES
= new String
[] {
112 private enum State
{ IDLE
, BUSY
, PENDING
}
114 // ------------------------------------------------------------------------
116 // ------------------------------------------------------------------------
118 // The timegraph combo
119 private TimeGraphCombo fTimeGraphCombo
;
121 // The selected trace
122 private ITmfTrace fTrace
;
124 // The timegraph entry list
125 private ArrayList
<ControlFlowEntry
> fEntryList
;
127 // The trace to entry list hash map
128 final private HashMap
<ITmfTrace
, ArrayList
<ControlFlowEntry
>> fEntryListMap
= new HashMap
<ITmfTrace
, ArrayList
<ControlFlowEntry
>>();
130 // The trace to build thread hash map
131 final private HashMap
<ITmfTrace
, BuildThread
> fBuildThreadMap
= new HashMap
<ITmfTrace
, BuildThread
>();
134 private long fStartTime
;
137 private long fEndTime
;
140 private final int fDisplayWidth
;
143 private ZoomThread fZoomThread
;
145 // The next resource action
146 private Action fNextResourceAction
;
148 // The previous resource action
149 private Action fPreviousResourceAction
;
151 // A comparator class
152 private final ControlFlowEntryComparator fControlFlowEntryComparator
= new ControlFlowEntryComparator();
154 // The redraw state used to prevent unnecessary queuing of display runnables
155 private State fRedrawState
= State
.IDLE
;
157 // The redraw synchronization object
158 final private Object fSyncObj
= new Object();
160 // ------------------------------------------------------------------------
162 // ------------------------------------------------------------------------
164 private class TreeContentProvider
implements ITreeContentProvider
{
167 public void dispose() {
171 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
175 public Object
[] getElements(Object inputElement
) {
176 return (ITimeGraphEntry
[]) inputElement
;
180 public Object
[] getChildren(Object parentElement
) {
181 ITimeGraphEntry entry
= (ITimeGraphEntry
) parentElement
;
182 List
<?
extends ITimeGraphEntry
> children
= entry
.getChildren();
183 return children
.toArray(new ITimeGraphEntry
[children
.size()]);
187 public Object
getParent(Object element
) {
188 ITimeGraphEntry entry
= (ITimeGraphEntry
) element
;
189 return entry
.getParent();
193 public boolean hasChildren(Object element
) {
194 ITimeGraphEntry entry
= (ITimeGraphEntry
) element
;
195 return entry
.hasChildren();
200 private class TreeLabelProvider
implements ITableLabelProvider
{
203 public void addListener(ILabelProviderListener listener
) {
207 public void dispose() {
211 public boolean isLabelProperty(Object element
, String property
) {
216 public void removeListener(ILabelProviderListener listener
) {
220 public Image
getColumnImage(Object element
, int columnIndex
) {
225 public String
getColumnText(Object element
, int columnIndex
) {
226 ControlFlowEntry entry
= (ControlFlowEntry
) element
;
227 if (columnIndex
== 0) {
228 return entry
.getName();
229 } else if (columnIndex
== 1) {
230 return Integer
.toString(entry
.getThreadId());
231 } else if (columnIndex
== 2) {
232 if (entry
.getParentThreadId() > 0) {
233 return Integer
.toString(entry
.getParentThreadId());
235 } else if (columnIndex
== 3) {
236 return Utils
.formatTime(entry
.getStartTime(), TimeFormat
.CALENDAR
, Resolution
.NANOSEC
);
237 } else if (columnIndex
== 4) {
238 return entry
.getTrace().getName();
240 return ""; //$NON-NLS-1$
245 private static class ControlFlowEntryComparator
implements Comparator
<ITimeGraphEntry
> {
248 public int compare(ITimeGraphEntry o1
, ITimeGraphEntry o2
) {
251 if ((o1
instanceof ControlFlowEntry
) && (o2
instanceof ControlFlowEntry
)) {
252 ControlFlowEntry entry1
= (ControlFlowEntry
) o1
;
253 ControlFlowEntry entry2
= (ControlFlowEntry
) o2
;
254 result
= entry1
.getTrace().getStartTime().compareTo(entry2
.getTrace().getStartTime());
256 result
= entry1
.getTrace().getName().compareTo(entry2
.getTrace().getName());
259 result
= entry1
.getThreadId() < entry2
.getThreadId() ?
-1 : entry1
.getThreadId() > entry2
.getThreadId() ?
1 : 0;
264 result
= o1
.getStartTime() < o2
.getStartTime() ?
-1 : o1
.getStartTime() > o2
.getStartTime() ?
1 : 0;
271 private class BuildThread
extends Thread
{
272 private final ITmfTrace fBuildTrace
;
273 private final IProgressMonitor fMonitor
;
275 public BuildThread(ITmfTrace trace
) {
276 super("ControlFlowView build"); //$NON-NLS-1$
278 fMonitor
= new NullProgressMonitor();
283 buildEventList(fBuildTrace
, fMonitor
);
284 synchronized (fBuildThreadMap
) {
285 fBuildThreadMap
.remove(this);
289 public void cancel() {
290 fMonitor
.setCanceled(true);
294 private class ZoomThread
extends Thread
{
295 private final ArrayList
<ControlFlowEntry
> fZoomEntryList
;
296 private final long fZoomStartTime
;
297 private final long fZoomEndTime
;
298 private final long fResolution
;
299 private final IProgressMonitor fMonitor
;
301 public ZoomThread(ArrayList
<ControlFlowEntry
> entryList
, long startTime
, long endTime
) {
302 super("ControlFlowView zoom"); //$NON-NLS-1$
303 fZoomEntryList
= entryList
;
304 fZoomStartTime
= startTime
;
305 fZoomEndTime
= endTime
;
306 fResolution
= Math
.max(1, (fZoomEndTime
- fZoomStartTime
) / fDisplayWidth
);
307 fMonitor
= new NullProgressMonitor();
312 if (fZoomEntryList
== null) {
315 for (ControlFlowEntry entry
: fZoomEntryList
) {
316 if (fMonitor
.isCanceled()) {
319 zoom(entry
, fMonitor
);
323 private void zoom(ControlFlowEntry entry
, IProgressMonitor monitor
) {
324 if (fZoomStartTime
<= fStartTime
&& fZoomEndTime
>= fEndTime
) {
325 entry
.setZoomedEventList(null);
327 List
<ITimeEvent
> zoomedEventList
= getEventList(entry
, fZoomStartTime
, fZoomEndTime
, fResolution
, monitor
);
328 if (zoomedEventList
!= null) {
329 entry
.setZoomedEventList(zoomedEventList
);
333 for (ControlFlowEntry child
: entry
.getChildren()) {
334 if (fMonitor
.isCanceled()) {
337 zoom(child
, monitor
);
341 public void cancel() {
342 fMonitor
.setCanceled(true);
346 // ------------------------------------------------------------------------
348 // ------------------------------------------------------------------------
353 public ControlFlowView() {
355 fDisplayWidth
= Display
.getDefault().getBounds().width
;
358 // ------------------------------------------------------------------------
360 // ------------------------------------------------------------------------
363 public void createPartControl(Composite parent
) {
364 fTimeGraphCombo
= new TimeGraphCombo(parent
, SWT
.NONE
);
366 fTimeGraphCombo
.setTreeContentProvider(new TreeContentProvider());
368 fTimeGraphCombo
.setTreeLabelProvider(new TreeLabelProvider());
370 fTimeGraphCombo
.setTimeGraphProvider(new ControlFlowPresentationProvider());
372 fTimeGraphCombo
.setTreeColumns(COLUMN_NAMES
);
374 fTimeGraphCombo
.setFilterContentProvider(new TreeContentProvider());
376 fTimeGraphCombo
.setFilterLabelProvider(new TreeLabelProvider());
378 fTimeGraphCombo
.setFilterColumns(FILTER_COLUMN_NAMES
);
380 fTimeGraphCombo
.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
382 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event
) {
383 final long startTime
= event
.getStartTime();
384 final long endTime
= event
.getEndTime();
385 TmfTimeRange range
= new TmfTimeRange(new CtfTmfTimestamp(startTime
), new CtfTmfTimestamp(endTime
));
386 TmfTimestamp time
= new CtfTmfTimestamp(fTimeGraphCombo
.getTimeGraphViewer().getSelectedTime());
387 broadcast(new TmfRangeSynchSignal(ControlFlowView
.this, range
, time
));
388 if (fZoomThread
!= null) {
389 fZoomThread
.cancel();
391 startZoomThread(startTime
, endTime
);
395 fTimeGraphCombo
.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
397 public void timeSelected(TimeGraphTimeEvent event
) {
398 long time
= event
.getTime();
399 broadcast(new TmfTimeSynchSignal(ControlFlowView
.this, new CtfTmfTimestamp(time
)));
403 fTimeGraphCombo
.addSelectionListener(new ITimeGraphSelectionListener() {
405 public void selectionChanged(TimeGraphSelectionEvent event
) {
406 //ITimeGraphEntry selection = event.getSelection();
410 fTimeGraphCombo
.getTimeGraphViewer().setTimeFormat(TimeFormat
.CALENDAR
);
412 // View Action Handling
414 contributeToActionBars();
416 ITmfTrace trace
= getActiveTrace();
418 traceSelected(new TmfTraceSelectedSignal(this, trace
));
421 // make selection available to other views
422 getSite().setSelectionProvider(fTimeGraphCombo
.getTreeViewer());
426 public void setFocus() {
427 fTimeGraphCombo
.setFocus();
430 // ------------------------------------------------------------------------
432 // ------------------------------------------------------------------------
434 * Handler for the trace opened signal.
436 * The incoming signal
440 public void traceOpened(TmfTraceOpenedSignal signal
) {
441 fTrace
= signal
.getTrace();
446 * Handler for the trace selected signal
449 * The incoming signal
452 public void traceSelected(final TmfTraceSelectedSignal signal
) {
453 if (signal
.getTrace() == fTrace
) {
456 fTrace
= signal
.getTrace();
461 * Trace is closed: clear the data structures and the view
463 * @param signal the signal received
466 public void traceClosed(final TmfTraceClosedSignal signal
) {
467 synchronized (fBuildThreadMap
) {
468 BuildThread buildThread
= fBuildThreadMap
.remove(signal
.getTrace());
469 if (buildThread
!= null) {
470 buildThread
.cancel();
473 synchronized (fEntryListMap
) {
474 fEntryListMap
.remove(signal
.getTrace());
476 if (signal
.getTrace() == fTrace
) {
480 if (fZoomThread
!= null) {
481 fZoomThread
.cancel();
488 * Handler for the synch signal
491 * The signal that's received
494 public void synchToTime(final TmfTimeSynchSignal signal
) {
495 if (signal
.getSource() == this || fTrace
== null) {
498 final long time
= signal
.getCurrentTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
501 for (ITmfTrace trace
: TmfTraceManager
.getTraceSet(fTrace
)) {
505 if (trace
instanceof LttngKernelTrace
) {
506 LttngKernelTrace ctfKernelTrace
= (LttngKernelTrace
) trace
;
507 ITmfStateSystem ssq
= ctfKernelTrace
.getStateSystems().get(LttngKernelTrace
.STATE_ID
);
508 if (time
>= ssq
.getStartTime() && time
<= ssq
.getCurrentEndTime()) {
509 List
<Integer
> currentThreadQuarks
= ssq
.getQuarks(Attributes
.CPUS
, "*", Attributes
.CURRENT_THREAD
); //$NON-NLS-1$
510 for (int currentThreadQuark
: currentThreadQuarks
) {
512 ITmfStateInterval currentThreadInterval
= ssq
.querySingleState(time
, currentThreadQuark
);
513 int currentThread
= currentThreadInterval
.getStateValue().unboxInt();
514 if (currentThread
> 0) {
515 int statusQuark
= ssq
.getQuarkAbsolute(Attributes
.THREADS
, Integer
.toString(currentThread
), Attributes
.STATUS
);
516 ITmfStateInterval statusInterval
= ssq
.querySingleState(time
, statusQuark
);
517 if (statusInterval
.getStartTime() == time
) {
518 thread
= currentThread
;
522 } catch (AttributeNotFoundException e
) {
524 } catch (TimeRangeException e
) {
526 } catch (StateValueTypeException e
) {
528 } catch (StateSystemDisposedException e
) {
535 final int selectedThread
= thread
;
537 Display
.getDefault().asyncExec(new Runnable() {
540 if (fTimeGraphCombo
.isDisposed()) {
543 fTimeGraphCombo
.getTimeGraphViewer().setSelectedTime(time
, true);
544 startZoomThread(fTimeGraphCombo
.getTimeGraphViewer().getTime0(), fTimeGraphCombo
.getTimeGraphViewer().getTime1());
546 if (selectedThread
> 0) {
547 for (Object element
: fTimeGraphCombo
.getTimeGraphViewer().getExpandedElements()) {
548 if (element
instanceof ControlFlowEntry
) {
549 ControlFlowEntry entry
= (ControlFlowEntry
) element
;
550 if (entry
.getThreadId() == selectedThread
) {
551 fTimeGraphCombo
.setSelection(entry
);
562 * Handler for the range sync signal
565 * The signal that's received
568 public void synchToRange(final TmfRangeSynchSignal signal
) {
569 if (signal
.getSource() == this || fTrace
== null) {
572 if (signal
.getCurrentRange().getIntersection(fTrace
.getTimeRange()) == null) {
575 final long startTime
= signal
.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
576 final long endTime
= signal
.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
577 final long time
= signal
.getCurrentTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
578 Display
.getDefault().asyncExec(new Runnable() {
581 if (fTimeGraphCombo
.isDisposed()) {
584 fTimeGraphCombo
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
585 fTimeGraphCombo
.getTimeGraphViewer().setSelectedTime(time
, false);
586 startZoomThread(startTime
, endTime
);
591 // ------------------------------------------------------------------------
593 // ------------------------------------------------------------------------
595 private void loadTrace() {
596 synchronized (fEntryListMap
) {
597 fEntryList
= fEntryListMap
.get(fTrace
);
598 if (fEntryList
== null) {
599 synchronized (fBuildThreadMap
) {
600 BuildThread buildThread
= new BuildThread(fTrace
);
601 fBuildThreadMap
.put(fTrace
, buildThread
);
605 fStartTime
= fTrace
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
606 fEndTime
= fTrace
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
612 private void buildEventList(final ITmfTrace trace
, IProgressMonitor monitor
) {
613 fStartTime
= Long
.MAX_VALUE
;
614 fEndTime
= Long
.MIN_VALUE
;
615 ArrayList
<ControlFlowEntry
> rootList
= new ArrayList
<ControlFlowEntry
>();
616 for (ITmfTrace aTrace
: TmfTraceManager
.getTraceSet(trace
)) {
617 if (monitor
.isCanceled()) {
620 if (aTrace
instanceof LttngKernelTrace
) {
621 ArrayList
<ControlFlowEntry
> entryList
= new ArrayList
<ControlFlowEntry
>();
622 LttngKernelTrace ctfKernelTrace
= (LttngKernelTrace
) aTrace
;
623 ITmfStateSystem ssq
= ctfKernelTrace
.getStateSystems().get(LttngKernelTrace
.STATE_ID
);
624 if (!ssq
.waitUntilBuilt()) {
627 long start
= ssq
.getStartTime();
628 long end
= ssq
.getCurrentEndTime() + 1;
629 fStartTime
= Math
.min(fStartTime
, start
);
630 fEndTime
= Math
.max(fEndTime
, end
);
631 List
<Integer
> threadQuarks
= ssq
.getQuarks(Attributes
.THREADS
, "*"); //$NON-NLS-1$
632 for (int threadQuark
: threadQuarks
) {
633 if (monitor
.isCanceled()) {
636 String threadName
= ssq
.getAttributeName(threadQuark
);
639 threadId
= Integer
.parseInt(threadName
);
640 } catch (NumberFormatException e1
) {
643 if (threadId
== 0) { // ignore the swapper thread
646 int execNameQuark
= -1;
649 execNameQuark
= ssq
.getQuarkRelative(threadQuark
, Attributes
.EXEC_NAME
);
650 } catch (AttributeNotFoundException e
) {
653 int ppidQuark
= ssq
.getQuarkRelative(threadQuark
, Attributes
.PPID
);
654 List
<ITmfStateInterval
> execNameIntervals
= ssq
.queryHistoryRange(execNameQuark
, start
, end
- 1); // use monitor when available in api
655 if (monitor
.isCanceled()) {
658 ControlFlowEntry entry
= null;
659 for (ITmfStateInterval execNameInterval
: execNameIntervals
) {
660 if (monitor
.isCanceled()) {
663 if (!execNameInterval
.getStateValue().isNull() &&
664 execNameInterval
.getStateValue().getType() == ITmfStateValue
.Type
.STRING
) {
665 String execName
= execNameInterval
.getStateValue().unboxStr();
666 long startTime
= execNameInterval
.getStartTime();
667 long endTime
= execNameInterval
.getEndTime() + 1;
669 if (ppidQuark
!= -1) {
670 ITmfStateInterval ppidInterval
= ssq
.querySingleState(startTime
, ppidQuark
);
671 ppid
= ppidInterval
.getStateValue().unboxInt();
674 entry
= new ControlFlowEntry(threadQuark
, ctfKernelTrace
, execName
, threadId
, ppid
, startTime
, endTime
);
675 entryList
.add(entry
);
677 // update the name of the entry to the latest execName
678 entry
.setName(execName
);
680 entry
.addEvent(new TimeEvent(entry
, startTime
, endTime
- startTime
));
685 } catch (AttributeNotFoundException e
) {
687 } catch (TimeRangeException e
) {
689 } catch (StateValueTypeException e
) {
691 } catch (StateSystemDisposedException e
) {
695 buildTree(entryList
, rootList
);
697 Collections
.sort(rootList
, fControlFlowEntryComparator
);
698 synchronized (fEntryListMap
) {
699 fEntryListMap
.put(trace
, (ArrayList
<ControlFlowEntry
>) rootList
.clone());
701 if (trace
== fTrace
) {
705 for (ControlFlowEntry entry
: rootList
) {
706 if (monitor
.isCanceled()) {
709 buildStatusEvents(trace
, entry
, monitor
);
713 private static void buildTree(ArrayList
<ControlFlowEntry
> entryList
,
714 ArrayList
<ControlFlowEntry
> rootList
) {
715 for (ControlFlowEntry entry
: entryList
) {
717 if (entry
.getParentThreadId() > 0) {
718 for (ControlFlowEntry parent
: entryList
) {
719 if (parent
.getThreadId() == entry
.getParentThreadId() &&
720 entry
.getStartTime() >= parent
.getStartTime() &&
721 entry
.getStartTime() <= parent
.getEndTime()) {
722 parent
.addChild(entry
);
734 private void buildStatusEvents(ITmfTrace trace
, ControlFlowEntry entry
, IProgressMonitor monitor
) {
735 ITmfStateSystem ssq
= entry
.getTrace().getStateSystems().get(LttngKernelTrace
.STATE_ID
);
736 long start
= ssq
.getStartTime();
737 long end
= ssq
.getCurrentEndTime() + 1;
738 long resolution
= Math
.max(1, (end
- start
) / fDisplayWidth
);
739 List
<ITimeEvent
> eventList
= getEventList(entry
, entry
.getStartTime(), entry
.getEndTime(), resolution
, monitor
);
740 if (monitor
.isCanceled()) {
743 entry
.setEventList(eventList
);
744 if (trace
== fTrace
) {
747 for (ITimeGraphEntry child
: entry
.getChildren()) {
748 if (monitor
.isCanceled()) {
751 buildStatusEvents(trace
, (ControlFlowEntry
) child
, monitor
);
755 private static List
<ITimeEvent
> getEventList(ControlFlowEntry entry
,
756 long startTime
, long endTime
, long resolution
,
757 IProgressMonitor monitor
) {
758 final long realStart
= Math
.max(startTime
, entry
.getStartTime());
759 final long realEnd
= Math
.min(endTime
, entry
.getEndTime());
760 if (realEnd
<= realStart
) {
763 ITmfStateSystem ssq
= entry
.getTrace().getStateSystems().get(LttngKernelTrace
.STATE_ID
);
764 List
<ITimeEvent
> eventList
= null;
766 int statusQuark
= ssq
.getQuarkRelative(entry
.getThreadQuark(), Attributes
.STATUS
);
767 List
<ITmfStateInterval
> statusIntervals
= ssq
.queryHistoryRange(statusQuark
, realStart
, realEnd
- 1, resolution
, monitor
);
768 eventList
= new ArrayList
<ITimeEvent
>(statusIntervals
.size());
769 long lastEndTime
= -1;
770 for (ITmfStateInterval statusInterval
: statusIntervals
) {
771 if (monitor
.isCanceled()) {
774 long time
= statusInterval
.getStartTime();
775 long duration
= statusInterval
.getEndTime() - time
+ 1;
778 status
= statusInterval
.getStateValue().unboxInt();
779 } catch (StateValueTypeException e
) {
782 if (lastEndTime
!= time
&& lastEndTime
!= -1) {
783 eventList
.add(new TimeEvent(entry
, lastEndTime
, time
- lastEndTime
));
785 eventList
.add(new ControlFlowEvent(entry
, time
, duration
, status
));
786 lastEndTime
= time
+ duration
;
788 } catch (AttributeNotFoundException e
) {
790 } catch (TimeRangeException e
) {
792 } catch (StateSystemDisposedException e
) {
798 private void refresh() {
799 Display
.getDefault().asyncExec(new Runnable() {
802 if (fTimeGraphCombo
.isDisposed()) {
805 ITimeGraphEntry
[] entries
= null;
806 synchronized (fEntryListMap
) {
807 fEntryList
= fEntryListMap
.get(fTrace
);
808 if (fEntryList
== null) {
809 fEntryList
= new ArrayList
<ControlFlowEntry
>();
811 entries
= fEntryList
.toArray(new ITimeGraphEntry
[0]);
813 Arrays
.sort(entries
, fControlFlowEntryComparator
);
814 fTimeGraphCombo
.setInput(entries
);
815 fTimeGraphCombo
.getTimeGraphViewer().setTimeBounds(fStartTime
, fEndTime
);
817 long timestamp
= fTrace
== null ?
0 : fTraceManager
.getCurrentTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
818 long startTime
= fTrace
== null ?
0 : fTraceManager
.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
819 long endTime
= fTrace
== null ?
0 : fTraceManager
.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
820 startTime
= Math
.max(startTime
, fStartTime
);
821 endTime
= Math
.min(endTime
, fEndTime
);
822 fTimeGraphCombo
.getTimeGraphViewer().setSelectedTime(timestamp
, false);
823 fTimeGraphCombo
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
825 for (TreeColumn column
: fTimeGraphCombo
.getTreeViewer().getTree().getColumns()) {
829 startZoomThread(startTime
, endTime
);
834 private void redraw() {
835 synchronized (fSyncObj
) {
836 if (fRedrawState
== State
.IDLE
) {
837 fRedrawState
= State
.BUSY
;
839 fRedrawState
= State
.PENDING
;
843 Display
.getDefault().asyncExec(new Runnable() {
846 if (fTimeGraphCombo
.isDisposed()) {
849 fTimeGraphCombo
.redraw();
850 fTimeGraphCombo
.update();
851 synchronized (fSyncObj
) {
852 if (fRedrawState
== State
.PENDING
) {
853 fRedrawState
= State
.IDLE
;
856 fRedrawState
= State
.IDLE
;
863 private void startZoomThread(long startTime
, long endTime
) {
864 if (fZoomThread
!= null) {
865 fZoomThread
.cancel();
867 fZoomThread
= new ZoomThread(fEntryList
, startTime
, endTime
);
871 private void makeActions() {
872 fPreviousResourceAction
= fTimeGraphCombo
.getTimeGraphViewer().getPreviousItemAction();
873 fPreviousResourceAction
.setText(Messages
.ControlFlowView_previousProcessActionNameText
);
874 fPreviousResourceAction
.setToolTipText(Messages
.ControlFlowView_previousProcessActionToolTipText
);
875 fNextResourceAction
= fTimeGraphCombo
.getTimeGraphViewer().getNextItemAction();
876 fNextResourceAction
.setText(Messages
.ControlFlowView_nextProcessActionNameText
);
877 fNextResourceAction
.setToolTipText(Messages
.ControlFlowView_nextProcessActionToolTipText
);
880 private void contributeToActionBars() {
881 IActionBars bars
= getViewSite().getActionBars();
882 fillLocalToolBar(bars
.getToolBarManager());
885 private void fillLocalToolBar(IToolBarManager manager
) {
886 manager
.add(fTimeGraphCombo
.getShowFilterAction());
887 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getShowLegendAction());
888 manager
.add(new Separator());
889 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getResetScaleAction());
890 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getPreviousEventAction());
891 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getNextEventAction());
892 manager
.add(fPreviousResourceAction
);
893 manager
.add(fNextResourceAction
);
894 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getZoomInAction());
895 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getZoomOutAction());
896 manager
.add(new Separator());