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
.List
;
21 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
22 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
23 import org
.eclipse
.jface
.action
.Action
;
24 import org
.eclipse
.jface
.action
.IToolBarManager
;
25 import org
.eclipse
.jface
.action
.Separator
;
26 import org
.eclipse
.jface
.viewers
.ILabelProviderListener
;
27 import org
.eclipse
.jface
.viewers
.ITableLabelProvider
;
28 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
29 import org
.eclipse
.jface
.viewers
.Viewer
;
30 import org
.eclipse
.linuxtools
.internal
.lttng2
.kernel
.core
.Attributes
;
31 import org
.eclipse
.linuxtools
.internal
.lttng2
.kernel
.ui
.Messages
;
32 import org
.eclipse
.linuxtools
.lttng2
.kernel
.core
.trace
.CtfKernelTrace
;
33 import org
.eclipse
.linuxtools
.tmf
.core
.ctfadaptor
.CtfTmfTimestamp
;
34 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimeRange
;
35 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimestamp
;
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
.TmfExperimentDisposedSignal
;
42 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfExperimentSelectedSignal
;
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
.TmfStateSystemBuildCompleted
;
46 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTimeSynchSignal
;
47 import org
.eclipse
.linuxtools
.tmf
.core
.statesystem
.ITmfStateSystem
;
48 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
49 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfExperiment
;
50 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.TmfView
;
51 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphRangeListener
;
52 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphSelectionListener
;
53 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphTimeListener
;
54 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphCombo
;
55 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphRangeUpdateEvent
;
56 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphSelectionEvent
;
57 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphTimeEvent
;
58 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
59 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
60 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.TimeEvent
;
61 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
;
62 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.Resolution
;
63 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.TimeFormat
;
64 import org
.eclipse
.swt
.SWT
;
65 import org
.eclipse
.swt
.graphics
.Image
;
66 import org
.eclipse
.swt
.widgets
.Composite
;
67 import org
.eclipse
.swt
.widgets
.Display
;
68 import org
.eclipse
.swt
.widgets
.TreeColumn
;
69 import org
.eclipse
.ui
.IActionBars
;
72 * The Control Flow view main object
75 public class ControlFlowView
extends TmfView
{
77 // ------------------------------------------------------------------------
79 // ------------------------------------------------------------------------
84 public static final String ID
= "org.eclipse.linuxtools.lttng2.kernel.ui.views.controlflow"; //$NON-NLS-1$
89 private static final long INITIAL_WINDOW_OFFSET
= (1L * 100 * 1000 * 1000); // .1sec
91 private static final String PROCESS_COLUMN
= Messages
.ControlFlowView_processColumn
;
92 private static final String TID_COLUMN
= Messages
.ControlFlowView_tidColumn
;
93 private static final String PTID_COLUMN
= Messages
.ControlFlowView_ptidColumn
;
94 private static final String BIRTH_TIME_COLUMN
= Messages
.ControlFlowView_birthTimeColumn
;
95 private static final String TRACE_COLUMN
= Messages
.ControlFlowView_traceColumn
;
97 private final String
[] COLUMN_NAMES
= new String
[] {
108 private enum State
{ IDLE
, BUSY
, PENDING
}
110 // ------------------------------------------------------------------------
112 // ------------------------------------------------------------------------
114 // The timegraph combo
115 private TimeGraphCombo fTimeGraphCombo
;
117 // The selected experiment
118 private TmfExperiment fSelectedExperiment
;
120 // The timegraph entry list
121 private ArrayList
<ControlFlowEntry
> fEntryList
;
123 // The time graph entry list synchronization object
124 final private Object fEntryListSyncObj
= new Object();
127 private long fStartTime
;
130 private long fEndTime
;
133 private final int fDisplayWidth
;
136 private ZoomThread fZoomThread
;
138 // The next resource action
139 private Action fNextResourceAction
;
141 // The previous resource action
142 private Action fPreviousResourceAction
;
144 // A comparator class
145 private final ControlFlowEntryComparator fControlFlowEntryComparator
= new ControlFlowEntryComparator();
147 // The redraw state used to prevent unnecessary queuing of display runnables
148 private State fRedrawState
= State
.IDLE
;
150 // The redraw synchronization object
151 final private Object fSyncObj
= new Object();
153 // ------------------------------------------------------------------------
155 // ------------------------------------------------------------------------
157 private class TreeContentProvider
implements ITreeContentProvider
{
160 public void dispose() {
164 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
168 public Object
[] getElements(Object inputElement
) {
169 return (ITimeGraphEntry
[]) inputElement
;
173 public Object
[] getChildren(Object parentElement
) {
174 ITimeGraphEntry entry
= (ITimeGraphEntry
) parentElement
;
175 List
<?
extends ITimeGraphEntry
> children
= entry
.getChildren();
176 return children
.toArray(new ITimeGraphEntry
[children
.size()]);
180 public Object
getParent(Object element
) {
181 ITimeGraphEntry entry
= (ITimeGraphEntry
) element
;
182 return entry
.getParent();
186 public boolean hasChildren(Object element
) {
187 ITimeGraphEntry entry
= (ITimeGraphEntry
) element
;
188 return entry
.hasChildren();
193 private class TreeLabelProvider
implements ITableLabelProvider
{
196 public void addListener(ILabelProviderListener listener
) {
200 public void dispose() {
204 public boolean isLabelProperty(Object element
, String property
) {
209 public void removeListener(ILabelProviderListener listener
) {
213 public Image
getColumnImage(Object element
, int columnIndex
) {
218 public String
getColumnText(Object element
, int columnIndex
) {
219 ControlFlowEntry entry
= (ControlFlowEntry
) element
;
220 if (columnIndex
== 0) {
221 return entry
.getName();
222 } else if (columnIndex
== 1) {
223 return Integer
.toString(entry
.getThreadId());
224 } else if (columnIndex
== 2) {
225 if (entry
.getParentThreadId() > 0) {
226 return Integer
.toString(entry
.getParentThreadId());
228 } else if (columnIndex
== 3) {
229 return Utils
.formatTime(entry
.getBirthTime(), TimeFormat
.ABSOLUTE
, Resolution
.NANOSEC
);
230 } else if (columnIndex
== 4) {
231 return entry
.getTrace().getName();
233 return ""; //$NON-NLS-1$
238 private static class ControlFlowEntryComparator
implements Comparator
<ITimeGraphEntry
> {
241 public int compare(ITimeGraphEntry o1
, ITimeGraphEntry o2
) {
244 if ((o1
instanceof ControlFlowEntry
) && (o2
instanceof ControlFlowEntry
)) {
245 ControlFlowEntry entry1
= (ControlFlowEntry
) o1
;
246 ControlFlowEntry entry2
= (ControlFlowEntry
) o2
;
247 result
= entry1
.getTrace().getStartTime().compareTo(entry2
.getTrace().getStartTime());
249 result
= entry1
.getTrace().getName().compareTo(entry2
.getTrace().getName());
252 result
= entry1
.getThreadId() < entry2
.getThreadId() ?
-1 : entry1
.getThreadId() > entry2
.getThreadId() ?
1 : 0;
257 result
= o1
.getStartTime() < o2
.getStartTime() ?
-1 : o1
.getStartTime() > o2
.getStartTime() ?
1 : 0;
265 private class ZoomThread
extends Thread
{
266 private final long fZoomStartTime
;
267 private final long fZoomEndTime
;
268 private final long fResolution
;
269 private final IProgressMonitor fMonitor
;
271 public ZoomThread(long startTime
, long endTime
) {
272 super("ControlFlowView zoom"); //$NON-NLS-1$
273 fZoomStartTime
= startTime
;
274 fZoomEndTime
= endTime
;
275 fResolution
= Math
.max(1, (fZoomEndTime
- fZoomStartTime
) / fDisplayWidth
);
276 fMonitor
= new NullProgressMonitor();
281 ArrayList
<ControlFlowEntry
> entryList
= null;
282 synchronized (fEntryListSyncObj
) {
283 entryList
= (ArrayList
<ControlFlowEntry
>) fEntryList
.clone();
285 if (entryList
== null) {
288 for (ControlFlowEntry entry
: entryList
) {
289 if (fMonitor
.isCanceled()) {
292 zoom(entry
, fMonitor
);
296 private void zoom(ControlFlowEntry entry
, IProgressMonitor monitor
) {
297 if (fZoomStartTime
<= fStartTime
&& fZoomEndTime
>= fEndTime
) {
298 entry
.setZoomedEventList(null);
300 List
<ITimeEvent
> zoomedEventList
= getEventList(entry
, fZoomStartTime
, fZoomEndTime
, fResolution
, monitor
);
301 if (zoomedEventList
!= null) {
302 entry
.setZoomedEventList(zoomedEventList
);
306 for (ControlFlowEntry child
: entry
.getChildren()) {
307 if (fMonitor
.isCanceled()) {
310 zoom(child
, monitor
);
314 public void cancel() {
315 fMonitor
.setCanceled(true);
319 // ------------------------------------------------------------------------
321 // ------------------------------------------------------------------------
326 public ControlFlowView() {
328 fDisplayWidth
= Display
.getDefault().getBounds().width
;
331 // ------------------------------------------------------------------------
333 // ------------------------------------------------------------------------
336 * @see org.eclipse.linuxtools.tmf.ui.views.TmfView#createPartControl(org.eclipse.swt.widgets.Composite)
339 public void createPartControl(Composite parent
) {
340 fTimeGraphCombo
= new TimeGraphCombo(parent
, SWT
.NONE
);
342 fTimeGraphCombo
.setTreeContentProvider(new TreeContentProvider());
344 fTimeGraphCombo
.setTreeLabelProvider(new TreeLabelProvider());
346 fTimeGraphCombo
.setTimeGraphProvider(new ControlFlowPresentationProvider());
348 fTimeGraphCombo
.setTreeColumns(COLUMN_NAMES
);
350 fTimeGraphCombo
.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
352 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event
) {
353 final long startTime
= event
.getStartTime();
354 final long endTime
= event
.getEndTime();
355 TmfTimeRange range
= new TmfTimeRange(new CtfTmfTimestamp(startTime
), new CtfTmfTimestamp(endTime
));
356 TmfTimestamp time
= new CtfTmfTimestamp(fTimeGraphCombo
.getTimeGraphViewer().getSelectedTime());
357 broadcast(new TmfRangeSynchSignal(ControlFlowView
.this, range
, time
));
358 if (fZoomThread
!= null) {
359 fZoomThread
.cancel();
361 startZoomThread(startTime
, endTime
);
365 fTimeGraphCombo
.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
367 public void timeSelected(TimeGraphTimeEvent event
) {
368 long time
= event
.getTime();
369 broadcast(new TmfTimeSynchSignal(ControlFlowView
.this, new CtfTmfTimestamp(time
)));
373 fTimeGraphCombo
.addSelectionListener(new ITimeGraphSelectionListener() {
375 public void selectionChanged(TimeGraphSelectionEvent event
) {
376 //ITimeGraphEntry selection = event.getSelection();
380 fTimeGraphCombo
.getTimeGraphViewer().setTimeCalendarFormat(true);
382 final Thread thread
= new Thread("ControlFlowView build") { //$NON-NLS-1$
385 if (TmfExperiment
.getCurrentExperiment() != null) {
386 selectExperiment(TmfExperiment
.getCurrentExperiment());
392 // View Action Handling
394 contributeToActionBars();
398 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
401 public void setFocus() {
402 fTimeGraphCombo
.setFocus();
405 // ------------------------------------------------------------------------
407 // ------------------------------------------------------------------------
410 * Handler for the experiment selected signal
413 * The signal that's received
416 public void experimentSelected(final TmfExperimentSelectedSignal signal
) {
417 if (signal
.getExperiment().equals(fSelectedExperiment
)) {
421 final Thread thread
= new Thread("ControlFlowView build") { //$NON-NLS-1$
424 selectExperiment(signal
.getExperiment());
431 * Experiment is disposed: clear the data structures and the view
433 * @param signal the signal received
436 public void experimentDisposed(final TmfExperimentDisposedSignal signal
) {
437 if (signal
.getExperiment().equals(fSelectedExperiment
)) {
438 fSelectedExperiment
= null;
441 fZoomThread
.cancel();
442 synchronized(fEntryListSyncObj
) {
445 refresh(INITIAL_WINDOW_OFFSET
);
450 * Handler for the synch signal
453 * The signal that's received
456 public void synchToTime(final TmfTimeSynchSignal signal
) {
457 if (signal
.getSource() == this || fSelectedExperiment
== null || fSelectedExperiment
.getTraces() == null) {
460 final long time
= signal
.getCurrentTime().normalize(0, -9).getValue();
463 for (ITmfTrace trace
: fSelectedExperiment
.getTraces()) {
467 if (trace
instanceof CtfKernelTrace
) {
468 CtfKernelTrace ctfKernelTrace
= (CtfKernelTrace
) trace
;
469 ITmfStateSystem ssq
= ctfKernelTrace
.getStateSystem();
470 if (time
>= ssq
.getStartTime() && time
<= ssq
.getCurrentEndTime()) {
471 List
<Integer
> currentThreadQuarks
= ssq
.getQuarks(Attributes
.CPUS
, "*", Attributes
.CURRENT_THREAD
); //$NON-NLS-1$
472 for (int currentThreadQuark
: currentThreadQuarks
) {
474 ITmfStateInterval currentThreadInterval
= ssq
.querySingleState(time
, currentThreadQuark
);
475 int currentThread
= currentThreadInterval
.getStateValue().unboxInt();
476 if (currentThread
> 0) {
477 int statusQuark
= ssq
.getQuarkAbsolute(Attributes
.THREADS
, Integer
.toString(currentThread
), Attributes
.STATUS
);
478 ITmfStateInterval statusInterval
= ssq
.querySingleState(time
, statusQuark
);
479 if (statusInterval
.getStartTime() == time
) {
480 thread
= currentThread
;
484 } catch (AttributeNotFoundException e
) {
486 } catch (TimeRangeException e
) {
488 } catch (StateValueTypeException e
) {
490 } catch (StateSystemDisposedException e
) {
497 final int selectedThread
= thread
;
499 Display
.getDefault().asyncExec(new Runnable() {
502 if (fTimeGraphCombo
.isDisposed()) {
505 fTimeGraphCombo
.getTimeGraphViewer().setSelectedTime(time
, true);
506 startZoomThread(fTimeGraphCombo
.getTimeGraphViewer().getTime0(), fTimeGraphCombo
.getTimeGraphViewer().getTime1());
508 if (selectedThread
> 0) {
509 for (Object element
: fTimeGraphCombo
.getTimeGraphViewer().getExpandedElements()) {
510 if (element
instanceof ControlFlowEntry
) {
511 ControlFlowEntry entry
= (ControlFlowEntry
) element
;
512 if (entry
.getThreadId() == selectedThread
) {
513 fTimeGraphCombo
.setSelection(entry
);
524 * Handler for the range sync signal
527 * The signal that's received
530 public void synchToRange(final TmfRangeSynchSignal signal
) {
531 if (signal
.getSource() == this || fSelectedExperiment
== null) {
534 final long startTime
= signal
.getCurrentRange().getStartTime().normalize(0, -9).getValue();
535 final long endTime
= signal
.getCurrentRange().getEndTime().normalize(0, -9).getValue();
536 final long time
= signal
.getCurrentTime().normalize(0, -9).getValue();
537 Display
.getDefault().asyncExec(new Runnable() {
540 if (fTimeGraphCombo
.isDisposed()) {
543 fTimeGraphCombo
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
544 fTimeGraphCombo
.getTimeGraphViewer().setSelectedTime(time
, false);
545 startZoomThread(startTime
, endTime
);
551 * Handler for the state system build completed signal
554 * The signal that's received
557 public void stateSystemBuildCompleted (final TmfStateSystemBuildCompleted signal
) {
558 final TmfExperiment selectedExperiment
= fSelectedExperiment
;
559 if (selectedExperiment
== null || selectedExperiment
.getTraces() == null) {
562 for (ITmfTrace trace
: selectedExperiment
.getTraces()) {
563 if (trace
== signal
.getTrace() && trace
instanceof CtfKernelTrace
) {
564 final Thread thread
= new Thread("ControlFlowView build") { //$NON-NLS-1$
568 selectExperiment(selectedExperiment
);
576 // ------------------------------------------------------------------------
578 // ------------------------------------------------------------------------
580 private void selectExperiment(TmfExperiment experiment
) {
581 fStartTime
= Long
.MAX_VALUE
;
582 fEndTime
= Long
.MIN_VALUE
;
583 fSelectedExperiment
= experiment
;
584 ArrayList
<ControlFlowEntry
> rootList
= new ArrayList
<ControlFlowEntry
>();
585 for (ITmfTrace trace
: experiment
.getTraces()) {
586 if (trace
instanceof CtfKernelTrace
) {
587 ArrayList
<ControlFlowEntry
> entryList
= new ArrayList
<ControlFlowEntry
>();
588 CtfKernelTrace ctfKernelTrace
= (CtfKernelTrace
) trace
;
589 ITmfStateSystem ssq
= ctfKernelTrace
.getStateSystem();
590 long start
= ssq
.getStartTime();
591 long end
= ssq
.getCurrentEndTime() + 1;
592 fStartTime
= Math
.min(fStartTime
, start
);
593 fEndTime
= Math
.max(fEndTime
, end
);
594 List
<Integer
> threadQuarks
= ssq
.getQuarks(Attributes
.THREADS
, "*"); //$NON-NLS-1$
595 for (int threadQuark
: threadQuarks
) {
596 String threadName
= ssq
.getAttributeName(threadQuark
);
599 threadId
= Integer
.parseInt(threadName
);
600 } catch (NumberFormatException e1
) {
603 if (threadId
== 0) { // ignore the swapper thread
606 int execNameQuark
= -1;
609 execNameQuark
= ssq
.getQuarkRelative(threadQuark
, Attributes
.EXEC_NAME
);
610 } catch (AttributeNotFoundException e
) {
613 int ppidQuark
= ssq
.getQuarkRelative(threadQuark
, Attributes
.PPID
);
614 List
<ITmfStateInterval
> execNameIntervals
= ssq
.queryHistoryRange(execNameQuark
, start
, end
- 1);
616 for (ITmfStateInterval execNameInterval
: execNameIntervals
) {
617 if (!execNameInterval
.getStateValue().isNull() && execNameInterval
.getStateValue().getType() == 1) {
618 String execName
= execNameInterval
.getStateValue().unboxStr();
619 long startTime
= execNameInterval
.getStartTime();
620 long endTime
= execNameInterval
.getEndTime() + 1;
621 if (birthTime
== -1) {
622 birthTime
= startTime
;
625 if (ppidQuark
!= -1) {
626 ITmfStateInterval ppidInterval
= ssq
.querySingleState(startTime
, ppidQuark
);
627 ppid
= ppidInterval
.getStateValue().unboxInt();
629 ControlFlowEntry entry
= new ControlFlowEntry(threadQuark
, ctfKernelTrace
, execName
, threadId
, ppid
, birthTime
, startTime
, endTime
);
630 entryList
.add(entry
);
631 entry
.addEvent(new TimeEvent(entry
, startTime
, endTime
- startTime
));
636 } catch (AttributeNotFoundException e
) {
638 } catch (TimeRangeException e
) {
640 } catch (StateValueTypeException e
) {
642 } catch (StateSystemDisposedException e
) {
646 buildTree(entryList
, rootList
);
648 Collections
.sort(rootList
, fControlFlowEntryComparator
);
649 synchronized (fEntryListSyncObj
) {
650 fEntryList
= (ArrayList
<ControlFlowEntry
>) rootList
.clone();
652 refresh(INITIAL_WINDOW_OFFSET
);
654 for (ControlFlowEntry entry
: rootList
) {
655 buildStatusEvents(entry
);
659 private static void buildTree(ArrayList
<ControlFlowEntry
> entryList
,
660 ArrayList
<ControlFlowEntry
> rootList
) {
661 for (ControlFlowEntry entry
: entryList
) {
663 if (entry
.getParentThreadId() > 0) {
664 for (ControlFlowEntry parent
: entryList
) {
665 if (parent
.getThreadId() == entry
.getParentThreadId() &&
666 entry
.getStartTime() >= parent
.getStartTime() &&
667 entry
.getStartTime() <= parent
.getEndTime()) {
668 parent
.addChild(entry
);
680 private void buildStatusEvents(ControlFlowEntry entry
) {
681 ITmfStateSystem ssq
= entry
.getTrace().getStateSystem();
682 long start
= ssq
.getStartTime();
683 long end
= ssq
.getCurrentEndTime() + 1;
684 long resolution
= Math
.max(1, (end
- start
) / fDisplayWidth
);
685 List
<ITimeEvent
> eventList
= getEventList(entry
, entry
.getStartTime(), entry
.getEndTime(), resolution
, new NullProgressMonitor());
686 entry
.setEventList(eventList
);
688 for (ITimeGraphEntry child
: entry
.getChildren()) {
689 buildStatusEvents((ControlFlowEntry
) child
);
693 private static List
<ITimeEvent
> getEventList(ControlFlowEntry entry
,
694 long startTime
, long endTime
, long resolution
,
695 IProgressMonitor monitor
) {
696 startTime
= Math
.max(startTime
, entry
.getStartTime());
697 endTime
= Math
.min(endTime
, entry
.getEndTime());
698 if (endTime
<= startTime
) {
701 ITmfStateSystem ssq
= entry
.getTrace().getStateSystem();
702 List
<ITimeEvent
> eventList
= null;
704 int statusQuark
= ssq
.getQuarkRelative(entry
.getThreadQuark(), Attributes
.STATUS
);
705 List
<ITmfStateInterval
> statusIntervals
= ssq
.queryHistoryRange(statusQuark
, startTime
, endTime
- 1, resolution
, monitor
);
706 eventList
= new ArrayList
<ITimeEvent
>(statusIntervals
.size());
707 long lastEndTime
= -1;
708 for (ITmfStateInterval statusInterval
: statusIntervals
) {
709 if (monitor
.isCanceled()) {
712 long time
= statusInterval
.getStartTime();
713 long duration
= statusInterval
.getEndTime() - time
+ 1;
716 status
= statusInterval
.getStateValue().unboxInt();
717 } catch (StateValueTypeException e
) {
720 if (lastEndTime
!= time
&& lastEndTime
!= -1) {
721 eventList
.add(new ControlFlowEvent(entry
, lastEndTime
, time
- lastEndTime
, 0));
723 eventList
.add(new ControlFlowEvent(entry
, time
, duration
, status
));
724 lastEndTime
= time
+ duration
;
726 } catch (AttributeNotFoundException e
) {
728 } catch (TimeRangeException e
) {
730 } catch (StateSystemDisposedException e
) {
736 private void refresh(final long windowRange
) {
737 Display
.getDefault().asyncExec(new Runnable() {
740 if (fTimeGraphCombo
.isDisposed()) {
743 ITimeGraphEntry
[] entries
= null;
744 synchronized (fEntryListSyncObj
) {
745 entries
= fEntryList
.toArray(new ITimeGraphEntry
[0]);
747 Arrays
.sort(entries
, fControlFlowEntryComparator
);
748 fTimeGraphCombo
.setInput(entries
);
749 fTimeGraphCombo
.getTimeGraphViewer().setTimeBounds(fStartTime
, fEndTime
);
751 long endTime
= fStartTime
+ windowRange
;
753 if (fEndTime
< endTime
) {
756 fTimeGraphCombo
.getTimeGraphViewer().setStartFinishTime(fStartTime
, endTime
);
757 for (TreeColumn column
: fTimeGraphCombo
.getTreeViewer().getTree().getColumns()) {
761 startZoomThread(fStartTime
, endTime
);
766 private void redraw() {
767 synchronized (fSyncObj
) {
768 if (fRedrawState
== State
.IDLE
) {
769 fRedrawState
= State
.BUSY
;
771 fRedrawState
= State
.PENDING
;
775 Display
.getDefault().asyncExec(new Runnable() {
778 if (fTimeGraphCombo
.isDisposed()) {
781 fTimeGraphCombo
.redraw();
782 fTimeGraphCombo
.update();
783 synchronized (fSyncObj
) {
784 if (fRedrawState
== State
.PENDING
) {
785 fRedrawState
= State
.IDLE
;
788 fRedrawState
= State
.IDLE
;
795 private void startZoomThread(long startTime
, long endTime
) {
796 if (fZoomThread
!= null) {
797 fZoomThread
.cancel();
799 fZoomThread
= new ZoomThread(startTime
, endTime
);
803 private void makeActions() {
804 fPreviousResourceAction
= fTimeGraphCombo
.getTimeGraphViewer().getPreviousItemAction();
805 fPreviousResourceAction
.setText(Messages
.ControlFlowView_previousProcessActionNameText
);
806 fPreviousResourceAction
.setToolTipText(Messages
.ControlFlowView_previousProcessActionToolTipText
);
807 fNextResourceAction
= fTimeGraphCombo
.getTimeGraphViewer().getNextItemAction();
808 fNextResourceAction
.setText(Messages
.ControlFlowView_nextProcessActionNameText
);
809 fNextResourceAction
.setToolTipText(Messages
.ControlFlowView_nextProcessActionToolTipText
);
812 private void contributeToActionBars() {
813 IActionBars bars
= getViewSite().getActionBars();
814 fillLocalToolBar(bars
.getToolBarManager());
817 private void fillLocalToolBar(IToolBarManager manager
) {
818 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getShowLegendAction());
819 manager
.add(new Separator());
820 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getResetScaleAction());
821 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getPreviousEventAction());
822 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getNextEventAction());
823 manager
.add(fPreviousResourceAction
);
824 manager
.add(fNextResourceAction
);
825 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getZoomInAction());
826 manager
.add(fTimeGraphCombo
.getTimeGraphViewer().getZoomOutAction());
827 manager
.add(new Separator());