Commit | Line | Data |
---|---|---|
04835162 PT |
1 | /*******************************************************************************\r |
2 | * Copyright (c) 2012 Ericsson\r | |
3 | * \r | |
4 | * All rights reserved. This program and the accompanying materials are\r | |
5 | * made available under the terms of the Eclipse Public License v1.0 which\r | |
6 | * accompanies this distribution, and is available at\r | |
7 | * http://www.eclipse.org/legal/epl-v10.html\r | |
8 | * \r | |
9 | * Contributors:\r | |
10 | * Patrick Tasse - Initial API and implementation\r | |
11 | *******************************************************************************/\r | |
12 | \r | |
13 | package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.controlflow;\r | |
14 | \r | |
15 | import java.util.ArrayList;\r | |
16 | import java.util.Arrays;\r | |
17 | import java.util.HashMap;\r | |
18 | import java.util.List;\r | |
19 | import java.util.Map;\r | |
20 | \r | |
21 | import org.eclipse.jface.viewers.ILabelProviderListener;\r | |
22 | import org.eclipse.jface.viewers.ITableLabelProvider;\r | |
23 | import org.eclipse.jface.viewers.ITreeContentProvider;\r | |
24 | import org.eclipse.jface.viewers.Viewer;\r | |
25 | import org.eclipse.linuxtools.internal.lttng2.kernel.ui.Messages;\r | |
26 | import org.eclipse.linuxtools.lttng2.kernel.core.trace.Attributes;\r | |
27 | import org.eclipse.linuxtools.lttng2.kernel.core.trace.CtfKernelTrace;\r | |
28 | import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;\r | |
29 | import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;\r | |
30 | import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;\r | |
31 | import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;\r | |
32 | import org.eclipse.linuxtools.tmf.core.experiment.TmfExperiment;\r | |
33 | import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;\r | |
34 | import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentSelectedSignal;\r | |
35 | import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;\r | |
36 | import org.eclipse.linuxtools.tmf.core.statesystem.IStateSystemQuerier;\r | |
37 | import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;\r | |
38 | import org.eclipse.linuxtools.tmf.ui.views.TmfView;\r | |
39 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;\r | |
40 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphSelectionListener;\r | |
41 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;\r | |
42 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphCombo;\r | |
43 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphProvider;\r | |
44 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;\r | |
45 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphSelectionEvent;\r | |
46 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;\r | |
47 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;\r | |
48 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;\r | |
49 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeEvent;\r | |
50 | import org.eclipse.swt.SWT;\r | |
51 | import org.eclipse.swt.graphics.Image;\r | |
52 | import org.eclipse.swt.widgets.Composite;\r | |
53 | import org.eclipse.swt.widgets.Display;\r | |
54 | \r | |
55 | public class ControlFlowView extends TmfView {\r | |
56 | \r | |
57 | // ------------------------------------------------------------------------\r | |
58 | // Constants\r | |
59 | // ------------------------------------------------------------------------\r | |
60 | \r | |
61 | /**\r | |
62 | * View ID.\r | |
63 | */\r | |
64 | public static final String ID = "org.eclipse.linuxtools.lttng2.kernel.ui.views.controlflow"; //$NON-NLS-1$\r | |
65 | \r | |
66 | private final String PROCESS_COLUMN = Messages.ControlFlowView_processColumn;\r | |
67 | private final String TID_COLUMN = Messages.ControlFlowView_tidColumn;\r | |
68 | private final String TGID_COLUMN = Messages.ControlFlowView_tgidColumn;\r | |
69 | private final String PPID_COLUMN = Messages.ControlFlowView_ppidColumn;\r | |
70 | private final String CPU_COLUMN = Messages.ControlFlowView_cpuColumn;\r | |
71 | private final String BIRTH_SEC_COLUMN = Messages.ControlFlowView_birthSecColumn;\r | |
72 | private final String BIRTH_NSEC_COLUMN = Messages.ControlFlowView_birthNsecColumn;\r | |
73 | private final String TRACE_COLUMN = Messages.ControlFlowView_traceColumn;\r | |
74 | \r | |
75 | private final String[] COLUMN_NAMES = new String[] {\r | |
76 | PROCESS_COLUMN,\r | |
77 | TID_COLUMN,\r | |
78 | TGID_COLUMN,\r | |
79 | PPID_COLUMN,\r | |
80 | CPU_COLUMN,\r | |
81 | BIRTH_SEC_COLUMN,\r | |
82 | BIRTH_NSEC_COLUMN,\r | |
83 | TRACE_COLUMN\r | |
84 | };\r | |
85 | \r | |
86 | // ------------------------------------------------------------------------\r | |
87 | // Fields\r | |
88 | // ------------------------------------------------------------------------\r | |
89 | \r | |
90 | // The timegraph combo\r | |
91 | private TimeGraphCombo fTimeGraphCombo;\r | |
92 | \r | |
93 | // The selected experiment\r | |
94 | private TmfExperiment<ITmfEvent> fSelectedExperiment;\r | |
95 | \r | |
96 | // The timegraph entry list\r | |
97 | private ArrayList<ITimeGraphEntry> fEntryList;\r | |
98 | \r | |
99 | // The start time\r | |
100 | private long fStartTime;\r | |
101 | \r | |
102 | // The end time\r | |
103 | private long fEndTime;\r | |
104 | \r | |
105 | // ------------------------------------------------------------------------\r | |
106 | // Classes\r | |
107 | // ------------------------------------------------------------------------\r | |
108 | \r | |
109 | private class TreeContentProvider implements ITreeContentProvider {\r | |
110 | \r | |
111 | @Override\r | |
112 | public void dispose() {\r | |
113 | }\r | |
114 | \r | |
115 | @Override\r | |
116 | public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r | |
117 | }\r | |
118 | \r | |
119 | @Override\r | |
120 | public Object[] getElements(Object inputElement) {\r | |
121 | return (ITimeGraphEntry[]) inputElement;\r | |
122 | }\r | |
123 | \r | |
124 | @Override\r | |
125 | public Object[] getChildren(Object parentElement) {\r | |
126 | ITimeGraphEntry entry = (ITimeGraphEntry) parentElement;\r | |
127 | return entry.getChildren();\r | |
128 | }\r | |
129 | \r | |
130 | @Override\r | |
131 | public Object getParent(Object element) {\r | |
132 | ITimeGraphEntry entry = (ITimeGraphEntry) element;\r | |
133 | return entry.getParent();\r | |
134 | }\r | |
135 | \r | |
136 | @Override\r | |
137 | public boolean hasChildren(Object element) {\r | |
138 | ITimeGraphEntry entry = (ITimeGraphEntry) element;\r | |
139 | return entry.hasChildren();\r | |
140 | }\r | |
141 | \r | |
142 | }\r | |
143 | \r | |
144 | private class TreeLabelProvider implements ITableLabelProvider {\r | |
145 | \r | |
146 | @Override\r | |
147 | public void addListener(ILabelProviderListener listener) {\r | |
148 | }\r | |
149 | \r | |
150 | @Override\r | |
151 | public void dispose() {\r | |
152 | }\r | |
153 | \r | |
154 | @Override\r | |
155 | public boolean isLabelProperty(Object element, String property) {\r | |
156 | return false;\r | |
157 | }\r | |
158 | \r | |
159 | @Override\r | |
160 | public void removeListener(ILabelProviderListener listener) {\r | |
161 | }\r | |
162 | \r | |
163 | @Override\r | |
164 | public Image getColumnImage(Object element, int columnIndex) {\r | |
165 | return null;\r | |
166 | }\r | |
167 | \r | |
168 | @Override\r | |
169 | public String getColumnText(Object element, int columnIndex) {\r | |
170 | ControlFlowEntry entry = (ControlFlowEntry) element;\r | |
171 | if (columnIndex == 0) {\r | |
172 | return entry.getName();\r | |
173 | } else if (columnIndex == 1) {\r | |
174 | return Integer.toString(entry.getThreadId());\r | |
175 | } else if (columnIndex == 3) {\r | |
176 | if (entry.getPPID() != -1) {\r | |
177 | return Integer.toString(entry.getPPID());\r | |
178 | }\r | |
179 | }\r | |
180 | return ""; //$NON-NLS-1$\r | |
181 | }\r | |
182 | \r | |
183 | }\r | |
184 | \r | |
185 | // ------------------------------------------------------------------------\r | |
186 | // Constructors\r | |
187 | // ------------------------------------------------------------------------\r | |
188 | \r | |
189 | public ControlFlowView() {\r | |
190 | super(ID);\r | |
191 | }\r | |
192 | \r | |
193 | // ------------------------------------------------------------------------\r | |
194 | // ViewPart\r | |
195 | // ------------------------------------------------------------------------\r | |
196 | \r | |
197 | /* (non-Javadoc)\r | |
198 | * @see org.eclipse.linuxtools.tmf.ui.views.TmfView#createPartControl(org.eclipse.swt.widgets.Composite)\r | |
199 | */\r | |
200 | @Override\r | |
201 | public void createPartControl(Composite parent) {\r | |
202 | fTimeGraphCombo = new TimeGraphCombo(parent, SWT.NONE);\r | |
203 | \r | |
204 | fTimeGraphCombo.setTreeContentProvider(new TreeContentProvider());\r | |
205 | \r | |
206 | fTimeGraphCombo.setTreeLabelProvider(new TreeLabelProvider());\r | |
207 | \r | |
208 | fTimeGraphCombo.setTimeGraphProvider(new TimeGraphProvider() {\r | |
209 | @Override\r | |
210 | public String getTraceClassName(ITimeGraphEntry trace) {\r | |
211 | return "trace class"; //$NON-NLS-1$\r | |
212 | }\r | |
213 | \r | |
214 | @Override\r | |
215 | public String getStateName(StateColor color) {\r | |
216 | return "state name"; //$NON-NLS-1$\r | |
217 | }\r | |
218 | \r | |
219 | @Override\r | |
220 | public String getEventName(ITimeEvent event, boolean upper, boolean extInfo) {\r | |
221 | return "event name"; //$NON-NLS-1$\r | |
222 | }\r | |
223 | \r | |
224 | @Override\r | |
225 | public Map<String, String> getEventHoverToolTipInfo(ITimeEvent event) {\r | |
226 | return new HashMap<String, String>();\r | |
227 | }\r | |
228 | \r | |
229 | @Override\r | |
230 | public StateColor getEventColor(ITimeEvent event) {\r | |
231 | return StateColor.BLACK;\r | |
232 | }\r | |
233 | });\r | |
234 | \r | |
235 | fTimeGraphCombo.setTreeColumns(COLUMN_NAMES);\r | |
236 | \r | |
237 | fTimeGraphCombo.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {\r | |
238 | @Override\r | |
239 | public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {\r | |
240 | long startTime = event.getStartTime();\r | |
241 | long endTime = event.getEndTime();\r | |
242 | System.out.println("timeRangeUpdated: startTime="+startTime+" endTime="+endTime);\r | |
243 | }\r | |
244 | });\r | |
245 | \r | |
246 | fTimeGraphCombo.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {\r | |
247 | @Override\r | |
248 | public void timeSelected(TimeGraphTimeEvent event) {\r | |
249 | long time = event.getTime();\r | |
250 | System.out.println("timeSelected: time="+time);\r | |
251 | }\r | |
252 | });\r | |
253 | \r | |
254 | fTimeGraphCombo.addSelectionListener(new ITimeGraphSelectionListener() {\r | |
255 | @Override\r | |
256 | public void selectionChanged(TimeGraphSelectionEvent event) {\r | |
257 | ITimeGraphEntry selection = event.getSelection();\r | |
258 | System.out.println("selectionChanged: source="+event.getSource()+" selection="+ (selection == null ? selection : selection.getName()));\r | |
259 | }\r | |
260 | });\r | |
261 | \r | |
262 | final Thread thread = new Thread() {\r | |
263 | @Override\r | |
264 | public void run() {\r | |
265 | if (TmfExperiment.getCurrentExperiment() != null) {\r | |
266 | selectExperiment(TmfExperiment.getCurrentExperiment());\r | |
267 | }\r | |
268 | }\r | |
269 | };\r | |
270 | thread.start();\r | |
271 | }\r | |
272 | \r | |
273 | /* (non-Javadoc)\r | |
274 | * @see org.eclipse.ui.part.WorkbenchPart#setFocus()\r | |
275 | */\r | |
276 | @Override\r | |
277 | public void setFocus() {\r | |
278 | fTimeGraphCombo.setFocus();\r | |
279 | }\r | |
280 | \r | |
281 | // ------------------------------------------------------------------------\r | |
282 | // Signal handlers\r | |
283 | // ------------------------------------------------------------------------\r | |
284 | \r | |
285 | @TmfSignalHandler\r | |
286 | public void experimentSelected(final TmfExperimentSelectedSignal<? extends ITmfEvent> signal) {\r | |
287 | if (signal.getExperiment().equals(fSelectedExperiment)) {\r | |
288 | return;\r | |
289 | }\r | |
290 | \r | |
291 | final Thread thread = new Thread() {\r | |
292 | @Override\r | |
293 | public void run() {\r | |
294 | selectExperiment(signal.getExperiment());\r | |
295 | }};\r | |
296 | thread.run();\r | |
297 | }\r | |
298 | \r | |
299 | @SuppressWarnings("unchecked")\r | |
300 | private void selectExperiment(TmfExperiment<?> experiment) {\r | |
301 | fStartTime = Long.MAX_VALUE;\r | |
302 | fEndTime = Long.MIN_VALUE;\r | |
303 | fSelectedExperiment = (TmfExperiment<ITmfEvent>) experiment;\r | |
304 | HashMap<String, ITimeGraphEntry> traces = new HashMap<String, ITimeGraphEntry>();\r | |
305 | fEntryList = new ArrayList<ITimeGraphEntry>();\r | |
306 | for (ITmfTrace<?> trace : experiment.getTraces()) {\r | |
307 | if (trace instanceof CtfKernelTrace) {\r | |
308 | CtfKernelTrace ctfKernelTrace = (CtfKernelTrace) trace;\r | |
309 | IStateSystemQuerier ssq = ctfKernelTrace.getStateSystem();\r | |
310 | ControlFlowEntry swapperEntry = null;\r | |
311 | long start = ssq.getStartTime();\r | |
312 | long end = ssq.getCurrentEndTime();\r | |
313 | fStartTime = Math.min(fStartTime, start);\r | |
314 | fEndTime = Math.max(fEndTime, end);\r | |
315 | List<Integer> threadQuarks = ssq.getQuarks(Attributes.THREADS, "*"); //$NON-NLS-1$\r | |
316 | for (int threadQuark : threadQuarks) {\r | |
317 | String threadName = ssq.getAttributeName(threadQuark);\r | |
318 | int threadId = -1;\r | |
319 | try {\r | |
320 | threadId = Integer.parseInt(threadName);\r | |
321 | } catch (NumberFormatException e1) {\r | |
322 | continue;\r | |
323 | }\r | |
324 | int execNameQuark = -1;\r | |
325 | try {\r | |
326 | try {\r | |
327 | execNameQuark = ssq.getQuarkRelative(threadQuark, Attributes.EXEC_NAME);\r | |
328 | } catch (AttributeNotFoundException e) {\r | |
329 | continue;\r | |
330 | }\r | |
331 | int ppidQuark = ssq.getQuarkRelative(threadQuark, Attributes.PPID);\r | |
332 | List<ITmfStateInterval> execNameIntervals = ssq.queryHistoryRange(execNameQuark, start, end);\r | |
333 | for (ITmfStateInterval execNameInterval : execNameIntervals) {\r | |
334 | if (!execNameInterval.getStateValue().isNull() && execNameInterval.getStateValue().getType() == 1) {\r | |
335 | String execName = execNameInterval.getStateValue().unboxStr();\r | |
336 | long startTime = execNameInterval.getStartTime();\r | |
337 | long endTime = execNameInterval.getEndTime();\r | |
338 | int ppid = -1;\r | |
339 | if (ppidQuark != -1) {\r | |
340 | ITmfStateInterval ppidInterval = ssq.querySingleState(startTime, ppidQuark);\r | |
341 | ppid = ppidInterval.getStateValue().unboxInt();\r | |
342 | }\r | |
343 | ControlFlowEntry entry;\r | |
344 | if (threadId == 0) {\r | |
345 | if (swapperEntry == null) {\r | |
346 | swapperEntry = new ControlFlowEntry(ctfKernelTrace, "swapper", threadId, ppid, startTime, endTime);\r | |
347 | fEntryList.add(swapperEntry);\r | |
348 | }\r | |
349 | entry = swapperEntry;\r | |
350 | } else {\r | |
351 | entry = new ControlFlowEntry(ctfKernelTrace, execName, threadId, ppid, startTime, endTime);\r | |
352 | fEntryList.add(entry);\r | |
353 | }\r | |
354 | entry.addTraceEvent(new TimeEvent(entry, startTime, endTime - startTime));\r | |
355 | }\r | |
356 | }\r | |
357 | } catch (AttributeNotFoundException e) {\r | |
358 | e.printStackTrace();\r | |
359 | } catch (TimeRangeException e) {\r | |
360 | e.printStackTrace();\r | |
361 | } catch (StateValueTypeException e) {\r | |
362 | e.printStackTrace();\r | |
363 | }\r | |
364 | }\r | |
365 | }\r | |
366 | refresh();\r | |
367 | }\r | |
368 | }\r | |
369 | \r | |
370 | private void refresh() {\r | |
371 | Display.getDefault().asyncExec(new Runnable() {\r | |
372 | @Override\r | |
373 | public void run() {\r | |
374 | if (fTimeGraphCombo.isDisposed()) {\r | |
375 | return;\r | |
376 | }\r | |
377 | ITimeGraphEntry[] entries = fEntryList.toArray(new ITimeGraphEntry[0]);\r | |
378 | Arrays.sort(entries);\r | |
379 | fTimeGraphCombo.setInput(entries);\r | |
380 | fTimeGraphCombo.getTimeGraphViewer().setTimeBounds(fStartTime, fEndTime);\r | |
381 | fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(fStartTime, fEndTime);\r | |
382 | }\r | |
383 | });\r | |
384 | }\r | |
385 | \r | |
386 | }\r |