Fix endless loop in Resources view when trace is disposed
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng2.kernel.ui / src / org / eclipse / linuxtools / internal / lttng2 / kernel / ui / views / resources / ResourcesPresentationProvider.java
1 /*******************************************************************************
2 * Copyright (c) 2012 Ericsson
3 *
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
8 *
9 * Contributors:
10 * Patrick Tasse - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.resources;
14
15 import java.util.LinkedHashMap;
16 import java.util.List;
17 import java.util.Map;
18
19 import org.eclipse.linuxtools.internal.lttng2.kernel.core.Attributes;
20 import org.eclipse.linuxtools.internal.lttng2.kernel.core.StateValues;
21 import org.eclipse.linuxtools.internal.lttng2.kernel.ui.Messages;
22 import org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.resources.ResourcesEntry.Type;
23 import org.eclipse.linuxtools.lttng2.kernel.core.trace.CtfKernelTrace;
24 import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
25 import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException;
26 import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
27 import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
28 import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
29 import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
30 import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
31 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.StateItem;
32 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
33 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphViewer;
34 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;
35 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
36 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils;
37 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.Resolution;
38 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
39 import org.eclipse.swt.SWT;
40 import org.eclipse.swt.graphics.GC;
41 import org.eclipse.swt.graphics.RGB;
42 import org.eclipse.swt.graphics.Rectangle;
43
44 /**
45 * Presentation provider for the Resource view, based on the generic TMF
46 * presentation provider.
47 *
48 * @author Patrick Tasse
49 */
50 public class ResourcesPresentationProvider extends TimeGraphPresentationProvider {
51
52 private final TimeGraphViewer fTimeGraphViewer;
53 private long fLastThreadId = -1; // used to draw the process name label only once per thread id
54
55 private enum State {
56 UNKNOWN (new RGB(100, 100, 100)),
57 IDLE (new RGB(200, 200, 200)),
58 USERMODE (new RGB(0, 200, 0)),
59 SYSCALL (new RGB(0, 0, 200)),
60 IRQ (new RGB(200, 100, 100)),
61 SOFT_IRQ (new RGB(200, 150, 100)),
62 IRQ_ACTIVE (new RGB(200, 100, 100)),
63 SOFT_IRQ_RAISED (new RGB(200, 200, 0)),
64 SOFT_IRQ_ACTIVE (new RGB(200, 150, 100));
65
66 public final RGB rgb;
67
68 private State (RGB rgb) {
69 this.rgb = rgb;
70 }
71 }
72
73 /**
74 * Default constructor
75 *
76 * @param timeGraphViewer the time graph viewer
77 */
78 public ResourcesPresentationProvider(TimeGraphViewer timeGraphViewer) {
79 super();
80 this.fTimeGraphViewer = timeGraphViewer;
81 }
82
83 @Override
84 public String getStateTypeName() {
85 return Messages.ResourcesView_stateTypeName;
86 }
87
88 @Override
89 public StateItem[] getStateTable() {
90 StateItem[] stateTable = new StateItem[State.values().length];
91 for (int i = 0; i < stateTable.length; i++) {
92 State state = State.values()[i];
93 stateTable[i] = new StateItem(state.rgb, state.toString());
94 }
95 return stateTable;
96 }
97
98 @Override
99 public int getStateTableIndex(ITimeEvent event) {
100 if (event instanceof ResourcesEvent) {
101 ResourcesEvent resourcesEvent = (ResourcesEvent) event;
102 if (resourcesEvent.getType() == Type.CPU) {
103 int status = resourcesEvent.getValue();
104 if (status == StateValues.CPU_STATUS_IDLE) {
105 return State.IDLE.ordinal();
106 } else if (status == StateValues.CPU_STATUS_RUN_USERMODE) {
107 return State.USERMODE.ordinal();
108 } else if (status == StateValues.CPU_STATUS_RUN_SYSCALL) {
109 return State.SYSCALL.ordinal();
110 } else if (status == StateValues.CPU_STATUS_IRQ) {
111 return State.IRQ.ordinal();
112 } else if (status == StateValues.CPU_STATUS_SOFTIRQ) {
113 return State.SOFT_IRQ.ordinal();
114 }
115 } else if (resourcesEvent.getType() == Type.IRQ) {
116 return State.IRQ_ACTIVE.ordinal();
117 } else if (resourcesEvent.getType() == Type.SOFT_IRQ) {
118 int cpu = resourcesEvent.getValue();
119 if (cpu == StateValues.SOFT_IRQ_RAISED) {
120 return State.SOFT_IRQ_RAISED.ordinal();
121 }
122 return State.SOFT_IRQ_ACTIVE.ordinal();
123 } else {
124 return -1; // NULL
125 }
126 }
127 return State.UNKNOWN.ordinal();
128 }
129
130 @Override
131 public String getEventName(ITimeEvent event) {
132 if (event instanceof ResourcesEvent) {
133 ResourcesEvent resourcesEvent = (ResourcesEvent) event;
134 if (resourcesEvent.getType() == Type.CPU) {
135 int status = resourcesEvent.getValue();
136 if (status == StateValues.CPU_STATUS_IDLE) {
137 return State.IDLE.toString();
138 } else if (status == StateValues.CPU_STATUS_RUN_USERMODE) {
139 return State.USERMODE.toString();
140 } else if (status == StateValues.CPU_STATUS_RUN_SYSCALL) {
141 return State.SYSCALL.toString();
142 } else if (status == StateValues.CPU_STATUS_IRQ) {
143 return State.IRQ.toString();
144 } else if (status == StateValues.CPU_STATUS_SOFTIRQ) {
145 return State.SOFT_IRQ.toString();
146 }
147 } else if (resourcesEvent.getType() == Type.IRQ) {
148 return State.IRQ_ACTIVE.toString();
149 } else if (resourcesEvent.getType() == Type.SOFT_IRQ) {
150 int cpu = resourcesEvent.getValue();
151 if (cpu == StateValues.SOFT_IRQ_RAISED) {
152 return State.SOFT_IRQ_RAISED.toString();
153 }
154 return State.SOFT_IRQ_ACTIVE.toString();
155 } else {
156 return null;
157 }
158 }
159 return State.UNKNOWN.toString();
160 }
161
162 @Override
163 public Map<String, String> getEventHoverToolTipInfo(ITimeEvent event, long hoverTime) {
164
165 Map<String, String> retMap = new LinkedHashMap<String, String>();
166 if (event instanceof ResourcesEvent) {
167
168 ResourcesEvent resourcesEvent = (ResourcesEvent) event;
169
170 // Check for IRQ or Soft_IRQ type
171 if (resourcesEvent.getType().equals(Type.IRQ) || resourcesEvent.getType().equals(Type.SOFT_IRQ)) {
172
173 // Get CPU of IRQ or SoftIRQ and provide it for the tooltip display
174 int cpu = resourcesEvent.getValue();
175 if (cpu >= 0) {
176 retMap.put(Messages.ResourcesView_attributeCpuName, String.valueOf(cpu));
177 }
178 }
179
180 // Check for type CPU
181 if (resourcesEvent.getType().equals(Type.CPU)) {
182 int status = resourcesEvent.getValue();
183
184 if (status == StateValues.CPU_STATUS_IRQ) {
185 // In IRQ state get the IRQ that caused the interruption
186 ResourcesEntry entry = (ResourcesEntry) event.getEntry();
187 ITmfStateSystem ss = entry.getTrace().getStateSystem(CtfKernelTrace.STATE_ID);
188 int cpu = entry.getId();
189
190 try {
191 List<ITmfStateInterval> fullState = ss.queryFullState(event.getTime());
192 List<Integer> irqQuarks = ss.getQuarks(Attributes.RESOURCES, Attributes.IRQS, "*"); //$NON-NLS-1$
193
194 for (int irqQuark : irqQuarks) {
195 if (fullState.get(irqQuark).getStateValue().unboxInt() == cpu) {
196 ITmfStateInterval value = ss.querySingleState(event.getTime(), irqQuark);
197 if (!value.getStateValue().isNull()) {
198 int irq = Integer.parseInt(ss.getAttributeName(irqQuark));
199 retMap.put(Messages.ResourcesView_attributeIrqName, String.valueOf(irq));
200 }
201 break;
202 }
203 }
204 } catch (AttributeNotFoundException e) {
205 e.printStackTrace();
206 } catch (TimeRangeException e) {
207 e.printStackTrace();
208 } catch (StateValueTypeException e) {
209 e.printStackTrace();
210 } catch (StateSystemDisposedException e) {
211 /* Ignored */
212 }
213 } else if (status == StateValues.CPU_STATUS_SOFTIRQ) {
214 // In SOFT_IRQ state get the SOFT_IRQ that caused the interruption
215 ResourcesEntry entry = (ResourcesEntry) event.getEntry();
216 ITmfStateSystem ss = entry.getTrace().getStateSystem(CtfKernelTrace.STATE_ID);
217 int cpu = entry.getId();
218
219 try {
220 List<ITmfStateInterval> fullState = ss.queryFullState(event.getTime());
221 List<Integer> softIrqQuarks = ss.getQuarks(Attributes.RESOURCES, Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$
222
223 for (int softIrqQuark : softIrqQuarks) {
224 if (fullState.get(softIrqQuark).getStateValue().unboxInt() == cpu) {
225 ITmfStateInterval value = ss.querySingleState(event.getTime(), softIrqQuark);
226 if (!value.getStateValue().isNull()) {
227 int softIrq = Integer.parseInt(ss.getAttributeName(softIrqQuark));
228 retMap.put(Messages.ResourcesView_attributeSoftIrqName, String.valueOf(softIrq));
229 }
230 break;
231 }
232 }
233 } catch (AttributeNotFoundException e) {
234 e.printStackTrace();
235 } catch (TimeRangeException e) {
236 e.printStackTrace();
237 } catch (StateValueTypeException e) {
238 e.printStackTrace();
239 } catch (StateSystemDisposedException e) {
240 /* Ignored */
241 }
242 } else if (status == StateValues.CPU_STATUS_RUN_USERMODE || status == StateValues.CPU_STATUS_RUN_SYSCALL){
243 // In running state get the current tid
244 ResourcesEntry entry = (ResourcesEntry) event.getEntry();
245 ITmfStateSystem ssq = entry.getTrace().getStateSystem(CtfKernelTrace.STATE_ID);
246
247 try {
248 retMap.put(Messages.ResourcesView_attributeHoverTime, Utils.formatTime(hoverTime, TimeFormat.ABSOLUTE, Resolution.NANOSEC));
249 int cpuQuark = entry.getQuark();
250 int currentThreadQuark = ssq.getQuarkRelative(cpuQuark, Attributes.CURRENT_THREAD);
251 ITmfStateInterval interval = ssq.querySingleState(hoverTime, currentThreadQuark);
252 if (!interval.getStateValue().isNull()) {
253 ITmfStateValue value = interval.getStateValue();
254 int currentThreadId = value.unboxInt();
255 retMap.put(Messages.ResourcesView_attributeTidName, Integer.toString(currentThreadId));
256 int execNameQuark = ssq.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThreadId), Attributes.EXEC_NAME);
257 interval = ssq.querySingleState(hoverTime, execNameQuark);
258 if (!interval.getStateValue().isNull()) {
259 value = interval.getStateValue();
260 retMap.put(Messages.ResourcesView_attributeProcessName, value.unboxStr());
261 }
262 if (status == StateValues.CPU_STATUS_RUN_SYSCALL) {
263 int syscallQuark = ssq.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThreadId), Attributes.SYSTEM_CALL);
264 interval = ssq.querySingleState(hoverTime, syscallQuark);
265 if (!interval.getStateValue().isNull()) {
266 value = interval.getStateValue();
267 retMap.put(Messages.ResourcesView_attributeSyscallName, value.unboxStr());
268 }
269 }
270 }
271 } catch (AttributeNotFoundException e) {
272 e.printStackTrace();
273 } catch (TimeRangeException e) {
274 e.printStackTrace();
275 } catch (StateValueTypeException e) {
276 e.printStackTrace();
277 } catch (StateSystemDisposedException e) {
278 /* Ignored */
279 }
280 }
281 }
282 }
283
284 return retMap;
285 }
286
287 @Override
288 public void postDrawEvent(ITimeEvent event, Rectangle bounds, GC gc) {
289 if (bounds.width <= gc.getFontMetrics().getAverageCharWidth()) {
290 return;
291 }
292 if (!(event instanceof ResourcesEvent)) {
293 return;
294 }
295 ResourcesEvent resourcesEvent = (ResourcesEvent) event;
296 if (!resourcesEvent.getType().equals(Type.CPU)) {
297 return;
298 }
299 int status = resourcesEvent.getValue();
300 if (status != StateValues.CPU_STATUS_RUN_USERMODE && status != StateValues.CPU_STATUS_RUN_SYSCALL) {
301 return;
302 }
303 ResourcesEntry entry = (ResourcesEntry) event.getEntry();
304 ITmfStateSystem ss = entry.getTrace().getStateSystem(CtfKernelTrace.STATE_ID);
305 long time = event.getTime();
306 try {
307 while (time < event.getTime() + event.getDuration()) {
308 int cpuQuark = entry.getQuark();
309 int currentThreadQuark = ss.getQuarkRelative(cpuQuark, Attributes.CURRENT_THREAD);
310 ITmfStateInterval tidInterval = ss.querySingleState(time, currentThreadQuark);
311 if (!tidInterval.getStateValue().isNull()) {
312 ITmfStateValue value = tidInterval.getStateValue();
313 int currentThreadId = value.unboxInt();
314 if (status == StateValues.CPU_STATUS_RUN_USERMODE && currentThreadId != fLastThreadId) {
315 int execNameQuark = ss.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThreadId), Attributes.EXEC_NAME);
316 ITmfStateInterval interval = ss.querySingleState(time, execNameQuark);
317 if (!interval.getStateValue().isNull()) {
318 value = interval.getStateValue();
319 gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
320 long startTime = Math.max(tidInterval.getStartTime(), event.getTime());
321 long endTime = Math.min(tidInterval.getEndTime() + 1, event.getTime() + event.getDuration());
322 if (fTimeGraphViewer.getXForTime(endTime) > bounds.x) {
323 int x = Math.max(fTimeGraphViewer.getXForTime(startTime), bounds.x);
324 int width = Math.min(fTimeGraphViewer.getXForTime(endTime), bounds.x + bounds.width) - x;
325 int drawn = Utils.drawText(gc, value.unboxStr(), x + 1, bounds.y - 2, width - 1, true, true);
326 if (drawn > 0) {
327 fLastThreadId = currentThreadId;
328 }
329 }
330 }
331 } else if (status == StateValues.CPU_STATUS_RUN_SYSCALL) {
332 int syscallQuark = ss.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThreadId), Attributes.SYSTEM_CALL);
333 ITmfStateInterval interval = ss.querySingleState(time, syscallQuark);
334 if (!interval.getStateValue().isNull()) {
335 value = interval.getStateValue();
336 gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
337 long startTime = Math.max(tidInterval.getStartTime(), event.getTime());
338 long endTime = Math.min(tidInterval.getEndTime() + 1, event.getTime() + event.getDuration());
339 if (fTimeGraphViewer.getXForTime(endTime) > bounds.x) {
340 int x = Math.max(fTimeGraphViewer.getXForTime(startTime), bounds.x);
341 int width = Math.min(fTimeGraphViewer.getXForTime(endTime), bounds.x + bounds.width) - x;
342 Utils.drawText(gc, value.unboxStr().substring(4), x + 1, bounds.y - 2, width - 1, true, true);
343 }
344 }
345 }
346 }
347 time = tidInterval.getEndTime() + 1;
348 if (time < event.getTime() + event.getDuration()) {
349 int x = fTimeGraphViewer.getXForTime(time);
350 if (x >= bounds.x) {
351 gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_GRAY));
352 gc.drawLine(x, bounds.y + 1, x, bounds.y + bounds.height - 2);
353 }
354 }
355 }
356 } catch (AttributeNotFoundException e) {
357 e.printStackTrace();
358 } catch (TimeRangeException e) {
359 e.printStackTrace();
360 } catch (StateValueTypeException e) {
361 e.printStackTrace();
362 } catch (StateSystemDisposedException e) {
363 /* Ignored */
364 }
365 }
366
367 @Override
368 public void postDrawEntry(ITimeGraphEntry entry, Rectangle bounds, GC gc) {
369 fLastThreadId = -1;
370 }
371 }
This page took 0.040681 seconds and 6 git commands to generate.