1 /*******************************************************************************
2 * Copyright (c) 2012 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
.internal
.lttng2
.kernel
.ui
.views
.controlflow
;
15 import java
.util
.ArrayList
;
16 import java
.util
.Arrays
;
17 import java
.util
.Collections
;
18 import java
.util
.Comparator
;
19 import java
.util
.HashMap
;
20 import java
.util
.List
;
22 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
23 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
24 import org
.eclipse
.jface
.action
.Action
;
25 import org
.eclipse
.jface
.action
.IToolBarManager
;
26 import org
.eclipse
.jface
.action
.Separator
;
27 import org
.eclipse
.jface
.viewers
.ILabelProviderListener
;
28 import org
.eclipse
.jface
.viewers
.ITableLabelProvider
;
29 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
30 import org
.eclipse
.jface
.viewers
.Viewer
;
31 import org
.eclipse
.linuxtools
.internal
.lttng2
.kernel
.core
.Attributes
;
32 import org
.eclipse
.linuxtools
.internal
.lttng2
.kernel
.ui
.Messages
;
33 import org
.eclipse
.linuxtools
.lttng2
.kernel
.core
.trace
.CtfKernelTrace
;
34 import org
.eclipse
.linuxtools
.tmf
.core
.ctfadaptor
.CtfTmfTimestamp
;
35 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfTimestamp
;
36 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimeRange
;
37 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimestamp
;
38 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.AttributeNotFoundException
;
39 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.StateSystemDisposedException
;
40 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.StateValueTypeException
;
41 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.TimeRangeException
;
42 import org
.eclipse
.linuxtools
.tmf
.core
.interval
.ITmfStateInterval
;
43 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfRangeSynchSignal
;
44 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfSignalHandler
;
45 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTimeSynchSignal
;
46 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceClosedSignal
;
47 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
48 import org
.eclipse
.linuxtools
.tmf
.core
.statesystem
.ITmfStateSystem
;
49 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
50 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfExperiment
;
51 import org
.eclipse
.linuxtools
.tmf
.ui
.editors
.ITmfTraceEditor
;
52 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.TmfView
;
53 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphRangeListener
;
54 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphSelectionListener
;
55 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphTimeListener
;
56 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphCombo
;
57 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphRangeUpdateEvent
;
58 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphSelectionEvent
;
59 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphTimeEvent
;
60 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
61 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
62 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.TimeEvent
;
63 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
;
64 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.Resolution
;
65 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.TimeFormat
;
66 import org
.eclipse
.swt
.SWT
;
67 import org
.eclipse
.swt
.graphics
.Image
;
68 import org
.eclipse
.swt
.widgets
.Composite
;
69 import org
.eclipse
.swt
.widgets
.Display
;
70 import org
.eclipse
.swt
.widgets
.TreeColumn
;
71 import org
.eclipse
.ui
.IActionBars
;
72 import org
.eclipse
.ui
.IEditorPart
;
75 * The Control Flow view main object
78 public class ControlFlowView
extends TmfView
{
80 // ------------------------------------------------------------------------
82 // ------------------------------------------------------------------------
87 public static final String ID
= "org.eclipse.linuxtools.lttng2.kernel.ui.views.controlflow"; //$NON-NLS-1$
92 private static final long INITIAL_WINDOW_OFFSET
= (1L * 100 * 1000 * 1000); // .1sec
94 private static final String PROCESS_COLUMN
= Messages
.ControlFlowView_processColumn
;
95 private static final String TID_COLUMN
= Messages
.ControlFlowView_tidColumn
;
96 private static final String PTID_COLUMN
= Messages
.ControlFlowView_ptidColumn
;
97 private static final String BIRTH_TIME_COLUMN
= Messages
.ControlFlowView_birthTimeColumn
;
98 private static final String TRACE_COLUMN
= Messages
.ControlFlowView_traceColumn
;
100 private final String
[] COLUMN_NAMES
= new String
[] {
111 private enum State
{ IDLE
, BUSY
, PENDING
}
113 // ------------------------------------------------------------------------
115 // ------------------------------------------------------------------------
117 // The timegraph combo
118 private TimeGraphCombo fTimeGraphCombo
;
120 // The selected trace
121 private ITmfTrace fTrace
;
123 // The timegraph entry list
124 private ArrayList
<ControlFlowEntry
> fEntryList
;
126 // The trace to entry list hash map
127 final private HashMap
<ITmfTrace
, ArrayList
<ControlFlowEntry
>> fEntryListMap
= new HashMap
<ITmfTrace
, ArrayList
<ControlFlowEntry
>>();
129 // The trace to build thread hash map
130 final private HashMap
<ITmfTrace
, BuildThread
> fBuildThreadMap
= new HashMap
<ITmfTrace
, BuildThread
>();
133 private long fStartTime
;
136 private long fEndTime
;
139 private final int fDisplayWidth
;
142 private ZoomThread fZoomThread
;
144 // The next resource action
145 private Action fNextResourceAction
;
147 // The previous resource action
148 private Action fPreviousResourceAction
;
150 // A comparator class
151 private final ControlFlowEntryComparator fControlFlowEntryComparator
= new ControlFlowEntryComparator();
153 // The redraw state used to prevent unnecessary queuing of display runnables
154 private State fRedrawState
= State
.IDLE
;
156 // The redraw synchronization object
157 final private Object fSyncObj
= new Object();
159 // ------------------------------------------------------------------------
161 // ------------------------------------------------------------------------
163 private class TreeContentProvider
implements ITreeContentProvider
{
166 public void dispose() {
170 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
174 public Object
[] getElements(Object inputElement
) {
175 return (ITimeGraphEntry
[]) inputElement
;
179 public Object
[] getChildren(Object parentElement
) {
180 ITimeGraphEntry entry
= (ITimeGraphEntry
) parentElement
;
181 List
<?
extends ITimeGraphEntry
> children
= entry
.getChildren();
182 return children
.toArray(new ITimeGraphEntry
[children
.size()]);
186 public Object
getParent(Object element
) {
187 ITimeGraphEntry entry
= (ITimeGraphEntry
) element
;
188 return entry
.getParent();
192 public boolean hasChildren(Object element
) {
193 ITimeGraphEntry entry
= (ITimeGraphEntry
) element
;
194 return entry
.hasChildren();
199 private class TreeLabelProvider
implements ITableLabelProvider
{
202 public void addListener(ILabelProviderListener listener
) {
206 public void dispose() {
210 public boolean isLabelProperty(Object element
, String property
) {
215 public void removeListener(ILabelProviderListener listener
) {
219 public Image
getColumnImage(Object element
, int columnIndex
) {
224 public String
getColumnText(Object element
, int columnIndex
) {
225 ControlFlowEntry entry
= (ControlFlowEntry
) element
;
226 if (columnIndex
== 0) {
227 return entry
.getName();
228 } else if (columnIndex
== 1) {
229 return Integer
.toString(entry
.getThreadId());
230 } else if (columnIndex
== 2) {
231 if (entry
.getParentThreadId() > 0) {
232 return Integer
.toString(entry
.getParentThreadId());
234 } else if (columnIndex
== 3) {
235 return Utils
.formatTime(entry
.getBirthTime(), TimeFormat
.ABSOLUTE
, Resolution
.NANOSEC
);
236 } else if (columnIndex
== 4) {
237 return entry
.getTrace().getName();
239 return ""; //$NON-NLS-1$
244 private static class ControlFlowEntryComparator
implements Comparator
<ITimeGraphEntry
> {
247 public int compare(ITimeGraphEntry o1
, ITimeGraphEntry o2
) {
250 if ((o1
instanceof ControlFlowEntry
) && (o2
instanceof ControlFlowEntry
)) {
251 ControlFlowEntry entry1
= (ControlFlowEntry
) o1
;
252 ControlFlowEntry entry2
= (ControlFlowEntry
) o2
;
253 result
= entry1
.getTrace().getStartTime().compareTo(entry2
.getTrace().getStartTime());
255 result
= entry1
.getTrace().getName().compareTo(entry2
.getTrace().getName());
258 result
= entry1
.getThreadId() < entry2
.getThreadId() ?
-1 : entry1
.getThreadId() > entry2
.getThreadId() ?
1 : 0;
263 result
= o1
.getStartTime() < o2
.getStartTime() ?
-1 : o1
.getStartTime() > o2
.getStartTime() ?
1 : 0;
270 private class BuildThread
extends Thread
{
271 private final ITmfTrace fBuildTrace
;
272 private final IProgressMonitor fMonitor
;
274 public BuildThread(ITmfTrace trace
) {
275 super("ControlFlowView build"); //$NON-NLS-1$
277 fMonitor
= new NullProgressMonitor();
282 buildEventList(fBuildTrace
, fMonitor
);
283 synchronized (fBuildThreadMap
) {
284 fBuildThreadMap
.remove(this);
288 public void cancel() {
289 fMonitor
.setCanceled(true);
293 private class ZoomThread
extends Thread
{
294 private final ArrayList
<ControlFlowEntry
> fZoomEntryList
;
295 private final long fZoomStartTime
;
296 private final long fZoomEndTime
;
297 private final long fResolution
;
298 private final IProgressMonitor fMonitor
;
300 public ZoomThread(ArrayList
<ControlFlowEntry
> entryList
, long startTime
, long endTime
) {
301 super("ControlFlowView zoom"); //$NON-NLS-1$
302 fZoomEntryList
= entryList
;
303 fZoomStartTime
= startTime
;
304 fZoomEndTime
= endTime
;
305 fResolution
= Math
.max(1, (fZoomEndTime
- fZoomStartTime
) / fDisplayWidth
);
306 fMonitor
= new NullProgressMonitor();
311 if (fZoomEntryList
== null) {
314 for (ControlFlowEntry entry
: fZoomEntryList
) {
315 if (fMonitor
.isCanceled()) {
318 zoom(entry
, fMonitor
);
322 private void zoom(ControlFlowEntry entry
, IProgressMonitor monitor
) {
323 if (fZoomStartTime
<= fStartTime
&& fZoomEndTime
>= fEndTime
) {
324 entry
.setZoomedEventList(null);
326 List
<ITimeEvent
> zoomedEventList
= getEventList(entry
, fZoomStartTime
, fZoomEndTime
, fResolution
, monitor
);
327 if (zoomedEventList
!= null) {
328 entry
.setZoomedEventList(zoomedEventList
);
332 for (ControlFlowEntry child
: entry
.getChildren()) {
333 if (fMonitor
.isCanceled()) {
336 zoom(child
, monitor
);
340 public void cancel() {
341 fMonitor
.setCanceled(true);
345 // ------------------------------------------------------------------------
347 // ------------------------------------------------------------------------
352 public ControlFlowView() {
354 fDisplayWidth
= Display
.getDefault().getBounds().width
;
357 // ------------------------------------------------------------------------
359 // ------------------------------------------------------------------------
362 * @see org.eclipse.linuxtools.tmf.ui.views.TmfView#createPartControl(org.eclipse.swt.widgets.Composite)
365 public void createPartControl(Composite parent
) {
366 fTimeGraphCombo
= new TimeGraphCombo(parent
, SWT
.NONE
);
368 fTimeGraphCombo
.setTreeContentProvider(new TreeContentProvider());
370 fTimeGraphCombo
.setTreeLabelProvider(new TreeLabelProvider());
372 fTimeGraphCombo
.setTimeGraphProvider(new ControlFlowPresentationProvider());
374 fTimeGraphCombo
.setTreeColumns(COLUMN_NAMES
);
376 fTimeGraphCombo
.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
378 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event
) {
379 final long startTime
= event
.getStartTime();
380 final long endTime
= event
.getEndTime();
381 TmfTimeRange range
= new TmfTimeRange(new CtfTmfTimestamp(startTime
), new CtfTmfTimestamp(endTime
));
382 TmfTimestamp time
= new CtfTmfTimestamp(fTimeGraphCombo
.getTimeGraphViewer().getSelectedTime());
383 broadcast(new TmfRangeSynchSignal(ControlFlowView
.this, range
, time
));
384 if (fZoomThread
!= null) {
385 fZoomThread
.cancel();
387 startZoomThread(startTime
, endTime
);
391 fTimeGraphCombo
.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
393 public void timeSelected(TimeGraphTimeEvent event
) {
394 long time
= event
.getTime();
395 broadcast(new TmfTimeSynchSignal(ControlFlowView
.this, new CtfTmfTimestamp(time
)));
399 fTimeGraphCombo
.addSelectionListener(new ITimeGraphSelectionListener() {
401 public void selectionChanged(TimeGraphSelectionEvent event
) {
402 //ITimeGraphEntry selection = event.getSelection();
406 fTimeGraphCombo
.getTimeGraphViewer().setTimeCalendarFormat(true);
408 // View Action Handling
410 contributeToActionBars();
412 IEditorPart editor
= getSite().getPage().getActiveEditor();
413 if (editor
instanceof ITmfTraceEditor
) {
414 ITmfTrace trace
= ((ITmfTraceEditor
) editor
).getTrace();
416 traceSelected(new TmfTraceSelectedSignal(this, trace
));
422 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
425 public void setFocus() {
426 fTimeGraphCombo
.setFocus();
429 // ------------------------------------------------------------------------
431 // ------------------------------------------------------------------------
434 * Handler for the trace selected signal
437 * The signal that's received
440 public void traceSelected(final TmfTraceSelectedSignal signal
) {
441 if (signal
.getTrace() == fTrace
) {
444 fTrace
= signal
.getTrace();
446 synchronized (fEntryListMap
) {
447 fEntryList
= fEntryListMap
.get(fTrace
);
448 if (fEntryList
== null) {
449 synchronized (fBuildThreadMap
) {
450 BuildThread buildThread
= new BuildThread(fTrace
);
451 fBuildThreadMap
.put(fTrace
, buildThread
);
455 fStartTime
= fTrace
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
456 fEndTime
= fTrace
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
457 refresh(INITIAL_WINDOW_OFFSET
);
463 * Trace is closed: clear the data structures and the view
465 * @param signal the signal received
468 public void traceClosed(final TmfTraceClosedSignal signal
) {
469 synchronized (fBuildThreadMap
) {
470 BuildThread buildThread
= fBuildThreadMap
.remove(signal
.getTrace());
471 if (buildThread
!= null) {
472 buildThread
.cancel();
475 synchronized (fEntryListMap
) {
476 fEntryListMap
.remove(signal
.getTrace());
478 if (signal
.getTrace() == fTrace
) {
482 if (fZoomThread
!= null) {
483 fZoomThread
.cancel();
485 refresh(INITIAL_WINDOW_OFFSET
);
490 * Handler for the synch signal
493 * The signal that's received
496 public void synchToTime(final TmfTimeSynchSignal signal
) {
497 if (signal
.getSource() == this || fTrace
== null) {
500 final long time
= signal
.getCurrentTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
504 if (fTrace
instanceof TmfExperiment
) {
505 TmfExperiment experiment
= (TmfExperiment
) fTrace
;
506 traces
= experiment
.getTraces();
508 traces
= new ITmfTrace
[] { fTrace
};
510 for (ITmfTrace trace
: traces
) {
514 if (trace
instanceof CtfKernelTrace
) {
515 CtfKernelTrace ctfKernelTrace
= (CtfKernelTrace
) trace
;
516 ITmfStateSystem ssq
= ctfKernelTrace
.getStateSystem();
517 if (time
>= ssq
.getStartTime() && time
<= ssq
.getCurrentEndTime()) {
518 List
<Integer
> currentThreadQuarks
= ssq
.getQuarks(Attributes
.CPUS
, "*", Attributes
.CURRENT_THREAD
); //$NON-NLS-1$
519 for (int currentThreadQuark
: currentThreadQuarks
) {
521 ITmfStateInterval currentThreadInterval
= ssq
.querySingleState(time
, currentThreadQuark
);
522 int currentThread
= currentThreadInterval
.getStateValue().unboxInt();
523 if (currentThread
> 0) {
524 int statusQuark
= ssq
.getQuarkAbsolute(Attributes
.THREADS
, Integer
.toString(currentThread
), Attributes
.STATUS
);
525 ITmfStateInterval statusInterval
= ssq
.querySingleState(time
, statusQuark
);
526 if (statusInterval
.getStartTime() == time
) {
527 thread
= currentThread
;
531 } catch (AttributeNotFoundException e
) {
533 } catch (TimeRangeException e
) {
535 } catch (StateValueTypeException e
) {
537 } catch (StateSystemDisposedException e
) {
544 final int selectedThread
= thread
;
546 Display
.getDefault().asyncExec(new Runnable() {
549 if (fTimeGraphCombo
.isDisposed()) {
552 fTimeGraphCombo
.getTimeGraphViewer().setSelectedTime(time
, true);
553 startZoomThread(fTimeGraphCombo
.getTimeGraphViewer().getTime0(), fTimeGraphCombo
.getTimeGraphViewer().getTime1());
555 if (selectedThread
> 0) {
556 for (Object element
: fTimeGraphCombo
.getTimeGraphViewer().getExpandedElements()) {
557 if (element
instanceof ControlFlowEntry
) {
558 ControlFlowEntry entry
= (ControlFlowEntry
) element
;
559 if (entry
.getThreadId() == selectedThread
) {
560 fTimeGraphCombo
.setSelection(entry
);
571 * Handler for the range sync signal
574 * The signal that's received
577 public void synchToRange(final TmfRangeSynchSignal signal
) {
578 if (signal
.getSource() == this || fTrace
== null) {
581 final long startTime
= signal
.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
582 final long endTime
= signal
.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
583 final long time
= signal
.getCurrentTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
584 Display
.getDefault().asyncExec(new Runnable() {
587 if (fTimeGraphCombo
.isDisposed()) {
590 fTimeGraphCombo
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
591 fTimeGraphCombo
.getTimeGraphViewer().setSelectedTime(time
, false);
592 startZoomThread(startTime
, endTime
);
597 // ------------------------------------------------------------------------
599 // ------------------------------------------------------------------------
601 private void buildEventList(final ITmfTrace trace
, IProgressMonitor monitor
) {
602 fStartTime
= Long
.MAX_VALUE
;
603 fEndTime
= Long
.MIN_VALUE
;
605 if (trace
instanceof TmfExperiment
) {
606 TmfExperiment experiment
= (TmfExperiment
) trace
;
607 traces
= experiment
.getTraces();
609 traces
= new ITmfTrace
[] { trace
};
611 ArrayList
<ControlFlowEntry
> rootList
= new ArrayList
<ControlFlowEntry
>();
612 for (ITmfTrace aTrace
: traces
) {
613 if (monitor
.isCanceled()) {
616 if (aTrace
instanceof CtfKernelTrace
) {
617 ArrayList
<ControlFlowEntry
> entryList
= new ArrayList
<ControlFlowEntry
>();
618 CtfKernelTrace ctfKernelTrace
= (CtfKernelTrace
) aTrace
;
619 ITmfStateSystem ssq
= ctfKernelTrace
.getStateSystem();
620 if (!ssq
.waitUntilBuilt()) {
623 long start
= ssq
.getStartTime();
624 long end
= ssq
.getCurrentEndTime() + 1;
625 fStartTime
= Math
.min(fStartTime
, start
);
626 fEndTime
= Math
.max(fEndTime
, end
);
627 List
<Integer
> threadQuarks
= ssq
.getQuarks(Attributes
.THREADS
, "*"); //$NON-NLS-1$
628 for (int threadQuark
: threadQuarks
) {
629 if (monitor
.isCanceled()) {
632 String threadName
= ssq
.getAttributeName(threadQuark
);
635 threadId
= Integer
.parseInt(threadName
);
636 } catch (NumberFormatException e1
) {
639 if (threadId
== 0) { // ignore the swapper thread
642 int execNameQuark
= -1;
645 execNameQuark
= ssq
.getQuarkRelative(threadQuark
, Attributes
.EXEC_NAME
);
646 } catch (AttributeNotFoundException e
) {
649 int ppidQuark
= ssq
.getQuarkRelative(threadQuark
, Attributes
.PPID
);
650 List
<ITmfStateInterval
> execNameIntervals
= ssq
.queryHistoryRange(execNameQuark
, start
, end
- 1); // use monitor when available in api
651 if (monitor
.isCanceled()) {
655 for (ITmfStateInterval execNameInterval
: execNameIntervals
) {
656 if (monitor
.isCanceled()) {
659 if (!execNameInterval
.getStateValue().isNull() && execNameInterval
.getStateValue().getType() == 1) {
660 String execName
= execNameInterval
.getStateValue().unboxStr();
661 long startTime
= execNameInterval
.getStartTime();
662 long endTime
= execNameInterval
.getEndTime() + 1;
663 if (birthTime
== -1) {
664 birthTime
= startTime
;
667 if (ppidQuark
!= -1) {
668 ITmfStateInterval ppidInterval
= ssq
.querySingleState(startTime
, ppidQuark
);
669 ppid
= ppidInterval
.getStateValue().unboxInt();
671 ControlFlowEntry entry
= new ControlFlowEntry(threadQuark
, ctfKernelTrace
, execName
, threadId
, ppid
, birthTime
, startTime
, endTime
);
672 entryList
.add(entry
);
673 entry
.addEvent(new TimeEvent(entry
, startTime
, endTime
- startTime
));
678 } catch (AttributeNotFoundException e
) {
680 } catch (TimeRangeException e
) {
682 } catch (StateValueTypeException e
) {
684 } catch (StateSystemDisposedException e
) {
688 buildTree(entryList
, rootList
);
690 Collections
.sort(rootList
, fControlFlowEntryComparator
);
691 synchronized (fEntryListMap
) {
692 fEntryListMap
.put(trace
, (ArrayList
<ControlFlowEntry
>) rootList
.clone());
694 if (trace
== fTrace
) {
695 refresh(INITIAL_WINDOW_OFFSET
);
698 for (ControlFlowEntry entry
: rootList
) {
699 if (monitor
.isCanceled()) {
702 buildStatusEvents(trace
, entry
, monitor
);
706 private static void buildTree(ArrayList
<ControlFlowEntry
> entryList
,
707 ArrayList
<ControlFlowEntry
> rootList
) {
708 for (ControlFlowEntry entry
: entryList
) {
710 if (entry
.getParentThreadId() > 0) {
711 for (ControlFlowEntry parent
: entryList
) {
712 if (parent
.getThreadId() == entry
.getParentThreadId() &&
713 entry
.getStartTime() >= parent
.getStartTime() &&
714 entry
.getStartTime() <= parent
.getEndTime()) {
715 parent
.addChild(entry
);
727 private void buildStatusEvents(ITmfTrace trace
, ControlFlowEntry entry
, IProgressMonitor monitor
) {
728 ITmfStateSystem ssq
= entry
.getTrace().getStateSystem();
729 long start
= ssq
.getStartTime();
730 long end
= ssq
.getCurrentEndTime() + 1;
731 long resolution
= Math
.max(1, (end
- start
) / fDisplayWidth
);
732 List
<ITimeEvent
> eventList
= getEventList(entry
, entry
.getStartTime(), entry
.getEndTime(), resolution
, monitor
);
733 if (monitor
.isCanceled()) {
736 entry
.setEventList(eventList
);
737 if (trace
== fTrace
) {
740 for (ITimeGraphEntry child
: entry
.getChildren()) {
741 if (monitor
.isCanceled()) {
744 buildStatusEvents(trace
, (ControlFlowEntry
) child
, monitor
);
748 private static List
<ITimeEvent
> getEventList(ControlFlowEntry entry
,
749 long startTime
, long endTime
, long resolution
,
750 IProgressMonitor monitor
) {
751 startTime
= Math
.max(startTime
, entry
.getStartTime());
752 endTime
= Math
.min(endTime
, entry
.getEndTime());
753 if (endTime
<= startTime
) {
756 ITmfStateSystem ssq
= entry
.getTrace().getStateSystem();
757 List
<ITimeEvent
> eventList
= null;
759 int statusQuark
= ssq
.getQuarkRelative(entry
.getThreadQuark(), Attributes
.STATUS
);
760 List
<ITmfStateInterval
> statusIntervals
= ssq
.queryHistoryRange(statusQuark
, startTime
, endTime
- 1, resolution
, monitor
);
761 eventList
= new ArrayList
<ITimeEvent
>(statusIntervals
.size());
762 long lastEndTime
= -1;
763 for (ITmfStateInterval statusInterval
: statusIntervals
) {
764 if (monitor
.isCanceled()) {
767 long time
= statusInterval
.getStartTime();
768 long duration
= statusInterval
.getEndTime() - time
+ 1;
771 status
= statusInterval
.getStateValue().unboxInt();
772 } catch (StateValueTypeException e
) {
775 if (lastEndTime
!= time
&& lastEndTime
!= -1) {
776 eventList
.add(new ControlFlowEvent(entry
, lastEndTime
, time
- lastEndTime
, 0));
778 eventList
.add(new ControlFlowEvent(entry
, time
, duration
, status
));
779 lastEndTime
= time
+ duration
;
781 } catch (AttributeNotFoundException e
) {
783 } catch (TimeRangeException e
) {
785 } catch (StateSystemDisposedException e
) {
791 private void refresh(final long windowRange
) {
792 Display
.getDefault().asyncExec(new Runnable() {
795 if (fTimeGraphCombo
.isDisposed()) {
798 ITimeGraphEntry
[] entries
= null;
799 synchronized (fEntryListMap
) {
800 fEntryList
= fEntryListMap
.get(fTrace
);
801 if (fEntryList
== null) {
802 fEntryList
= new ArrayList
<ControlFlowEntry
>();
804 entries
= fEntryList
.toArray(new ITimeGraphEntry
[0]);
806 Arrays
.sort(entries
, fControlFlowEntryComparator
);
807 fTimeGraphCombo
.setInput(entries
);
808 fTimeGraphCombo
.getTimeGraphViewer().setTimeBounds(fStartTime
, fEndTime
);
810 long endTime
= fStartTime
+ windowRange
;
812 if (fEndTime
< endTime
) {
815 fTimeGraphCombo
.getTimeGraphViewer().setStartFinishTime(fStartTime
, endTime
);
816 for (TreeColumn column
: fTimeGraphCombo
.getTreeViewer().getTree().getColumns()) {
820 startZoomThread(fStartTime
, endTime
);
825 private void redraw() {
826 synchronized (fSyncObj
) {
827 if (fRedrawState
== State
.IDLE
) {
828 fRedrawState
= State
.BUSY
;
830 fRedrawState
= State
.PENDING
;
834 Display
.getDefault().asyncExec(new Runnable() {
837 if (fTimeGraphCombo
.isDisposed()) {
840 fTimeGraphCombo
.redraw();
841 fTimeGraphCombo
.update();
842 synchronized (fSyncObj
) {
843 if (fRedrawState
== State
.PENDING
) {
844 fRedrawState
= State
.IDLE
;
847 fRedrawState
= State
.IDLE
;
854 private void startZoomThread(long startTime
, long endTime
) {
855 if (fZoomThread
!= null) {
856 fZoomThread
.cancel();
858 fZoomThread
= new ZoomThread(fEntryList
, startTime
, endTime
);
862 private void makeActions() {
863 fPreviousResourceAction
= fTimeGraphCombo
.getTimeGraphViewer().getPreviousItemAction();
864 fPreviousResourceAction
.setText(Messages
.ControlFlowView_previousProcessActionNameText
);
865 fPreviousResourceAction
.setToolTipText(Messages
.ControlFlowView_previousProcessActionToolTipText
);
866 fNextResourceAction
= fTimeGraphCombo
.getTimeGraphViewer().getNextItemAction();
867 fNextResourceAction
.setText(Messages
.ControlFlowView_nextProcessActionNameText
);
868 fNextResourceAction
.setToolTipText(Messages
.ControlFlowView_nextProcessActionToolTipText
);
871 private void contributeToActionBars() {
872 IActionBars bars
= getViewSite().getActionBars();
873 fillLocalToolBar(bars
.getToolBarManager());
876 private void fillLocalToolBar(IToolBarManager manager
) {
877 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getShowLegendAction());
878 manager
.add(new Separator());
879 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getResetScaleAction());
880 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getPreviousEventAction());
881 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getNextEventAction());
882 manager
.add(fPreviousResourceAction
);
883 manager
.add(fNextResourceAction
);
884 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getZoomInAction());
885 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getZoomOutAction());
886 manager
.add(new Separator());