LTTng: Add developer documentation for virtual machine analysis
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.os.linux.ui / src / org / eclipse / tracecompass / analysis / os / linux / ui / views / resources / ResourcesView.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 views
12 *******************************************************************************/
13
14 package org.eclipse.tracecompass.analysis.os.linux.ui.views.resources;
15
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.Comparator;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22
23 import org.eclipse.core.runtime.IProgressMonitor;
24 import org.eclipse.jdt.annotation.NonNull;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.Attributes;
27 import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.KernelAnalysisModule;
28 import org.eclipse.tracecompass.analysis.os.linux.ui.views.resources.ResourcesEntry.Type;
29 import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Messages;
30 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
31 import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
32 import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
33 import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
34 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
35 import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractStateSystemTimeGraphView;
36 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
37 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
38 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent;
39 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
40 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
41
42 /**
43 * Main implementation for the LTTng 2.0 kernel Resource view
44 *
45 * @author Patrick Tasse
46 */
47 public class ResourcesView extends AbstractStateSystemTimeGraphView {
48
49 /** View ID. */
50 public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.views.resources"; //$NON-NLS-1$
51
52 private static final String[] FILTER_COLUMN_NAMES = new String[] {
53 Messages.ResourcesView_stateTypeName
54 };
55
56 // Timeout between updates in the build thread in ms
57 private static final long BUILD_UPDATE_TIMEOUT = 500;
58
59 // ------------------------------------------------------------------------
60 // Constructors
61 // ------------------------------------------------------------------------
62
63 /**
64 * Default constructor
65 */
66 public ResourcesView() {
67 super(ID, new ResourcesPresentationProvider());
68 setFilterColumns(FILTER_COLUMN_NAMES);
69 setFilterLabelProvider(new ResourcesFilterLabelProvider());
70 }
71
72 private static class ResourcesFilterLabelProvider extends TreeLabelProvider {
73 @Override
74 public String getColumnText(Object element, int columnIndex) {
75 ResourcesEntry entry = (ResourcesEntry) element;
76 if (columnIndex == 0) {
77 return entry.getName();
78 }
79 return ""; //$NON-NLS-1$
80 }
81
82 }
83
84 // ------------------------------------------------------------------------
85 // Internal
86 // ------------------------------------------------------------------------
87
88 @Override
89 protected String getNextText() {
90 return Messages.ResourcesView_nextResourceActionNameText;
91 }
92
93 @Override
94 protected String getNextTooltip() {
95 return Messages.ResourcesView_nextResourceActionToolTipText;
96 }
97
98 @Override
99 protected String getPrevText() {
100 return Messages.ResourcesView_previousResourceActionNameText;
101 }
102
103 @Override
104 protected String getPrevTooltip() {
105 return Messages.ResourcesView_previousResourceActionToolTipText;
106 }
107
108 @Override
109 protected void buildEventList(ITmfTrace trace, ITmfTrace parentTrace, final IProgressMonitor monitor) {
110 final ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID);
111 if (ssq == null) {
112 return;
113 }
114 Comparator<ITimeGraphEntry> comparator = new Comparator<ITimeGraphEntry>() {
115 @Override
116 public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) {
117 return ((ResourcesEntry) o1).compareTo(o2);
118 }
119 };
120
121 Map<Integer, ResourcesEntry> entryMap = new HashMap<>();
122 TimeGraphEntry traceEntry = null;
123
124 long startTime = ssq.getStartTime();
125 long start = startTime;
126 setStartTime(Math.min(getStartTime(), startTime));
127 boolean complete = false;
128 while (!complete) {
129 if (monitor.isCanceled()) {
130 return;
131 }
132 complete = ssq.waitUntilBuilt(BUILD_UPDATE_TIMEOUT);
133 if (ssq.isCancelled()) {
134 return;
135 }
136 long end = ssq.getCurrentEndTime();
137 if (start == end && !complete) { // when complete execute one last time regardless of end time
138 continue;
139 }
140 long endTime = end + 1;
141 setEndTime(Math.max(getEndTime(), endTime));
142
143 if (traceEntry == null) {
144 traceEntry = new ResourcesEntry(trace, trace.getName(), startTime, endTime, 0);
145 traceEntry.sortChildren(comparator);
146 List<TimeGraphEntry> entryList = Collections.singletonList(traceEntry);
147 addToEntryList(parentTrace, ssq, entryList);
148 } else {
149 traceEntry.updateEndTime(endTime);
150 }
151
152 List<Integer> cpuQuarks = ssq.getQuarks(Attributes.CPUS, "*"); //$NON-NLS-1$
153 for (Integer cpuQuark : cpuQuarks) {
154 int cpu = Integer.parseInt(ssq.getAttributeName(cpuQuark));
155 ResourcesEntry entry = entryMap.get(cpuQuark);
156 if (entry == null) {
157 entry = new ResourcesEntry(cpuQuark, trace, startTime, endTime, Type.CPU, cpu);
158 entryMap.put(cpuQuark, entry);
159 traceEntry.addChild(entry);
160 } else {
161 entry.updateEndTime(endTime);
162 }
163 }
164 List<Integer> irqQuarks = ssq.getQuarks(Attributes.RESOURCES, Attributes.IRQS, "*"); //$NON-NLS-1$
165 for (Integer irqQuark : irqQuarks) {
166 int irq = Integer.parseInt(ssq.getAttributeName(irqQuark));
167 ResourcesEntry entry = entryMap.get(irqQuark);
168 if (entry == null) {
169 entry = new ResourcesEntry(irqQuark, trace, startTime, endTime, Type.IRQ, irq);
170 entryMap.put(irqQuark, entry);
171 traceEntry.addChild(entry);
172 } else {
173 entry.updateEndTime(endTime);
174 }
175 }
176 List<Integer> softIrqQuarks = ssq.getQuarks(Attributes.RESOURCES, Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$
177 for (Integer softIrqQuark : softIrqQuarks) {
178 int softIrq = Integer.parseInt(ssq.getAttributeName(softIrqQuark));
179 ResourcesEntry entry = entryMap.get(softIrqQuark);
180 if (entry == null) {
181 entry = new ResourcesEntry(softIrqQuark, trace, startTime, endTime, Type.SOFT_IRQ, softIrq);
182 entryMap.put(softIrqQuark, entry);
183 traceEntry.addChild(entry);
184 } else {
185 entry.updateEndTime(endTime);
186 }
187 }
188
189 if (parentTrace.equals(getTrace())) {
190 refresh();
191 }
192 final List<? extends ITimeGraphEntry> traceEntryChildren = traceEntry.getChildren();
193 final long resolution = Math.max(1, (endTime - ssq.getStartTime()) / getDisplayWidth());
194 final long qStart = start;
195 final long qEnd = end;
196 queryFullStates(ssq, qStart, qEnd, resolution, monitor, new IQueryHandler() {
197 @Override
198 public void handle(List<List<ITmfStateInterval>> fullStates, List<ITmfStateInterval> prevFullState) {
199 for (ITimeGraphEntry child : traceEntryChildren) {
200 if (monitor.isCanceled()) {
201 return;
202 }
203 if (child instanceof TimeGraphEntry) {
204 TimeGraphEntry entry = (TimeGraphEntry) child;
205 List<ITimeEvent> eventList = getEventList(entry, ssq, fullStates, prevFullState, monitor);
206 if (eventList != null) {
207 for (ITimeEvent event : eventList) {
208 entry.addEvent(event);
209 }
210 }
211 }
212 }
213 }
214 });
215
216 start = end;
217 }
218 }
219
220 @Override
221 protected @Nullable List<ITimeEvent> getEventList(@NonNull TimeGraphEntry entry, ITmfStateSystem ssq,
222 @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
223 ResourcesEntry resourcesEntry = (ResourcesEntry) entry;
224 List<ITimeEvent> eventList = null;
225 int quark = resourcesEntry.getQuark();
226
227 if (resourcesEntry.getType().equals(Type.CPU)) {
228 int statusQuark;
229 try {
230 statusQuark = ssq.getQuarkRelative(quark, Attributes.STATUS);
231 } catch (AttributeNotFoundException e) {
232 /*
233 * The sub-attribute "status" is not available. May happen
234 * if the trace does not have sched_switch events enabled.
235 */
236 return null;
237 }
238 eventList = new ArrayList<>(fullStates.size());
239 ITmfStateInterval lastInterval = prevFullState == null || statusQuark >= prevFullState.size() ? null : prevFullState.get(statusQuark);
240 long lastStartTime = lastInterval == null ? -1 : lastInterval.getStartTime();
241 long lastEndTime = lastInterval == null ? -1 : lastInterval.getEndTime() + 1;
242 for (List<ITmfStateInterval> fullState : fullStates) {
243 if (monitor.isCanceled()) {
244 return null;
245 }
246 if (statusQuark >= fullState.size()) {
247 /* No information on this CPU (yet?), skip it for now */
248 continue;
249 }
250 ITmfStateInterval statusInterval = fullState.get(statusQuark);
251 int status = statusInterval.getStateValue().unboxInt();
252 long time = statusInterval.getStartTime();
253 long duration = statusInterval.getEndTime() - time + 1;
254 if (time == lastStartTime) {
255 continue;
256 }
257 if (!statusInterval.getStateValue().isNull()) {
258 if (lastEndTime != time && lastEndTime != -1) {
259 eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
260 }
261 eventList.add(new TimeEvent(entry, time, duration, status));
262 } else {
263 eventList.add(new NullTimeEvent(entry, time, duration));
264 }
265 lastStartTime = time;
266 lastEndTime = time + duration;
267 }
268 } else if (resourcesEntry.getType().equals(Type.IRQ) || resourcesEntry.getType().equals(Type.SOFT_IRQ)) {
269 eventList = new ArrayList<>(fullStates.size());
270 ITmfStateInterval lastInterval = prevFullState == null || quark >= prevFullState.size() ? null : prevFullState.get(quark);
271 long lastStartTime = lastInterval == null ? -1 : lastInterval.getStartTime();
272 long lastEndTime = lastInterval == null ? -1 : lastInterval.getEndTime() + 1;
273 boolean lastIsNull = lastInterval == null ? false : lastInterval.getStateValue().isNull();
274 for (List<ITmfStateInterval> fullState : fullStates) {
275 if (monitor.isCanceled()) {
276 return null;
277 }
278 if (quark >= fullState.size()) {
279 /* No information on this IRQ (yet?), skip it for now */
280 continue;
281 }
282 ITmfStateInterval irqInterval = fullState.get(quark);
283 long time = irqInterval.getStartTime();
284 long duration = irqInterval.getEndTime() - time + 1;
285 if (time == lastStartTime) {
286 continue;
287 }
288 if (!irqInterval.getStateValue().isNull()) {
289 int cpu = irqInterval.getStateValue().unboxInt();
290 eventList.add(new TimeEvent(entry, time, duration, cpu));
291 lastIsNull = false;
292 } else {
293 if (lastEndTime != time && lastIsNull) {
294 /* This is a special case where we want to show IRQ_ACTIVE state but we don't know the CPU (it is between two null samples) */
295 eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime, -1));
296 }
297 eventList.add(new NullTimeEvent(entry, time, duration));
298 lastIsNull = true;
299 }
300 lastStartTime = time;
301 lastEndTime = time + duration;
302 }
303 }
304
305 return eventList;
306 }
307
308 }
This page took 0.038471 seconds and 5 git commands to generate.