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
.HashMap
;
18 import java
.util
.List
;
21 import org
.eclipse
.jface
.viewers
.ILabelProviderListener
;
22 import org
.eclipse
.jface
.viewers
.ITableLabelProvider
;
23 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
24 import org
.eclipse
.jface
.viewers
.Viewer
;
25 import org
.eclipse
.linuxtools
.internal
.lttng2
.kernel
.ui
.Messages
;
26 import org
.eclipse
.linuxtools
.lttng2
.kernel
.core
.trace
.Attributes
;
27 import org
.eclipse
.linuxtools
.lttng2
.kernel
.core
.trace
.CtfKernelTrace
;
28 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfEvent
;
29 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.AttributeNotFoundException
;
30 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.StateValueTypeException
;
31 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.TimeRangeException
;
32 import org
.eclipse
.linuxtools
.tmf
.core
.experiment
.TmfExperiment
;
33 import org
.eclipse
.linuxtools
.tmf
.core
.interval
.ITmfStateInterval
;
34 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfExperimentSelectedSignal
;
35 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfSignalHandler
;
36 import org
.eclipse
.linuxtools
.tmf
.core
.statesystem
.IStateSystemQuerier
;
37 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
38 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.TmfView
;
39 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphRangeListener
;
40 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphSelectionListener
;
41 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphTimeListener
;
42 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphCombo
;
43 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphProvider
;
44 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphRangeUpdateEvent
;
45 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphSelectionEvent
;
46 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphTimeEvent
;
47 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
48 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
49 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.TimeEvent
;
50 import org
.eclipse
.swt
.SWT
;
51 import org
.eclipse
.swt
.graphics
.Image
;
52 import org
.eclipse
.swt
.widgets
.Composite
;
53 import org
.eclipse
.swt
.widgets
.Display
;
55 public class ControlFlowView
extends TmfView
{
57 // ------------------------------------------------------------------------
59 // ------------------------------------------------------------------------
64 public static final String ID
= "org.eclipse.linuxtools.lttng2.kernel.ui.views.controlflow"; //$NON-NLS-1$
66 private final String PROCESS_COLUMN
= Messages
.ControlFlowView_processColumn
;
67 private final String TID_COLUMN
= Messages
.ControlFlowView_tidColumn
;
68 private final String TGID_COLUMN
= Messages
.ControlFlowView_tgidColumn
;
69 private final String PPID_COLUMN
= Messages
.ControlFlowView_ppidColumn
;
70 private final String CPU_COLUMN
= Messages
.ControlFlowView_cpuColumn
;
71 private final String BIRTH_SEC_COLUMN
= Messages
.ControlFlowView_birthSecColumn
;
72 private final String BIRTH_NSEC_COLUMN
= Messages
.ControlFlowView_birthNsecColumn
;
73 private final String TRACE_COLUMN
= Messages
.ControlFlowView_traceColumn
;
75 private final String
[] COLUMN_NAMES
= new String
[] {
86 // ------------------------------------------------------------------------
88 // ------------------------------------------------------------------------
90 // The timegraph combo
91 private TimeGraphCombo fTimeGraphCombo
;
93 // The selected experiment
94 private TmfExperiment
<ITmfEvent
> fSelectedExperiment
;
96 // The timegraph entry list
97 private ArrayList
<ITimeGraphEntry
> fEntryList
;
100 private long fStartTime
;
103 private long fEndTime
;
105 // ------------------------------------------------------------------------
107 // ------------------------------------------------------------------------
109 private class TreeContentProvider
implements ITreeContentProvider
{
112 public void dispose() {
116 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
120 public Object
[] getElements(Object inputElement
) {
121 return (ITimeGraphEntry
[]) inputElement
;
125 public Object
[] getChildren(Object parentElement
) {
126 ITimeGraphEntry entry
= (ITimeGraphEntry
) parentElement
;
127 return entry
.getChildren();
131 public Object
getParent(Object element
) {
132 ITimeGraphEntry entry
= (ITimeGraphEntry
) element
;
133 return entry
.getParent();
137 public boolean hasChildren(Object element
) {
138 ITimeGraphEntry entry
= (ITimeGraphEntry
) element
;
139 return entry
.hasChildren();
144 private class TreeLabelProvider
implements ITableLabelProvider
{
147 public void addListener(ILabelProviderListener listener
) {
151 public void dispose() {
155 public boolean isLabelProperty(Object element
, String property
) {
160 public void removeListener(ILabelProviderListener listener
) {
164 public Image
getColumnImage(Object element
, int columnIndex
) {
169 public String
getColumnText(Object element
, int columnIndex
) {
170 ControlFlowEntry entry
= (ControlFlowEntry
) element
;
171 if (columnIndex
== 0) {
172 return entry
.getName();
173 } else if (columnIndex
== 1) {
174 return Integer
.toString(entry
.getThreadId());
175 } else if (columnIndex
== 3) {
176 if (entry
.getPPID() != -1) {
177 return Integer
.toString(entry
.getPPID());
180 return ""; //$NON-NLS-1$
185 // ------------------------------------------------------------------------
187 // ------------------------------------------------------------------------
189 public ControlFlowView() {
193 // ------------------------------------------------------------------------
195 // ------------------------------------------------------------------------
198 * @see org.eclipse.linuxtools.tmf.ui.views.TmfView#createPartControl(org.eclipse.swt.widgets.Composite)
201 public void createPartControl(Composite parent
) {
202 fTimeGraphCombo
= new TimeGraphCombo(parent
, SWT
.NONE
);
204 fTimeGraphCombo
.setTreeContentProvider(new TreeContentProvider());
206 fTimeGraphCombo
.setTreeLabelProvider(new TreeLabelProvider());
208 fTimeGraphCombo
.setTimeGraphProvider(new TimeGraphProvider() {
210 public String
getTraceClassName(ITimeGraphEntry trace
) {
211 return "trace class"; //$NON-NLS-1$
215 public String
getStateName(StateColor color
) {
216 return "state name"; //$NON-NLS-1$
220 public String
getEventName(ITimeEvent event
, boolean upper
, boolean extInfo
) {
221 return "event name"; //$NON-NLS-1$
225 public Map
<String
, String
> getEventHoverToolTipInfo(ITimeEvent event
) {
226 return new HashMap
<String
, String
>();
230 public StateColor
getEventColor(ITimeEvent event
) {
231 return StateColor
.BLACK
;
235 fTimeGraphCombo
.setTreeColumns(COLUMN_NAMES
);
237 fTimeGraphCombo
.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
239 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event
) {
240 long startTime
= event
.getStartTime();
241 long endTime
= event
.getEndTime();
242 System
.out
.println("timeRangeUpdated: startTime="+startTime
+" endTime="+endTime
);
246 fTimeGraphCombo
.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
248 public void timeSelected(TimeGraphTimeEvent event
) {
249 long time
= event
.getTime();
250 System
.out
.println("timeSelected: time="+time
);
254 fTimeGraphCombo
.addSelectionListener(new ITimeGraphSelectionListener() {
256 public void selectionChanged(TimeGraphSelectionEvent event
) {
257 ITimeGraphEntry selection
= event
.getSelection();
258 System
.out
.println("selectionChanged: source="+event
.getSource()+" selection="+ (selection
== null ? selection
: selection
.getName()));
262 final Thread thread
= new Thread() {
265 if (TmfExperiment
.getCurrentExperiment() != null) {
266 selectExperiment(TmfExperiment
.getCurrentExperiment());
274 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
277 public void setFocus() {
278 fTimeGraphCombo
.setFocus();
281 // ------------------------------------------------------------------------
283 // ------------------------------------------------------------------------
286 public void experimentSelected(final TmfExperimentSelectedSignal
<?
extends ITmfEvent
> signal
) {
287 if (signal
.getExperiment().equals(fSelectedExperiment
)) {
291 final Thread thread
= new Thread() {
294 selectExperiment(signal
.getExperiment());
299 @SuppressWarnings("unchecked")
300 private void selectExperiment(TmfExperiment
<?
> experiment
) {
301 fStartTime
= Long
.MAX_VALUE
;
302 fEndTime
= Long
.MIN_VALUE
;
303 fSelectedExperiment
= (TmfExperiment
<ITmfEvent
>) experiment
;
304 HashMap
<String
, ITimeGraphEntry
> traces
= new HashMap
<String
, ITimeGraphEntry
>();
305 fEntryList
= new ArrayList
<ITimeGraphEntry
>();
306 for (ITmfTrace
<?
> trace
: experiment
.getTraces()) {
307 if (trace
instanceof CtfKernelTrace
) {
308 CtfKernelTrace ctfKernelTrace
= (CtfKernelTrace
) trace
;
309 IStateSystemQuerier ssq
= ctfKernelTrace
.getStateSystem();
310 ControlFlowEntry swapperEntry
= null;
311 long start
= ssq
.getStartTime();
312 long end
= ssq
.getCurrentEndTime();
313 fStartTime
= Math
.min(fStartTime
, start
);
314 fEndTime
= Math
.max(fEndTime
, end
);
315 List
<Integer
> threadQuarks
= ssq
.getQuarks(Attributes
.THREADS
, "*"); //$NON-NLS-1$
316 for (int threadQuark
: threadQuarks
) {
317 String threadName
= ssq
.getAttributeName(threadQuark
);
320 threadId
= Integer
.parseInt(threadName
);
321 } catch (NumberFormatException e1
) {
324 int execNameQuark
= -1;
327 execNameQuark
= ssq
.getQuarkRelative(threadQuark
, Attributes
.EXEC_NAME
);
328 } catch (AttributeNotFoundException e
) {
331 int ppidQuark
= ssq
.getQuarkRelative(threadQuark
, Attributes
.PPID
);
332 List
<ITmfStateInterval
> execNameIntervals
= ssq
.queryHistoryRange(execNameQuark
, start
, end
);
333 for (ITmfStateInterval execNameInterval
: execNameIntervals
) {
334 if (!execNameInterval
.getStateValue().isNull() && execNameInterval
.getStateValue().getType() == 1) {
335 String execName
= execNameInterval
.getStateValue().unboxStr();
336 long startTime
= execNameInterval
.getStartTime();
337 long endTime
= execNameInterval
.getEndTime();
339 if (ppidQuark
!= -1) {
340 ITmfStateInterval ppidInterval
= ssq
.querySingleState(startTime
, ppidQuark
);
341 ppid
= ppidInterval
.getStateValue().unboxInt();
343 ControlFlowEntry entry
;
345 if (swapperEntry
== null) {
346 swapperEntry
= new ControlFlowEntry(ctfKernelTrace
, "swapper", threadId
, ppid
, startTime
, endTime
);
347 fEntryList
.add(swapperEntry
);
349 entry
= swapperEntry
;
351 entry
= new ControlFlowEntry(ctfKernelTrace
, execName
, threadId
, ppid
, startTime
, endTime
);
352 fEntryList
.add(entry
);
354 entry
.addTraceEvent(new TimeEvent(entry
, startTime
, endTime
- startTime
));
357 } catch (AttributeNotFoundException e
) {
359 } catch (TimeRangeException e
) {
361 } catch (StateValueTypeException e
) {
370 private void refresh() {
371 Display
.getDefault().asyncExec(new Runnable() {
374 if (fTimeGraphCombo
.isDisposed()) {
377 ITimeGraphEntry
[] entries
= fEntryList
.toArray(new ITimeGraphEntry
[0]);
378 Arrays
.sort(entries
);
379 fTimeGraphCombo
.setInput(entries
);
380 fTimeGraphCombo
.getTimeGraphViewer().setTimeBounds(fStartTime
, fEndTime
);
381 fTimeGraphCombo
.getTimeGraphViewer().setStartFinishTime(fStartTime
, fEndTime
);