os.linux: Rename the "kernelanalysis" package to just "kernel"
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.os.linux.ui / src / org / eclipse / tracecompass / analysis / os / linux / ui / views / resources / ResourcesView.java
CommitLineData
6151d86c 1/*******************************************************************************
263c3747 2 * Copyright (c) 2012, 2016 Ericsson, École Polytechnique de Montréal
6151d86c
PT
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
4999a196 11 * Geneviève Bastien - Move code to provide base classes for time graph views
6151d86c
PT
12 *******************************************************************************/
13
e363eae1 14package org.eclipse.tracecompass.analysis.os.linux.ui.views.resources;
6151d86c
PT
15
16import java.util.ArrayList;
1cf25311 17import java.util.Collections;
9ba941e9 18import java.util.Comparator;
1cf25311 19import java.util.HashMap;
6151d86c 20import java.util.List;
1cf25311 21import java.util.Map;
6151d86c
PT
22
23import org.eclipse.core.runtime.IProgressMonitor;
19ed6598
MK
24import org.eclipse.core.runtime.IStatus;
25import org.eclipse.core.runtime.Status;
8213a0c0 26import org.eclipse.jdt.annotation.NonNull;
d2120fb6 27import org.eclipse.jdt.annotation.Nullable;
0f7a12d3
AM
28import org.eclipse.tracecompass.analysis.os.linux.core.kernel.Attributes;
29import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
e363eae1
AM
30import org.eclipse.tracecompass.analysis.os.linux.ui.views.resources.ResourcesEntry.Type;
31import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Messages;
e894a508
AM
32import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
33import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
e894a508 34import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
2bdf0193
AM
35import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
36import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
8213a0c0 37import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractStateSystemTimeGraphView;
2bdf0193
AM
38import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
39import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
40import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent;
41import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
42import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
6151d86c
PT
43
44/**
45 * Main implementation for the LTTng 2.0 kernel Resource view
46 *
47 * @author Patrick Tasse
48 */
8213a0c0 49public class ResourcesView extends AbstractStateSystemTimeGraphView {
6151d86c
PT
50
51 /** View ID. */
e363eae1 52 public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.views.resources"; //$NON-NLS-1$
6151d86c 53
4999a196 54 private static final String[] FILTER_COLUMN_NAMES = new String[] {
747adf5c 55 Messages.ResourcesView_stateTypeName
4999a196 56 };
6151d86c 57
1cf25311
PT
58 // Timeout between updates in the build thread in ms
59 private static final long BUILD_UPDATE_TIMEOUT = 500;
60
6151d86c
PT
61 // ------------------------------------------------------------------------
62 // Constructors
63 // ------------------------------------------------------------------------
64
65 /**
66 * Default constructor
67 */
68 public ResourcesView() {
747adf5c
PT
69 super(ID, new ResourcesPresentationProvider());
70 setFilterColumns(FILTER_COLUMN_NAMES);
bb447fcb 71 setFilterLabelProvider(new ResourcesFilterLabelProvider());
263c3747 72 setEntryComparator(new ResourcesEntryComparator());
19ed6598 73 setAutoExpandLevel(1);
263c3747
PT
74 }
75
76 private static class ResourcesEntryComparator implements Comparator<ITimeGraphEntry> {
77 @Override
78 public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) {
79 ResourcesEntry entry1 = (ResourcesEntry) o1;
80 ResourcesEntry entry2 = (ResourcesEntry) o2;
81 if (entry1.getType() == Type.NULL && entry2.getType() == Type.NULL) {
82 /* sort trace entries alphabetically */
83 return entry1.getName().compareTo(entry2.getName());
84 }
85 /* sort resource entries by their defined order */
86 return entry1.compareTo(entry2);
87 }
bb447fcb
PT
88 }
89
90 private static class ResourcesFilterLabelProvider extends TreeLabelProvider {
91 @Override
92 public String getColumnText(Object element, int columnIndex) {
93 ResourcesEntry entry = (ResourcesEntry) element;
94 if (columnIndex == 0) {
95 return entry.getName();
96 }
97 return ""; //$NON-NLS-1$
98 }
99
6151d86c
PT
100 }
101
1cf25311
PT
102 // ------------------------------------------------------------------------
103 // Internal
104 // ------------------------------------------------------------------------
105
6151d86c 106 @Override
4999a196
GB
107 protected String getNextText() {
108 return Messages.ResourcesView_nextResourceActionNameText;
6151d86c
PT
109 }
110
6151d86c 111 @Override
4999a196
GB
112 protected String getNextTooltip() {
113 return Messages.ResourcesView_nextResourceActionToolTipText;
fec1ac0b
BH
114 }
115
4999a196
GB
116 @Override
117 protected String getPrevText() {
118 return Messages.ResourcesView_previousResourceActionNameText;
6151d86c
PT
119 }
120
4999a196
GB
121 @Override
122 protected String getPrevTooltip() {
123 return Messages.ResourcesView_previousResourceActionToolTipText;
6151d86c
PT
124 }
125
4999a196 126 @Override
8213a0c0
PT
127 protected void buildEventList(ITmfTrace trace, ITmfTrace parentTrace, final IProgressMonitor monitor) {
128 final ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID);
1cf25311
PT
129 if (ssq == null) {
130 return;
131 }
fec1ac0b 132
1cf25311
PT
133 Map<Integer, ResourcesEntry> entryMap = new HashMap<>();
134 TimeGraphEntry traceEntry = null;
135
136 long startTime = ssq.getStartTime();
137 long start = startTime;
138 setStartTime(Math.min(getStartTime(), startTime));
139 boolean complete = false;
140 while (!complete) {
faa38350
PT
141 if (monitor.isCanceled()) {
142 return;
143 }
1cf25311
PT
144 complete = ssq.waitUntilBuilt(BUILD_UPDATE_TIMEOUT);
145 if (ssq.isCancelled()) {
146 return;
147 }
148 long end = ssq.getCurrentEndTime();
19ed6598
MK
149 if (start == end && !complete) {
150 // when complete execute one last time regardless of end time
1cf25311
PT
151 continue;
152 }
153 long endTime = end + 1;
154 setEndTime(Math.max(getEndTime(), endTime));
155
156 if (traceEntry == null) {
157 traceEntry = new ResourcesEntry(trace, trace.getName(), startTime, endTime, 0);
158 List<TimeGraphEntry> entryList = Collections.singletonList(traceEntry);
8213a0c0 159 addToEntryList(parentTrace, ssq, entryList);
1cf25311
PT
160 } else {
161 traceEntry.updateEndTime(endTime);
162 }
1cf25311 163 List<Integer> cpuQuarks = ssq.getQuarks(Attributes.CPUS, "*"); //$NON-NLS-1$
19ed6598 164 createCpuEntriesWithQuark(trace, ssq, entryMap, traceEntry, startTime, endTime, cpuQuarks);
1cf25311
PT
165 if (parentTrace.equals(getTrace())) {
166 refresh();
faa38350 167 }
8213a0c0
PT
168 final List<? extends ITimeGraphEntry> traceEntryChildren = traceEntry.getChildren();
169 final long resolution = Math.max(1, (endTime - ssq.getStartTime()) / getDisplayWidth());
170 final long qStart = start;
171 final long qEnd = end;
172 queryFullStates(ssq, qStart, qEnd, resolution, monitor, new IQueryHandler() {
173 @Override
174 public void handle(List<List<ITmfStateInterval>> fullStates, List<ITmfStateInterval> prevFullState) {
175 for (ITimeGraphEntry child : traceEntryChildren) {
19ed6598 176 if (!populateEventsRecursively(fullStates, prevFullState, child).isOK()) {
8213a0c0
PT
177 return;
178 }
19ed6598
MK
179 }
180 }
181
182 private IStatus populateEventsRecursively(@NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, ITimeGraphEntry entry) {
183 if (monitor.isCanceled()) {
184 return Status.CANCEL_STATUS;
185 }
186 if (entry instanceof TimeGraphEntry) {
187 TimeGraphEntry timeGraphEntry = (TimeGraphEntry) entry;
188 List<ITimeEvent> eventList = getEventList(timeGraphEntry, ssq, fullStates, prevFullState, monitor);
189 if (eventList != null) {
190 for (ITimeEvent event : eventList) {
191 timeGraphEntry.addEvent(event);
8213a0c0 192 }
a3188982 193 }
1cf25311 194 }
19ed6598
MK
195 for (ITimeGraphEntry child : entry.getChildren()) {
196 IStatus status = populateEventsRecursively(fullStates, prevFullState, child);
197 if (!status.isOK()) {
198 return status;
199 }
200 }
201 return Status.OK_STATUS;
1cf25311 202 }
8213a0c0 203 });
1cf25311
PT
204
205 start = end;
6151d86c 206 }
19ed6598
MK
207
208 }
209
210 private static void createCpuEntriesWithQuark(@NonNull ITmfTrace trace, final ITmfStateSystem ssq, Map<Integer, ResourcesEntry> entryMap, TimeGraphEntry traceEntry, long startTime, long endTime, List<Integer> cpuQuarks) {
211 for (Integer cpuQuark : cpuQuarks) {
212 final @NonNull String cpuName = ssq.getAttributeName(cpuQuark);
213 int cpu = Integer.parseInt(cpuName);
214 ResourcesEntry cpuEntry = entryMap.get(cpuQuark);
215 if (cpuEntry == null) {
216 cpuEntry = new ResourcesEntry(cpuQuark, trace, startTime, endTime, Type.CPU, cpu);
217 entryMap.put(cpuQuark, cpuEntry);
218 traceEntry.addChild(cpuEntry);
219 } else {
220 cpuEntry.updateEndTime(endTime);
221 }
222 List<Integer> irqQuarks = ssq.getQuarks(Attributes.CPUS, cpuName, Attributes.IRQS, "*"); //$NON-NLS-1$
223 createCpuInterruptEntryWithQuark(trace, ssq, entryMap, startTime, endTime, traceEntry, cpuEntry, irqQuarks, Type.IRQ);
224 List<Integer> softIrqQuarks = ssq.getQuarks(Attributes.CPUS, cpuName, Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$
225 createCpuInterruptEntryWithQuark(trace, ssq, entryMap, startTime, endTime, traceEntry, cpuEntry, softIrqQuarks, Type.SOFT_IRQ);
226 }
227 }
228
229 /**
230 * Create and add execution contexts to a cpu entry. Also creates an
231 * aggregate entry in the root trace entry. The execution context is
232 * basically what the cpu is doing in its execution stack. It can be in an
233 * IRQ, Soft IRQ. MCEs, NMIs, Userland and Kernel execution is not yet
234 * supported.
235 *
236 * @param trace
237 * the trace
238 * @param ssq
239 * the state system
240 * @param entryMap
241 * the entry map
242 * @param startTime
243 * the start time in nanoseconds
244 * @param endTime
245 * the end time in nanoseconds
246 * @param traceEntry
247 * the trace timegraph entry
248 * @param cpuEntry
249 * the cpu timegraph entry (the entry under the trace entry
250 * @param childrenQuarks
251 * the quarks to add to cpu entry
252 * @param type
253 * the type of entry being added
254 */
255 private static void createCpuInterruptEntryWithQuark(@NonNull ITmfTrace trace,
256 final ITmfStateSystem ssq, Map<Integer, ResourcesEntry> entryMap,
257 long startTime, long endTime,
258 TimeGraphEntry traceEntry, ResourcesEntry cpuEntry,
259 List<Integer> childrenQuarks, Type type) {
260 for (Integer quark : childrenQuarks) {
261 final @NonNull String resourceName = ssq.getAttributeName(quark);
262 int resourceId = Integer.parseInt(resourceName);
263 ResourcesEntry interruptEntry = entryMap.get(quark);
264 if (interruptEntry == null) {
265 interruptEntry = new ResourcesEntry(quark, trace, startTime, endTime, type, resourceId);
266 entryMap.put(quark, interruptEntry);
267 cpuEntry.addChild(interruptEntry);
268 boolean found = false;
269 for (ITimeGraphEntry rootElem : traceEntry.getChildren()) {
270 if (rootElem instanceof AggregateResourcesEntry) {
271 AggregateResourcesEntry aggregateInterruptEntry = (AggregateResourcesEntry) rootElem;
272 if (aggregateInterruptEntry.getId() == resourceId && aggregateInterruptEntry.getType().equals(type)) {
273 found = true;
274 aggregateInterruptEntry.addContributor(interruptEntry);
ff0b7e58
MK
275 final AggregateResourcesEntry irqCpuEntry = new AggregateResourcesEntry(trace, cpuEntry.getName(), startTime, endTime, type, cpuEntry.getId());
276 irqCpuEntry.addContributor(interruptEntry);
277 aggregateInterruptEntry.addChild(irqCpuEntry);
19ed6598
MK
278 break;
279 }
280 }
281 }
282 if (!found) {
283 AggregateResourcesEntry aggregateInterruptEntry = new AggregateResourcesEntry(trace, startTime, endTime, type, resourceId);
284 aggregateInterruptEntry.addContributor(interruptEntry);
ff0b7e58
MK
285 final AggregateResourcesEntry irqCpuEntry = new AggregateResourcesEntry(trace, cpuEntry.getName(), startTime, endTime, type, cpuEntry.getId());
286 irqCpuEntry.addContributor(interruptEntry);
287 aggregateInterruptEntry.addChild(irqCpuEntry);
19ed6598
MK
288 traceEntry.addChild(aggregateInterruptEntry);
289 }
290 } else {
291 interruptEntry.updateEndTime(endTime);
292 }
293 }
6151d86c
PT
294 }
295
4999a196 296 @Override
8213a0c0
PT
297 protected @Nullable List<ITimeEvent> getEventList(@NonNull TimeGraphEntry entry, ITmfStateSystem ssq,
298 @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
1d46dc38 299 ResourcesEntry resourcesEntry = (ResourcesEntry) entry;
4999a196
GB
300 int quark = resourcesEntry.getQuark();
301
8213a0c0 302 if (resourcesEntry.getType().equals(Type.CPU)) {
19ed6598
MK
303 return createCpuEventsList(entry, ssq, fullStates, prevFullState, monitor, quark);
304 } else if ((resourcesEntry.getType().equals(Type.IRQ) || resourcesEntry.getType().equals(Type.SOFT_IRQ)) && (quark >= 0)) {
305 return createIrqEventsList(entry, fullStates, prevFullState, monitor, quark);
306 }
307
308 return null;
309 }
310
311 private static List<ITimeEvent> createCpuEventsList(TimeGraphEntry entry, ITmfStateSystem ssq, List<List<ITmfStateInterval>> fullStates, List<ITmfStateInterval> prevFullState, IProgressMonitor monitor, int quark) {
312 List<ITimeEvent> eventList;
313 int statusQuark;
314 try {
315 statusQuark = ssq.getQuarkRelative(quark, Attributes.STATUS);
316 } catch (AttributeNotFoundException e) {
317 /*
318 * The sub-attribute "status" is not available. May happen if the
319 * trace does not have sched_switch events enabled.
320 */
321 return null;
322 }
323 eventList = new ArrayList<>(fullStates.size());
324 ITmfStateInterval lastInterval = prevFullState == null || statusQuark >= prevFullState.size() ? null : prevFullState.get(statusQuark);
325 long lastStartTime = lastInterval == null ? -1 : lastInterval.getStartTime();
326 long lastEndTime = lastInterval == null ? -1 : lastInterval.getEndTime() + 1;
327 for (List<ITmfStateInterval> fullState : fullStates) {
328 if (monitor.isCanceled()) {
8213a0c0
PT
329 return null;
330 }
19ed6598
MK
331 if (statusQuark >= fullState.size()) {
332 /* No information on this CPU (yet?), skip it for now */
333 continue;
8213a0c0 334 }
19ed6598
MK
335 ITmfStateInterval statusInterval = fullState.get(statusQuark);
336 int status = statusInterval.getStateValue().unboxInt();
337 long time = statusInterval.getStartTime();
338 long duration = statusInterval.getEndTime() - time + 1;
339 if (time == lastStartTime) {
340 continue;
341 }
342 if (!statusInterval.getStateValue().isNull()) {
343 if (lastEndTime != time && lastEndTime != -1) {
344 eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
6151d86c 345 }
19ed6598
MK
346 eventList.add(new TimeEvent(entry, time, duration, status));
347 } else {
348 eventList.add(new NullTimeEvent(entry, time, duration));
6151d86c 349 }
19ed6598
MK
350 lastStartTime = time;
351 lastEndTime = time + duration;
6151d86c 352 }
19ed6598
MK
353 return eventList;
354 }
8213a0c0 355
19ed6598
MK
356 private static List<ITimeEvent> createIrqEventsList(TimeGraphEntry entry, List<List<ITmfStateInterval>> fullStates, List<ITmfStateInterval> prevFullState, IProgressMonitor monitor, int quark) {
357 List<ITimeEvent> eventList;
358 eventList = new ArrayList<>(fullStates.size());
359 ITmfStateInterval lastInterval = prevFullState == null || quark >= prevFullState.size() ? null : prevFullState.get(quark);
360 long lastStartTime = lastInterval == null ? -1 : lastInterval.getStartTime();
361 long lastEndTime = lastInterval == null ? -1 : lastInterval.getEndTime() + 1;
362 boolean lastIsNull = lastInterval == null ? false : lastInterval.getStateValue().isNull();
363 for (List<ITmfStateInterval> fullState : fullStates) {
364 if (monitor.isCanceled()) {
365 return null;
366 }
367 if (quark >= fullState.size()) {
368 /* No information on this IRQ (yet?), skip it for now */
369 continue;
370 }
371 ITmfStateInterval irqInterval = fullState.get(quark);
372 long time = irqInterval.getStartTime();
373 long duration = irqInterval.getEndTime() - time + 1;
374 if (time == lastStartTime) {
375 continue;
376 }
377 if (!irqInterval.getStateValue().isNull()) {
378 int cpu = irqInterval.getStateValue().unboxInt();
379 eventList.add(new TimeEvent(entry, time, duration, cpu));
380 lastIsNull = false;
381 } else {
382 if (lastEndTime != time && lastIsNull) {
383 /*
384 * This is a special case where we want to show IRQ_ACTIVE
385 * state but we don't know the CPU (it is between two null
386 * samples)
387 */
388 eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime, -1));
389 }
390 eventList.add(new NullTimeEvent(entry, time, duration));
391 lastIsNull = true;
392 }
393 lastStartTime = time;
394 lastEndTime = time + duration;
395 }
6151d86c
PT
396 return eventList;
397 }
398
6151d86c 399}
This page took 0.089569 seconds and 5 git commands to generate.