ss: Replace AttributeNotFoundException with IOOBE for quark parameters
[deliverable/tracecompass.git] / lttng / org.eclipse.tracecompass.lttng2.kernel.ui / src / org / eclipse / tracecompass / internal / lttng2 / kernel / ui / views / vm / vcpuview / VirtualMachineView.java
CommitLineData
b1a7aebb
MG
1/*******************************************************************************
2 * Copyright (c) 2016 É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
10package org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.vm.vcpuview;
11
12import java.util.ArrayList;
13import java.util.Collection;
14import java.util.Collections;
15import java.util.Comparator;
16import java.util.HashMap;
17import java.util.List;
18import java.util.Map;
19
20import org.eclipse.core.runtime.IProgressMonitor;
21import org.eclipse.jdt.annotation.NonNull;
22import org.eclipse.jdt.annotation.Nullable;
0f7a12d3
AM
23import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
24import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelThreadInformationProvider;
b1a7aebb
MG
25import org.eclipse.tracecompass.common.core.NonNullUtils;
26import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.VmAttributes;
27import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.module.VirtualMachineCpuAnalysis;
28import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.trace.VirtualMachineExperiment;
29import org.eclipse.tracecompass.internal.lttng2.kernel.ui.Activator;
30import org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.vm.vcpuview.VirtualMachineCommon.Type;
31import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
32import org.eclipse.tracecompass.statesystem.core.StateSystemUtils;
33import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
34import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
35import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
36import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
37import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
38import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
39import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
40import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
41import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperimentUtils;
42import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractTimeGraphView;
43import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
44import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
45import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent;
46import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
47import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
48
49import com.google.common.collect.Multimap;
50
51/**
52 * Main implementation for the Virtual Machine view
53 *
54 * @author Mohamad Gebai
55 */
56public class VirtualMachineView extends AbstractTimeGraphView {
57
58 /** View ID. */
59 public static final String ID = "org.eclipse.tracecompass.lttng2.analysis.vm.ui.vmview"; //$NON-NLS-1$
60
61 private static final String[] COLUMN_NAMES = new String[] {
62 Messages.VmView_stateTypeName
63 };
64
65 private static final String[] FILTER_COLUMN_NAMES = new String[] {
66 Messages.VmView_stateTypeName
67 };
68
69 // Timeout between updates in the build thread in ms
70 private static final long BUILD_UPDATE_TIMEOUT = 500;
71 private static final int[] DEFAULT_WEIGHT = { 1, 3 };
72
6a492637 73 private Comparator<ITimeGraphEntry> fComparator = VirtualMachineViewEntry.getComparator();
b1a7aebb
MG
74
75 // ------------------------------------------------------------------------
76 // Constructors
77 // ------------------------------------------------------------------------
78
79 /**
80 * Default constructor
81 */
82 public VirtualMachineView() {
83 super(ID, new VirtualMachinePresentationProvider());
84 setFilterColumns(FILTER_COLUMN_NAMES);
85 setTreeColumns(COLUMN_NAMES);
86 setTreeLabelProvider(new VmViewTreeLabelProvider());
87 setWeight(DEFAULT_WEIGHT);
88 setAutoExpandLevel(2);
89 }
90
91 @Override
92 protected @Nullable String getNextText() {
93 return Messages.VmView_nextResourceActionNameText;
94 }
95
96 @Override
97 protected @Nullable String getNextTooltip() {
98 return Messages.VmView_nextResourceActionToolTipText;
99 }
100
101 @Override
102 protected @Nullable String getPrevText() {
103 return Messages.VmView_previousResourceActionNameText;
104 }
105
106 @Override
107 protected @Nullable String getPrevTooltip() {
108 return Messages.VmView_previousResourceActionToolTipText;
109 }
110
111 private static class VmViewTreeLabelProvider extends TreeLabelProvider {
112
113 @Override
114 public String getColumnText(@Nullable Object element, int columnIndex) {
115 if (!(element instanceof VirtualMachineViewEntry)) {
116 return ""; //$NON-NLS-1$
117 }
118 VirtualMachineViewEntry entry = (VirtualMachineViewEntry) element;
119
120 if (COLUMN_NAMES[columnIndex].equals(Messages.VmView_stateTypeName)) {
121 String name = entry.getName();
122 return (name == null) ? "" : name; //$NON-NLS-1$
123 }
124 return ""; //$NON-NLS-1$
125 }
126
127 }
128
129 // ------------------------------------------------------------------------
130 // Internal
131 // ------------------------------------------------------------------------
132
133 @Override
f8f46a52 134 protected void buildEntryList(ITmfTrace trace, ITmfTrace parentTrace, IProgressMonitor monitor) {
b1a7aebb
MG
135 setStartTime(Long.MAX_VALUE);
136 setEndTime(Long.MIN_VALUE);
137
b1a7aebb
MG
138 if (!(parentTrace instanceof VirtualMachineExperiment)) {
139 return;
140 }
141 ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(parentTrace, VirtualMachineCpuAnalysis.ID);
142 if (ssq == null) {
143 return;
144 }
145 VirtualMachineExperiment vmExperiment = (VirtualMachineExperiment) parentTrace;
146 long startTime = ssq.getStartTime();
147
148 ArrayList<VirtualMachineViewEntry> entryList = new ArrayList<>();
149 Map<String, VirtualMachineViewEntry> entryMap = new HashMap<>();
150
151 boolean complete = false;
507e1c50
GB
152 VirtualMachineViewEntry groupEntry = new VirtualMachineViewEntry.VmEntryBuilder(vmExperiment.getName(), startTime, startTime, vmExperiment).build();
153 entryList.add(groupEntry);
154 putEntryList(parentTrace, new ArrayList<TimeGraphEntry>(entryList));
b1a7aebb
MG
155
156 while (!complete) {
157 if (monitor.isCanceled()) {
158 return;
159 }
160 complete = ssq.waitUntilBuilt(BUILD_UPDATE_TIMEOUT);
161 if (ssq.isCancelled()) {
162 return;
163 }
164
165 long endTime = ssq.getCurrentEndTime() + 1;
507e1c50 166 groupEntry.updateEndTime(endTime);
b1a7aebb
MG
167
168 setStartTime(Math.min(getStartTime(), startTime));
169 setEndTime(Math.max(getEndTime(), endTime));
170
171 /*
172 * Create the entries for the VMs in this experiment and their
173 * respective threads
174 */
175 buildEntries(ssq, startTime, endTime, groupEntry, entryMap, vmExperiment);
176
177 if (parentTrace.equals(getTrace())) {
178 refresh();
179 }
180
507e1c50
GB
181 /* Build event lists for each entry */
182 buildEntryEventLists(entryList, ssq, startTime, endTime, monitor);
b1a7aebb
MG
183 }
184 }
185
186 private void buildEntries(ITmfStateSystem ssq, long startTime, long endTime, VirtualMachineViewEntry groupEntry,
187 Map<@NonNull String, @NonNull VirtualMachineViewEntry> entryMap, VirtualMachineExperiment vmExperiment) {
188 try {
189 List<Integer> vmQuarks = ssq.getQuarks(VmAttributes.VIRTUAL_MACHINES, "*"); //$NON-NLS-1$
190 /* For each virtual machine in the analysis */
191 for (Integer vmQuark : vmQuarks) {
192
193 /* Display an entry for the virtual machine */
0e4f957e 194 String vmHostId = ssq.getAttributeName(vmQuark);
b1a7aebb
MG
195 ITmfStateInterval vmNameInterval = StateSystemUtils.queryUntilNonNullValue(ssq, vmQuark, startTime, endTime);
196 String vmName = vmHostId;
197 if (vmNameInterval != null) {
198 vmName = vmNameInterval.getStateValue().unboxStr();
199 }
200
201 VirtualMachineViewEntry vmEntry = entryMap.get(vmHostId);
202 if (vmEntry == null) {
203 vmEntry = new VirtualMachineViewEntry.VmEntryBuilder(vmName, startTime, endTime, vmExperiment).setId(vmHostId).setVmName(vmName).setNumericId(vmQuark).setType(Type.VM).build();
204 vmEntry.sortChildren(fComparator);
205
206 groupEntry.addChild(vmEntry);
207 entryMap.put(vmHostId, vmEntry);
208 } else {
209 vmEntry.updateEndTime(endTime);
210 }
211
212 /* Display an entry for each of its CPUs */
213 for (Integer vCpuQuark : ssq.getSubAttributes(vmQuark, false)) {
214 String vcpuId = ssq.getAttributeName(vCpuQuark);
215 VirtualMachineViewEntry vcpuEntry = entryMap.get(vmHostId + vcpuId);
216 if (vcpuEntry == null) {
217 vcpuEntry = new VirtualMachineViewEntry.VmEntryBuilder(vcpuId, startTime, endTime, vmExperiment).setId(vcpuId).setVmName(vmName).setNumericId(vCpuQuark).setType(Type.VCPU).build();
218
219 vmEntry.addChild(vcpuEntry);
220 entryMap.put(vmHostId + vcpuId, vcpuEntry);
221 } else {
222 vcpuEntry.updateEndTime(endTime);
223 }
224
225 }
226
507e1c50
GB
227 /* Add the entries for the threads */
228 buildThreadEntries(vmEntry, entryMap, startTime, endTime);
b1a7aebb 229 }
b1a7aebb
MG
230 } catch (TimeRangeException | StateValueTypeException e) {
231 Activator.getDefault().logError("VirtualMachineView: error building event list", e); //$NON-NLS-1$
232 }
233 }
234
507e1c50
GB
235 private static void buildThreadEntries(VirtualMachineViewEntry vmEntry, Map<String, VirtualMachineViewEntry> entryMap, long startTime, long endTime) {
236 String vmHostId = vmEntry.getId();
237 VirtualMachineExperiment vmExperiment = vmEntry.getExperiment();
238
239 /*
240 * Get the LTTng Kernel analysis module from the corresponding trace
241 */
242 KernelAnalysisModule kernelModule = TmfExperimentUtils.getAnalysisModuleOfClassForHost(vmExperiment, vmHostId, KernelAnalysisModule.class);
243 if (kernelModule == null) {
244 return;
245 }
246
247 VirtualMachineViewEntry threadEntry = entryMap.get(vmHostId + NonNullUtils.nullToEmptyString(Messages.VmView_threads));
248 if (threadEntry == null) {
249 threadEntry = new VirtualMachineViewEntry.VmEntryBuilder(NonNullUtils.nullToEmptyString(Messages.VmView_threads), startTime, endTime, vmExperiment).build();
250 entryMap.put(vmHostId + NonNullUtils.nullToEmptyString(Messages.VmView_threads), threadEntry);
251 vmEntry.addChild(threadEntry);
252 } else {
253 threadEntry.updateEndTime(endTime);
254 }
255
256 String vmName = vmEntry.getVmName();
257 if (vmName == null) {
258 return;
259 }
260
261 /*
262 * Display an entry for each thread.
263 *
264 * For each interval that is in a running status, intersect with the
265 * status of the virtual CPU it is currently running on
266 */
267 Collection<Integer> threadIds = KernelThreadInformationProvider.getThreadIds(kernelModule);
268 for (Integer threadId : threadIds) {
269 if (threadId == -1) {
270 continue;
271 }
272 VirtualMachineViewEntry oneThreadEntry = entryMap.get(vmHostId + ':' + threadId);
273 if (oneThreadEntry != null) {
274 oneThreadEntry.updateEndTime(endTime);
275 continue;
276 }
277 /*
278 * FIXME: Only add threads that are active during the trace
279 */
280 String threadName = KernelThreadInformationProvider.getExecutableName(kernelModule, threadId);
0e4f957e 281 String tidString = threadId.toString();
507e1c50
GB
282 threadName = (threadName != null) ? tidString + ':' + ' ' + threadName : tidString;
283 oneThreadEntry = new VirtualMachineViewEntry.VmEntryBuilder(threadName, startTime, endTime, vmExperiment).setId(threadName).setVmName(vmName).setNumericId(threadId).setType(Type.THREAD).build();
284
285 threadEntry.addChild(oneThreadEntry);
286 entryMap.put(vmHostId + ':' + threadId, oneThreadEntry);
287 }
288
289 }
290
00c15db6 291 private void buildEntryEventLists(List<@NonNull VirtualMachineViewEntry> entryList, ITmfStateSystem ssq, long startTime, long endTime, IProgressMonitor monitor) {
507e1c50
GB
292 for (VirtualMachineViewEntry entry : entryList) {
293 if (monitor.isCanceled()) {
294 return;
295 }
296 buildEntryEventList(entry, ssq, startTime, endTime, monitor);
297 }
298 }
299
b1a7aebb
MG
300 private void buildEntryEventList(TimeGraphEntry entry, ITmfStateSystem ssq, long start, long end, IProgressMonitor monitor) {
301 if (start < entry.getEndTime() && end > entry.getStartTime()) {
302
303 long startTime = Math.max(start, entry.getStartTime());
304 long endTime = Math.min(end + 1, entry.getEndTime());
305 long resolution = Math.max(1, (end - ssq.getStartTime()) / getDisplayWidth());
306 List<ITimeEvent> eventList = getEventList(entry, startTime, endTime, resolution, monitor);
307 entry.setEventList(eventList);
308 redraw();
f8f46a52 309 for (TimeGraphEntry child : entry.getChildren()) {
b1a7aebb
MG
310 if (monitor.isCanceled()) {
311 return;
312 }
f8f46a52 313 buildEntryEventList(child, ssq, start, end, monitor);
b1a7aebb
MG
314 }
315 }
316 }
317
318 @Override
319 protected @Nullable List<ITimeEvent> getEventList(TimeGraphEntry entry,
320 long startTime, long endTime, long resolution,
321 IProgressMonitor monitor) {
322 if (!(entry instanceof VirtualMachineViewEntry)) {
323 return null;
324 }
325 if (monitor.isCanceled()) {
326 return null;
327 }
328
329 VirtualMachineViewEntry vmEntry = (VirtualMachineViewEntry) entry;
330
331 switch (vmEntry.getType()) {
332 case THREAD: {
507e1c50 333 return getThreadEventList(vmEntry, endTime, monitor);
b1a7aebb
MG
334 }
335 case VCPU: {
507e1c50 336 return getVcpuEventList(vmEntry, startTime, endTime, resolution, monitor);
b1a7aebb
MG
337 }
338 case VM: {
339 VirtualMachineExperiment experiment = vmEntry.getExperiment();
507e1c50 340 VirtualMachineCpuAnalysis vmAnalysis = TmfTraceUtils.getAnalysisModuleOfClass(experiment, VirtualMachineCpuAnalysis.class, VirtualMachineCpuAnalysis.ID);
b1a7aebb
MG
341 if (vmAnalysis == null) {
342 break;
343 }
344 Multimap<Integer, ITmfStateInterval> updatedThreadIntervals = vmAnalysis.getUpdatedThreadIntervals(vmEntry.getNumericId(), startTime, endTime, resolution, monitor);
345 vmEntry.setThreadIntervals(updatedThreadIntervals);
346 }
347 break;
348 case NULL:
349 /* These entry types are not used in this view */
350 break;
351 default:
352 break;
353 }
354
355 return null;
356 }
357
507e1c50 358 private static @Nullable List<@NonNull ITimeEvent> getVcpuEventList(VirtualMachineViewEntry vmEntry, long startTime, long endTime, long resolution, IProgressMonitor monitor) {
b1a7aebb
MG
359 List<ITimeEvent> eventList = null;
360 try {
361 int quark = vmEntry.getNumericId();
362
363 ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(vmEntry.getExperiment(), VirtualMachineCpuAnalysis.ID);
364 if (ssq == null) {
365 return Collections.EMPTY_LIST;
366 }
367 final long realStart = Math.max(startTime, ssq.getStartTime());
368 final long realEnd = Math.min(endTime, ssq.getCurrentEndTime() + 1);
369 if (realEnd <= realStart) {
370 return Collections.EMPTY_LIST;
371 }
372 quark = ssq.getQuarkRelative(quark, VmAttributes.STATUS);
373 List<ITmfStateInterval> statusIntervals = StateSystemUtils.queryHistoryRange(ssq, quark, realStart, realEnd - 1, resolution, monitor);
b1a7aebb 374
507e1c50 375 eventList = parseIntervalsForEvents(vmEntry, statusIntervals, endTime, monitor);
b1a7aebb
MG
376 } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
377 Activator.getDefault().logError("Error getting event list", e); //$NON-NLS-1$
378 } catch (StateSystemDisposedException e) {
379 /* Ignored */
380 }
381 return eventList;
382 }
383
507e1c50 384 private static @Nullable List<@NonNull ITimeEvent> getThreadEventList(VirtualMachineViewEntry vmEntry, long endTime, IProgressMonitor monitor) {
b1a7aebb 385 List<ITimeEvent> eventList = null;
507e1c50
GB
386 Collection<ITmfStateInterval> threadIntervals = getThreadIntervalsForEntry(vmEntry);
387
388 if (threadIntervals != null) {
389 /*
390 * FIXME: I think the key for the alpha bug when alpha overlaps
391 * multiple events is around here
392 *
393 * Hint by Patrick: "The problem is that the thread intervals
394 * are sorted by start time, and drawn in that order.
395 *
396 * Given the intervals: Blue [0,10] Alpha [5,15] Red [10,20]
397 *
398 * Blue is drawn, then Alpha makes DarkBlue from [5,10] and
399 * DarkBackground from [10,15], then Red is drawn over [10,20],
400 * overwriting the DarkBackground. There is no DarkRed.
401 *
402 * For this to work you would have to draw all real states
403 * first, then all alpha states second.
404 *
405 * I think this would also have the side-effect that the find
406 * item used for tool tips would always find the real event and
407 * never the alpha event. This might be what we want. Right now
408 * the tool tip has State: (multiple).
409 *
410 * But using the Next Event button, we would skip to the next
411 * real event and not at the preemption event. Maybe not what we
412 * want.
413 *
414 * Maybe what we need is separate thread interval events:
415 *
416 * Blue [0,5] Preempted Blue [5,10] Preempted Red [10,15] Red
417 * [15,20]...
418 *
419 * The preempted events would have the real state value, but
420 * with a flag for alpha to be used in the postDrawEvent."
421 */
422 eventList = parseIntervalsForEvents(vmEntry, threadIntervals, endTime, monitor);
423 }
424 return eventList;
425 }
426
427 private static @Nullable List<@NonNull ITimeEvent> parseIntervalsForEvents(VirtualMachineViewEntry vmEntry, Collection<@NonNull ITmfStateInterval> intervals, long endTime, IProgressMonitor monitor) {
428 List<ITimeEvent> eventList = new ArrayList<>(intervals.size());
429 long lastEndTime = -1;
430 for (ITmfStateInterval interval : intervals) {
431 if (monitor.isCanceled()) {
432 return null;
433 }
434
435 long time = interval.getStartTime();
436 long duration = interval.getEndTime() - time + 1;
437 if (!interval.getStateValue().isNull()) {
438 int status = interval.getStateValue().unboxInt();
439 if (lastEndTime != time && lastEndTime != -1) {
440 eventList.add(new TimeEvent(vmEntry, lastEndTime, time - lastEndTime));
441 }
442 eventList.add(new TimeEvent(vmEntry, time, duration, status));
443 } else if (lastEndTime == -1 || time + duration >= endTime) {
444 /* add null event if it intersects the start or end time */
445 eventList.add(new NullTimeEvent(vmEntry, time, duration));
446 }
447 lastEndTime = time + duration;
448 }
449
450 return eventList;
451 }
452
453 private static @Nullable Collection<@NonNull ITmfStateInterval> getThreadIntervalsForEntry(VirtualMachineViewEntry vmEntry) {
454 Collection<ITmfStateInterval> threadIntervals = null;
455
b1a7aebb 456 /*
507e1c50
GB
457 * The parent VM entry will contain the thread intervals for all
458 * threads. Just take the list from there
b1a7aebb 459 */
f8f46a52 460 TimeGraphEntry parent = vmEntry.getParent();
b1a7aebb
MG
461 while (threadIntervals == null && parent != null) {
462 if (parent instanceof VirtualMachineViewEntry) {
463 threadIntervals = ((VirtualMachineViewEntry) parent).getThreadIntervals(vmEntry.getNumericId());
464 }
f8f46a52 465 parent = parent.getParent();
b1a7aebb 466 }
507e1c50 467 return threadIntervals;
b1a7aebb
MG
468 }
469
470 @Override
471 protected Iterable<ITmfTrace> getTracesToBuild(@Nullable ITmfTrace trace) {
472 if (trace == null) {
0e4f957e 473 return Collections.EMPTY_SET;
b1a7aebb 474 }
0e4f957e 475 return Collections.singleton(trace);
b1a7aebb
MG
476 }
477
478}
This page took 0.048006 seconds and 5 git commands to generate.