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