a25a8ad48a0c59a7727743a0f00f69a481d7121f
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.os.linux.ui / src / org / eclipse / tracecompass / internal / 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.internal.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.KernelAnalysisModule;
26 import org.eclipse.tracecompass.analysis.os.linux.core.kernel.StateValues;
27 import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
28 import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
29 import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes;
30 import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Activator;
31 import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Messages;
32 import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources.ResourcesEntry.Type;
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 ITmfStateInterval value = fullState.get(irqQuark);
196 if (!value.getStateValue().isNull()) {
197 String irq = ss.getAttributeName(irqQuark);
198 retMap.put(Messages.ResourcesView_attributeIrqName, irq);
199 break;
200 }
201 }
202 } catch (TimeRangeException | StateValueTypeException e) {
203 Activator.getDefault().logError("Error in ResourcesPresentationProvider", e); //$NON-NLS-1$
204 } catch (StateSystemDisposedException e) {
205 /* Ignored */
206 }
207 } else if (status == StateValues.CPU_STATUS_SOFTIRQ) {
208 // In SOFT_IRQ state get the SOFT_IRQ that caused the interruption
209 int cpu = entry.getId();
210
211 try {
212 List<ITmfStateInterval> fullState = ss.queryFullState(event.getTime());
213 List<Integer> softIrqQuarks = ss.getQuarks(Attributes.CPUS, Integer.toString(cpu), Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$
214
215 for (int softIrqQuark : softIrqQuarks) {
216 ITmfStateInterval value = fullState.get(softIrqQuark);
217 if (!value.getStateValue().isNull()) {
218 String softIrq = ss.getAttributeName(softIrqQuark);
219 retMap.put(Messages.ResourcesView_attributeSoftIrqName, softIrq);
220 break;
221 }
222 }
223 } catch (TimeRangeException | StateValueTypeException e) {
224 Activator.getDefault().logError("Error in ResourcesPresentationProvider", e); //$NON-NLS-1$
225 } catch (StateSystemDisposedException e) {
226 /* Ignored */
227 }
228 } else if (status == StateValues.CPU_STATUS_RUN_USERMODE || status == StateValues.CPU_STATUS_RUN_SYSCALL) {
229 // In running state get the current tid
230
231 try {
232 retMap.put(Messages.ResourcesView_attributeHoverTime, Utils.formatTime(hoverTime, TimeFormat.CALENDAR, Resolution.NANOSEC));
233 int cpuQuark = entry.getQuark();
234 int currentThreadQuark = ss.getQuarkRelative(cpuQuark, Attributes.CURRENT_THREAD);
235 ITmfStateInterval interval = ss.querySingleState(hoverTime, currentThreadQuark);
236 if (!interval.getStateValue().isNull()) {
237 ITmfStateValue value = interval.getStateValue();
238 int currentThreadId = value.unboxInt();
239 retMap.put(Messages.ResourcesView_attributeTidName, Integer.toString(currentThreadId));
240 int execNameQuark = ss.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThreadId), Attributes.EXEC_NAME);
241 interval = ss.querySingleState(hoverTime, execNameQuark);
242 if (!interval.getStateValue().isNull()) {
243 value = interval.getStateValue();
244 retMap.put(Messages.ResourcesView_attributeProcessName, value.unboxStr());
245 }
246 if (status == StateValues.CPU_STATUS_RUN_SYSCALL) {
247 int syscallQuark = ss.optQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThreadId), Attributes.SYSTEM_CALL);
248 if (syscallQuark == ITmfStateSystem.INVALID_ATTRIBUTE) {
249 return retMap;
250 }
251 interval = ss.querySingleState(hoverTime, syscallQuark);
252 if (!interval.getStateValue().isNull()) {
253 value = interval.getStateValue();
254 retMap.put(Messages.ResourcesView_attributeSyscallName, value.unboxStr());
255 }
256 }
257 }
258 } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
259 Activator.getDefault().logError("Error in ResourcesPresentationProvider", e); //$NON-NLS-1$
260 } catch (StateSystemDisposedException e) {
261 /* Ignored */
262 }
263 }
264 }
265 }
266 }
267
268 return retMap;
269 }
270
271 @Override
272 public void postDrawEvent(ITimeEvent event, Rectangle bounds, GC gc) {
273 if (fColorGray == null) {
274 fColorGray = gc.getDevice().getSystemColor(SWT.COLOR_GRAY);
275 }
276 if (fColorWhite == null) {
277 fColorWhite = gc.getDevice().getSystemColor(SWT.COLOR_WHITE);
278 }
279 if (fAverageCharWidth == null) {
280 fAverageCharWidth = gc.getFontMetrics().getAverageCharWidth();
281 }
282
283 ITmfTimeGraphDrawingHelper drawingHelper = getDrawingHelper();
284 if (bounds.width <= fAverageCharWidth) {
285 return;
286 }
287
288 if (!(event instanceof TimeEvent)) {
289 return;
290 }
291 TimeEvent tcEvent = (TimeEvent) event;
292 if (!tcEvent.hasValue()) {
293 return;
294 }
295
296 ResourcesEntry entry = (ResourcesEntry) event.getEntry();
297 if (!entry.getType().equals(Type.CPU)) {
298 return;
299 }
300
301 int status = tcEvent.getValue();
302 if (status != StateValues.CPU_STATUS_RUN_USERMODE && status != StateValues.CPU_STATUS_RUN_SYSCALL) {
303 return;
304 }
305
306 ITmfStateSystem ss = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), KernelAnalysisModule.ID);
307 if (ss == null) {
308 return;
309 }
310 long time = event.getTime();
311 try {
312 while (time < event.getTime() + event.getDuration()) {
313 int cpuQuark = entry.getQuark();
314 int currentThreadQuark = ss.getQuarkRelative(cpuQuark, Attributes.CURRENT_THREAD);
315 ITmfStateInterval tidInterval = ss.querySingleState(time, currentThreadQuark);
316 long startTime = Math.max(tidInterval.getStartTime(), event.getTime());
317 int x = Math.max(drawingHelper.getXForTime(startTime), bounds.x);
318 if (x >= bounds.x + bounds.width) {
319 break;
320 }
321 if (!tidInterval.getStateValue().isNull()) {
322 ITmfStateValue value = tidInterval.getStateValue();
323 int currentThreadId = value.unboxInt();
324 long endTime = Math.min(tidInterval.getEndTime() + 1, event.getTime() + event.getDuration());
325 int xForEndTime = drawingHelper.getXForTime(endTime);
326 if (xForEndTime > bounds.x) {
327 int width = Math.min(xForEndTime, bounds.x + bounds.width) - x - 1;
328 if (width > 0) {
329 String attribute = null;
330 int beginIndex = 0;
331 if (status == StateValues.CPU_STATUS_RUN_USERMODE && currentThreadId != fLastThreadId) {
332 attribute = Attributes.EXEC_NAME;
333 } else if (status == StateValues.CPU_STATUS_RUN_SYSCALL) {
334 attribute = Attributes.SYSTEM_CALL;
335 /*
336 * Remove the "sys_" or "syscall_entry_" or similar from what we
337 * draw in the rectangle. This depends on the trace's event layout.
338 */
339 ITmfTrace trace = entry.getTrace();
340 if (trace instanceof IKernelTrace) {
341 IKernelAnalysisEventLayout layout = ((IKernelTrace) trace).getKernelEventLayout();
342 beginIndex = layout.eventSyscallEntryPrefix().length();
343 }
344 }
345 if (attribute != null) {
346 int quark = ss.optQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThreadId), attribute);
347 if (quark == ITmfStateSystem.INVALID_ATTRIBUTE) {
348 return;
349 }
350 ITmfStateInterval interval = ss.querySingleState(time, quark);
351 if (!interval.getStateValue().isNull()) {
352 value = interval.getStateValue();
353 gc.setForeground(fColorWhite);
354 int drawn = Utils.drawText(gc, value.unboxStr().substring(beginIndex), x + 1, bounds.y, width, bounds.height, true, true);
355 if (drawn > 0 && status == StateValues.CPU_STATUS_RUN_USERMODE) {
356 fLastThreadId = currentThreadId;
357 }
358 }
359 }
360 if (xForEndTime < bounds.x + bounds.width) {
361 gc.setForeground(fColorGray);
362 gc.drawLine(xForEndTime, bounds.y + 1, xForEndTime, bounds.y + bounds.height - 2);
363 }
364 }
365 }
366 }
367 // make sure next time is at least at the next pixel
368 time = Math.max(tidInterval.getEndTime() + 1, drawingHelper.getTimeAtX(x + 1));
369 }
370 } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
371 Activator.getDefault().logError("Error in ResourcesPresentationProvider", e); //$NON-NLS-1$
372 } catch (StateSystemDisposedException e) {
373 /* Ignored */
374 }
375 }
376
377 @Override
378 public void postDrawEntry(ITimeGraphEntry entry, Rectangle bounds, GC gc) {
379 fLastThreadId = -1;
380 }
381 }
This page took 0.038661 seconds and 4 git commands to generate.