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