LTTng: Add a virtual CPU view for the virtual machine analysis
authorMohamad Gebai <mohamad.gebai@polymtl.ca>
Thu, 4 Dec 2014 02:52:33 +0000 (21:52 -0500)
committerGenevieve Bastien <gbastien+lttng@versatic.net>
Thu, 14 Jan 2016 22:26:05 +0000 (17:26 -0500)
This view shows for each guest the status of its virtual CPUs (running or
preempted) as well as a modified view of the threads running on them to
highlight when it was thought to be running, but was actually preempted on the
host.

Change-Id: Id260abc6d43e868ba261714de64c5530596de7ff
Signed-off-by: Mohamad Gebai <mohamad.gebai@polymtl.ca>
Signed-off-by: Geneviève Bastien <gbastien+lttng@versatic.net>
Reviewed-on: https://git.eclipse.org/r/37602
Reviewed-by: Hudson CI
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
12 files changed:
lttng/org.eclipse.tracecompass.lttng2.kernel.core/plugin.xml
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/module/VirtualMachineCpuAnalysis.java
lttng/org.eclipse.tracecompass.lttng2.kernel.ui/META-INF/MANIFEST.MF
lttng/org.eclipse.tracecompass.lttng2.kernel.ui/plugin.properties
lttng/org.eclipse.tracecompass.lttng2.kernel.ui/plugin.xml
lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/Messages.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/VirtualMachineCommon.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/VirtualMachinePresentationProvider.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/VirtualMachineView.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/VirtualMachineViewEntry.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/messages.properties [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/package-info.java [new file with mode: 0644]

index f62c6c77d456a5e6f228838321d0a748acf12946..b9d1b3ef84217f6d1018a60087212bad057b59ae 100644 (file)
@@ -22,7 +22,7 @@
       <module
             analysis_module="org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.module.VirtualMachineCpuAnalysis"
             automatic="false"
-            id="lttng2.analysis.vm.core.VirtualMachineAnalysisModule"
+            id="org.eclipse.tracecompass.lttng2.analysis.vm.core.VirtualMachineAnalysisModule"
             name="Virtual Machine Analysis">
             <tracetype
                   applies="true"
index 617ac827f1b6db127ae20633d899720e633c1091..1289356064462f360fab843d83adfcbe8bf75a4c 100644 (file)
@@ -57,6 +57,9 @@ import com.google.common.collect.TreeMultimap;
  */
 public class VirtualMachineCpuAnalysis extends TmfStateSystemAnalysisModule {
 
+    /** The ID of this analysis module */
+    public static final String ID = "org.eclipse.tracecompass.lttng2.analysis.vm.core.VirtualMachineAnalysisModule"; //$NON-NLS-1$
+
     // TODO: Update with event layout when requirements are back */
     static final Set<String> REQUIRED_EVENTS = NonNullUtils.checkNotNull(ImmutableSet.of(
             // LttngStrings.SCHED_SWITCH
index ea5ffffb38fc08bdbc5dd7a01abf9062dd1a073e..8dfb2e01d4f2f75b05eecd24b10749bc99dcfa58 100644 (file)
@@ -15,6 +15,7 @@ Require-Bundle: org.eclipse.ui,
  org.eclipse.tracecompass.common.core,
  org.eclipse.tracecompass.tmf.core,
  org.eclipse.tracecompass.tmf.ui,
+ org.eclipse.tracecompass.analysis.os.linux.core,
  org.eclipse.tracecompass.analysis.os.linux.ui,
  org.eclipse.tracecompass.tmf.ctf.core,
  org.eclipse.tracecompass.lttng2.control.core,
@@ -27,4 +28,5 @@ Require-Bundle: org.eclipse.ui,
 Import-Package: com.google.common.collect
 Export-Package: org.eclipse.tracecompass.internal.lttng2.kernel.ui;x-internal:=true,
  org.eclipse.tracecompass.internal.lttng2.kernel.ui.criticalpath;x-internal:=true,
- org.eclipse.tracecompass.internal.lttng2.kernel.ui.views;x-friends:="org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests"
+ org.eclipse.tracecompass.internal.lttng2.kernel.ui.views;x-friends:="org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests",
+ org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.vm.vcpuview;x-internal:=true
index 96a73ce0eaf4432f0d3b57f42942656b16dabbbb..4aef7c0df787ace41a00e84ba66f82fa830ac582 100644 (file)
@@ -21,3 +21,5 @@ cpuusage.view.name = CPU Usage
 
 tracetype.type.kernel = LTTng Kernel Trace
 analysis.lttngkernel = LTTng Kernel Analysis
+
+vcpuview.name = Virtual CPU View
\ No newline at end of file
index 6890ccb287daebe99ffc481c9aea1fe067eef8fc..d730444d95f7137f79c2a30b194ea7c626bd0876 100644 (file)
             name="%kernel.perspective.name">
       </perspective>
    </extension>
+   <extension
+         point="org.eclipse.ui.views">
+      <view
+            allowMultiple="false"
+            category="org.eclipse.linuxtools.tmf.ui.views.category"
+            class="org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.vm.vcpuview.VirtualMachineView"
+            id="org.eclipse.tracecompass.lttng2.analysis.vm.ui.vmview"
+            name="%vcpuview.name"
+            restorable="true">
+      </view>
+   </extension>
    <extension
          point="org.eclipse.ui.navigator.navigatorContent">
       <commonWizard
          </enablement>
       </commonWizard>
    </extension>
+   <extension
+         point="org.eclipse.linuxtools.tmf.core.analysis">
+      <output
+            class="org.eclipse.tracecompass.tmf.ui.analysis.TmfAnalysisViewOutput"
+            id="org.eclipse.tracecompass.lttng2.analysis.vm.ui.vmview">
+         <analysisId
+               id="org.eclipse.tracecompass.lttng2.analysis.vm.core.VirtualMachineAnalysisModule">
+         </analysisId>
+      </output>
+   </extension>
    <extension
          point="org.eclipse.linuxtools.tmf.ui.tracetypeui">
       <type
diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/Messages.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/Messages.java
new file mode 100644 (file)
index 0000000..04e6527
--- /dev/null
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.vm.vcpuview;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.osgi.util.NLS;
+
+@SuppressWarnings("javadoc")
+public class Messages extends NLS {
+    private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.vm.vcpuview.messages"; //$NON-NLS-1$
+
+    public static @Nullable String VmView_threads;
+    public static @Nullable String VmView_stateTypeName;
+    public static @Nullable String VmView_multipleStates;
+    public static @Nullable String VmView_nextResourceActionNameText;
+    public static @Nullable String VmView_nextResourceActionToolTipText;
+    public static @Nullable String VmView_previousResourceActionNameText;
+    public static @Nullable String VmView_previousResourceActionToolTipText;
+    public static @Nullable String VmView_VCpu;
+    public static @Nullable String VmView_virtualMachine;
+
+    static {
+        // initialize resource bundle
+        NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+    }
+
+    private Messages() {
+    }
+
+}
diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/VirtualMachineCommon.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/VirtualMachineCommon.java
new file mode 100644 (file)
index 0000000..aed70e8
--- /dev/null
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.vm.vcpuview;
+
+/**
+ * Provides some common elements for all virtual machine views
+ *
+ * @author Mohamad Gebai
+ */
+public final class VirtualMachineCommon {
+
+    /** Type of resources/entries */
+    public static enum Type {
+        /** Entries for VMs */
+        VM,
+        /** Entries for VCPUs */
+        VCPU,
+        /** Entries for Threads */
+        THREAD,
+        /** Null resources (filler rows, etc.) */
+        NULL
+    }
+}
diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/VirtualMachinePresentationProvider.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/VirtualMachinePresentationProvider.java
new file mode 100644 (file)
index 0000000..ed29f38
--- /dev/null
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.vm.vcpuview;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.StateValues;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.VcpuStateValues;
+import org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.vm.vcpuview.VirtualMachineCommon.Type;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.StateItem;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
+
+/**
+ * Presentation provider for the Virtual Machine view, based on the generic TMF
+ * presentation provider.
+ *
+ * @author Mohamad Gebai
+ */
+public class VirtualMachinePresentationProvider extends TimeGraphPresentationProvider {
+
+    /*
+     * TODO: Some of it is copy-pasted from the control flow presentation
+     * provider because it actually is the same data as from the control flow
+     * view. Ideally, we should reuse what is there instead of rewriting it here
+     */
+    private enum State {
+        UNKNOWN(new RGB(100, 100, 100)),
+        IDLE(new RGB(200, 200, 200)),
+        USERMODE(new RGB(0, 200, 0)),
+        WAIT_VMM(new RGB(200, 0, 0)),
+        VCPU_PREEMPTED(new RGB(120, 40, 90)),
+        THREAD_UNKNOWN(new RGB(100, 100, 100)),
+        THREAD_WAIT_BLOCKED(new RGB(200, 200, 0)),
+        THREAD_WAIT_FOR_CPU(new RGB(200, 100, 0)),
+        THREAD_USERMODE(new RGB(0, 200, 0)),
+        THREAD_SYSCALL(new RGB(0, 0, 200)),
+        THREAD_INTERRUPTED(new RGB(200, 0, 100));
+
+        public final RGB rgb;
+
+        private State(RGB rgb) {
+            this.rgb = rgb;
+        }
+    }
+
+    /**
+     * Default constructor
+     */
+    public VirtualMachinePresentationProvider() {
+        super();
+    }
+
+    private static State[] getStateValues() {
+        return State.values();
+    }
+
+    private static State getStateForVcpu(int value) {
+        if ((value & VcpuStateValues.VCPU_PREEMPT) > 0) {
+            return State.VCPU_PREEMPTED;
+        } else if ((value & VcpuStateValues.VCPU_VMM) > 0) {
+            return State.WAIT_VMM;
+        } else if (value == 2) {
+            return State.USERMODE;
+        } else if (value == 1) {
+            return State.IDLE;
+        } else {
+            return State.UNKNOWN;
+        }
+    }
+
+    private static @Nullable State getStateForThread(int value) {
+        if (value == VcpuStateValues.VCPU_PREEMPT) {
+            return null;
+        }
+        switch (value) {
+        case StateValues.PROCESS_STATUS_RUN_USERMODE:
+            return State.THREAD_USERMODE;
+        case StateValues.PROCESS_STATUS_RUN_SYSCALL:
+            return State.THREAD_SYSCALL;
+        case StateValues.PROCESS_STATUS_WAIT_FOR_CPU:
+            return State.THREAD_WAIT_FOR_CPU;
+        case StateValues.PROCESS_STATUS_WAIT_BLOCKED:
+            return State.THREAD_WAIT_BLOCKED;
+        case StateValues.PROCESS_STATUS_INTERRUPTED:
+            return State.THREAD_INTERRUPTED;
+        case StateValues.PROCESS_STATUS_UNKNOWN:
+        case StateValues.PROCESS_STATUS_WAIT_UNKNOWN:
+            return State.THREAD_UNKNOWN;
+        default:
+            return null;
+        }
+    }
+
+    private static @Nullable State getEventState(TimeEvent event) {
+        if (event.hasValue()) {
+            VirtualMachineViewEntry entry = (VirtualMachineViewEntry) event.getEntry();
+            int value = event.getValue();
+
+            if (entry.getType() == Type.VCPU) {
+                return getStateForVcpu(value);
+            } else if (entry.getType() == Type.THREAD) {
+                return getStateForThread(value);
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public int getStateTableIndex(@Nullable ITimeEvent event) {
+        if (event == null) {
+            return TRANSPARENT;
+        }
+        State state = getEventState((TimeEvent) event);
+        if (state != null) {
+            return state.ordinal();
+        }
+        if (event instanceof NullTimeEvent) {
+            return INVISIBLE;
+        }
+        return TRANSPARENT;
+    }
+
+    @Override
+    public StateItem[] getStateTable() {
+        State[] states = getStateValues();
+        StateItem[] stateTable = new StateItem[states.length];
+        for (int i = 0; i < stateTable.length; i++) {
+            State state = states[i];
+            stateTable[i] = new StateItem(state.rgb, state.toString());
+        }
+        return stateTable;
+    }
+
+    @Override
+    public @Nullable String getEventName(@Nullable ITimeEvent event) {
+        if (event == null) {
+            return null;
+        }
+        State state = getEventState((TimeEvent) event);
+        if (state != null) {
+            return state.toString();
+        }
+        if (event instanceof NullTimeEvent) {
+            return null;
+        }
+        return Messages.VmView_multipleStates;
+    }
+
+    @Override
+    public void postDrawEvent(@Nullable ITimeEvent event, @Nullable Rectangle bounds, @Nullable GC gc) {
+        if (bounds == null || gc == null) {
+            return;
+        }
+        boolean visible = bounds.width == 0 ? false : true;
+        if (!visible) {
+            return;
+        }
+        if (!(event instanceof TimeEvent)) {
+            return;
+        }
+        TimeEvent ev = (TimeEvent) event;
+        /*
+         * FIXME: There seems to be a bug when multiple events should be drawn
+         * under a alpha event. See FIXME comment in
+         * VirtualMachineView#getEventList
+         */
+        if (ev.hasValue()) {
+            VirtualMachineViewEntry entry = (VirtualMachineViewEntry) event.getEntry();
+
+            if (entry.getType() == Type.THREAD) {
+                int value = ev.getValue();
+                if ((value & VcpuStateValues.VCPU_PREEMPT) != 0) {
+                    /*
+                     * If the status was preempted at this time, draw an alpha
+                     * over this state
+                     */
+                    Color alphaColor = Display.getDefault().getSystemColor(SWT.COLOR_RED);
+
+                    int alpha = gc.getAlpha();
+                    Color background = gc.getBackground();
+                    // fill all rect area
+                    gc.setBackground(alphaColor);
+                    gc.setAlpha(70);
+                    gc.fillRectangle(bounds);
+
+                    gc.setBackground(background);
+                    gc.setAlpha(alpha);
+                }
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/VirtualMachineView.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/VirtualMachineView.java
new file mode 100644 (file)
index 0000000..53a5bc9
--- /dev/null
@@ -0,0 +1,508 @@
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.vm.vcpuview;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.KernelAnalysisModule;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.KernelThreadInformationProvider;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.VmAttributes;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.module.VirtualMachineCpuAnalysis;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.trace.VirtualMachineExperiment;
+import org.eclipse.tracecompass.internal.lttng2.kernel.ui.Activator;
+import org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.vm.vcpuview.VirtualMachineCommon.Type;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
+import org.eclipse.tracecompass.statesystem.core.StateSystemUtils;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
+import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
+import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
+import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperimentUtils;
+import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractTimeGraphView;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
+
+import com.google.common.collect.Multimap;
+
+/**
+ * Main implementation for the Virtual Machine view
+ *
+ * @author Mohamad Gebai
+ */
+public class VirtualMachineView extends AbstractTimeGraphView {
+
+    /** View ID. */
+    public static final String ID = "org.eclipse.tracecompass.lttng2.analysis.vm.ui.vmview"; //$NON-NLS-1$
+
+    private static final String[] COLUMN_NAMES = new String[] {
+            Messages.VmView_stateTypeName
+    };
+
+    private static final String[] FILTER_COLUMN_NAMES = new String[] {
+            Messages.VmView_stateTypeName
+    };
+
+    // Timeout between updates in the build thread in ms
+    private static final long BUILD_UPDATE_TIMEOUT = 500;
+    private static final int[] DEFAULT_WEIGHT = { 1, 3 };
+
+    private Comparator<ITimeGraphEntry> fComparator = new Comparator<ITimeGraphEntry>() {
+        @Override
+        public int compare(@Nullable ITimeGraphEntry o1, @Nullable ITimeGraphEntry o2) {
+            if (!((o1 instanceof VirtualMachineViewEntry) && (o2 instanceof VirtualMachineViewEntry))) {
+                return 0;
+            }
+            VirtualMachineViewEntry entry1 = (VirtualMachineViewEntry) o1;
+            VirtualMachineViewEntry entry2 = (VirtualMachineViewEntry) o2;
+            int cmp = entry1.getType().compareTo(entry2.getType());
+            /* FIXME: Threads should be ordered by their thread IDs instead */
+            if (cmp == 0) {
+                cmp = entry1.getName().compareTo(entry2.getName());
+            }
+            return cmp;
+        }
+    };
+
+    // ------------------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------------------
+
+    /**
+     * Default constructor
+     */
+    public VirtualMachineView() {
+        super(ID, new VirtualMachinePresentationProvider());
+        setFilterColumns(FILTER_COLUMN_NAMES);
+        setTreeColumns(COLUMN_NAMES);
+        setTreeLabelProvider(new VmViewTreeLabelProvider());
+        setWeight(DEFAULT_WEIGHT);
+        setAutoExpandLevel(2);
+    }
+
+    @Override
+    protected @Nullable String getNextText() {
+        return Messages.VmView_nextResourceActionNameText;
+    }
+
+    @Override
+    protected @Nullable String getNextTooltip() {
+        return Messages.VmView_nextResourceActionToolTipText;
+    }
+
+    @Override
+    protected @Nullable String getPrevText() {
+        return Messages.VmView_previousResourceActionNameText;
+    }
+
+    @Override
+    protected @Nullable String getPrevTooltip() {
+        return Messages.VmView_previousResourceActionToolTipText;
+    }
+
+    private static class VmViewTreeLabelProvider extends TreeLabelProvider {
+
+        @Override
+        public String getColumnText(@Nullable Object element, int columnIndex) {
+            if (!(element instanceof VirtualMachineViewEntry)) {
+                return ""; //$NON-NLS-1$
+            }
+            VirtualMachineViewEntry entry = (VirtualMachineViewEntry) element;
+
+            if (COLUMN_NAMES[columnIndex].equals(Messages.VmView_stateTypeName)) {
+                String name = entry.getName();
+                return (name == null) ? "" : name; //$NON-NLS-1$
+            }
+            return ""; //$NON-NLS-1$
+        }
+
+    }
+
+    // ------------------------------------------------------------------------
+    // Internal
+    // ------------------------------------------------------------------------
+
+    @Override
+    protected void buildEventList(ITmfTrace trace, ITmfTrace parentTrace, IProgressMonitor monitor) {
+        setStartTime(Long.MAX_VALUE);
+        setEndTime(Long.MIN_VALUE);
+
+        if (monitor.isCanceled()) {
+            return;
+        }
+        if (!(parentTrace instanceof VirtualMachineExperiment)) {
+            return;
+        }
+        ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(parentTrace, VirtualMachineCpuAnalysis.ID);
+        if (ssq == null) {
+            return;
+        }
+        VirtualMachineExperiment vmExperiment = (VirtualMachineExperiment) parentTrace;
+        long startTime = ssq.getStartTime();
+
+        ArrayList<VirtualMachineViewEntry> entryList = new ArrayList<>();
+        Map<String, VirtualMachineViewEntry> entryMap = new HashMap<>();
+
+        boolean complete = false;
+        VirtualMachineViewEntry groupEntry = null;
+
+        while (!complete) {
+            if (monitor.isCanceled()) {
+                return;
+            }
+            complete = ssq.waitUntilBuilt(BUILD_UPDATE_TIMEOUT);
+            if (ssq.isCancelled()) {
+                return;
+            }
+
+            long endTime = ssq.getCurrentEndTime() + 1;
+            if (groupEntry == null) {
+                groupEntry = new VirtualMachineViewEntry.VmEntryBuilder(vmExperiment.getName(), startTime, endTime, vmExperiment).build();
+                /*
+                 * There is only one root entry for this view, so we can put it
+                 * right away
+                 */
+                entryList.add(groupEntry);
+                putEntryList(parentTrace, new ArrayList<TimeGraphEntry>(entryList));
+            } else {
+                groupEntry.updateEndTime(endTime);
+            }
+
+            setStartTime(Math.min(getStartTime(), startTime));
+            setEndTime(Math.max(getEndTime(), endTime));
+
+            /*
+             * Create the entries for the VMs in this experiment and their
+             * respective threads
+             */
+            buildEntries(ssq, startTime, endTime, groupEntry, entryMap, vmExperiment);
+
+            if (parentTrace.equals(getTrace())) {
+                refresh();
+            }
+
+            for (VirtualMachineViewEntry entry : entryList) {
+                if (monitor.isCanceled()) {
+                    return;
+                }
+                buildEntryEventList(entry, ssq, startTime, endTime, monitor);
+            }
+        }
+    }
+
+    private void buildEntries(ITmfStateSystem ssq, long startTime, long endTime, VirtualMachineViewEntry groupEntry,
+            Map<@NonNull String, @NonNull VirtualMachineViewEntry> entryMap, VirtualMachineExperiment vmExperiment) {
+        try {
+            List<Integer> vmQuarks = ssq.getQuarks(VmAttributes.VIRTUAL_MACHINES, "*"); //$NON-NLS-1$
+            /* For each virtual machine in the analysis */
+            for (Integer vmQuark : vmQuarks) {
+
+                /* Display an entry for the virtual machine */
+                String vmHostId = NonNullUtils.checkNotNull(ssq.getAttributeName(vmQuark));
+                ITmfStateInterval vmNameInterval = StateSystemUtils.queryUntilNonNullValue(ssq, vmQuark, startTime, endTime);
+                String vmName = vmHostId;
+                if (vmNameInterval != null) {
+                    vmName = vmNameInterval.getStateValue().unboxStr();
+                }
+
+                VirtualMachineViewEntry vmEntry = entryMap.get(vmHostId);
+                if (vmEntry == null) {
+                    vmEntry = new VirtualMachineViewEntry.VmEntryBuilder(vmName, startTime, endTime, vmExperiment).setId(vmHostId).setVmName(vmName).setNumericId(vmQuark).setType(Type.VM).build();
+                    vmEntry.sortChildren(fComparator);
+
+                    groupEntry.addChild(vmEntry);
+                    entryMap.put(vmHostId, vmEntry);
+                } else {
+                    vmEntry.updateEndTime(endTime);
+                }
+
+                /* Display an entry for each of its CPUs */
+                for (Integer vCpuQuark : ssq.getSubAttributes(vmQuark, false)) {
+                    String vcpuId = ssq.getAttributeName(vCpuQuark);
+                    VirtualMachineViewEntry vcpuEntry = entryMap.get(vmHostId + vcpuId);
+                    if (vcpuEntry == null) {
+                        vcpuEntry = new VirtualMachineViewEntry.VmEntryBuilder(vcpuId, startTime, endTime, vmExperiment).setId(vcpuId).setVmName(vmName).setNumericId(vCpuQuark).setType(Type.VCPU).build();
+
+                        vmEntry.addChild(vcpuEntry);
+                        entryMap.put(vmHostId + vcpuId, vcpuEntry);
+                    } else {
+                        vcpuEntry.updateEndTime(endTime);
+                    }
+
+                }
+
+                /*
+                 * Get the LTTng Kernel analysis module from the corresponding
+                 * trace
+                 */
+                KernelAnalysisModule kernelModule = TmfExperimentUtils.getAnalysisModuleOfClassForHost(vmExperiment, vmHostId, KernelAnalysisModule.class);
+                if (kernelModule == null) {
+                    continue;
+                }
+
+                VirtualMachineViewEntry threadEntry = entryMap.get(vmHostId + NonNullUtils.nullToEmptyString(Messages.VmView_threads));
+                if (threadEntry == null) {
+                    threadEntry = new VirtualMachineViewEntry.VmEntryBuilder(NonNullUtils.nullToEmptyString(Messages.VmView_threads), startTime, endTime, vmExperiment).build();
+                    entryMap.put(vmHostId + NonNullUtils.nullToEmptyString(Messages.VmView_threads), threadEntry);
+                    vmEntry.addChild(threadEntry);
+                } else {
+                    threadEntry.updateEndTime(endTime);
+                }
+
+                /*
+                 * Display an entry for each thread.
+                 *
+                 * For each interval that is in a running status, intersect with
+                 * the status of the virtual CPU it is currently running on
+                 */
+                Collection<Integer> threadIds = KernelThreadInformationProvider.getThreadIds(kernelModule);
+                for (Integer threadId : threadIds) {
+                    if (threadId == -1) {
+                        continue;
+                    }
+                    VirtualMachineViewEntry oneThreadEntry = entryMap.get(vmHostId + ':' + threadId);
+                    if (oneThreadEntry != null) {
+                        oneThreadEntry.updateEndTime(endTime);
+                        continue;
+                    }
+                    /*
+                     * FIXME: Only add threads that are active during the trace
+                     */
+                    String threadName = KernelThreadInformationProvider.getExecutableName(kernelModule, threadId);
+                    String tidString = NonNullUtils.checkNotNull(threadId.toString());
+                    threadName = (threadName != null) ? tidString + ':' + ' ' + threadName : tidString;
+                    oneThreadEntry = new VirtualMachineViewEntry.VmEntryBuilder(threadName, startTime, endTime, vmExperiment).setId(threadName).setVmName(vmName).setNumericId(threadId).setType(Type.THREAD).build();
+
+                    threadEntry.addChild(oneThreadEntry);
+                    entryMap.put(vmHostId + ':' + threadId, oneThreadEntry);
+                }
+
+            }
+        } catch (AttributeNotFoundException e) {
+            /*
+             * The attribute may not exist yet if the state system is being
+             * built
+             */
+        } catch (TimeRangeException | StateValueTypeException e) {
+            Activator.getDefault().logError("VirtualMachineView: error building event list", e); //$NON-NLS-1$
+        }
+    }
+
+    private void buildEntryEventList(TimeGraphEntry entry, ITmfStateSystem ssq, long start, long end, IProgressMonitor monitor) {
+        if (start < entry.getEndTime() && end > entry.getStartTime()) {
+
+            long startTime = Math.max(start, entry.getStartTime());
+            long endTime = Math.min(end + 1, entry.getEndTime());
+            long resolution = Math.max(1, (end - ssq.getStartTime()) / getDisplayWidth());
+            List<ITimeEvent> eventList = getEventList(entry, startTime, endTime, resolution, monitor);
+            entry.setEventList(eventList);
+            redraw();
+            for (ITimeGraphEntry child : entry.getChildren()) {
+                if (!(child instanceof TimeGraphEntry)) {
+                    continue;
+                }
+                if (monitor.isCanceled()) {
+                    return;
+                }
+                buildEntryEventList((TimeGraphEntry) child, ssq, start, end, monitor);
+            }
+        }
+    }
+
+    @Override
+    protected @Nullable List<ITimeEvent> getEventList(TimeGraphEntry entry,
+            long startTime, long endTime, long resolution,
+            IProgressMonitor monitor) {
+        if (!(entry instanceof VirtualMachineViewEntry)) {
+            return null;
+        }
+        if (monitor.isCanceled()) {
+            return null;
+        }
+
+        VirtualMachineViewEntry vmEntry = (VirtualMachineViewEntry) entry;
+
+        switch (vmEntry.getType()) {
+        case THREAD: {
+            return getThreadEventList(entry, vmEntry, monitor);
+        }
+        case VCPU: {
+            return getVcpuEventList(entry, vmEntry, startTime, endTime, resolution, monitor);
+        }
+        case VM: {
+            VirtualMachineExperiment experiment = vmEntry.getExperiment();
+            VirtualMachineCpuAnalysis vmAnalysis = null;
+            for (VirtualMachineCpuAnalysis module : TmfTraceUtils.getAnalysisModulesOfClass(experiment, VirtualMachineCpuAnalysis.class)) {
+                vmAnalysis = module;
+                break;
+            }
+            if (vmAnalysis == null) {
+                break;
+            }
+            Multimap<Integer, ITmfStateInterval> updatedThreadIntervals = vmAnalysis.getUpdatedThreadIntervals(vmEntry.getNumericId(), startTime, endTime, resolution, monitor);
+            vmEntry.setThreadIntervals(updatedThreadIntervals);
+        }
+            break;
+        case NULL:
+            /* These entry types are not used in this view */
+            break;
+        default:
+            break;
+        }
+
+        return null;
+    }
+
+    private static @Nullable List<@NonNull ITimeEvent> getVcpuEventList(TimeGraphEntry entry, VirtualMachineViewEntry vmEntry, long startTime, long endTime, long resolution, IProgressMonitor monitor) {
+        List<ITimeEvent> eventList = null;
+        try {
+            int quark = vmEntry.getNumericId();
+
+            ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(vmEntry.getExperiment(), VirtualMachineCpuAnalysis.ID);
+            if (ssq == null) {
+                return Collections.EMPTY_LIST;
+            }
+            final long realStart = Math.max(startTime, ssq.getStartTime());
+            final long realEnd = Math.min(endTime, ssq.getCurrentEndTime() + 1);
+            if (realEnd <= realStart) {
+                return Collections.EMPTY_LIST;
+            }
+            quark = ssq.getQuarkRelative(quark, VmAttributes.STATUS);
+            List<ITmfStateInterval> statusIntervals = StateSystemUtils.queryHistoryRange(ssq, quark, realStart, realEnd - 1, resolution, monitor);
+            eventList = new ArrayList<>(statusIntervals.size());
+            long lastEndTime = -1;
+            for (ITmfStateInterval statusInterval : statusIntervals) {
+                if (monitor.isCanceled()) {
+                    return null;
+                }
+
+                long time = statusInterval.getStartTime();
+                long duration = statusInterval.getEndTime() - time + 1;
+                if (!statusInterval.getStateValue().isNull()) {
+                    int status = statusInterval.getStateValue().unboxInt();
+                    if (lastEndTime != time && lastEndTime != -1) {
+                        eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
+                    }
+                    eventList.add(new TimeEvent(entry, time, duration, status));
+                } else if (lastEndTime == -1 || time + duration >= endTime) {
+                    // add null event if it intersects the start or end time
+                    eventList.add(new NullTimeEvent(entry, time, duration));
+                }
+                lastEndTime = time + duration;
+            }
+        } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
+            Activator.getDefault().logError("Error getting event list", e); //$NON-NLS-1$
+        } catch (StateSystemDisposedException e) {
+            /* Ignored */
+        }
+        return eventList;
+    }
+
+    private static @Nullable List<@NonNull ITimeEvent> getThreadEventList(TimeGraphEntry entry, VirtualMachineViewEntry vmEntry, IProgressMonitor monitor) {
+        List<ITimeEvent> eventList = null;
+        /*
+         * The parent VM entry will contain the thread intervals for all thread.
+         * Just take the list from there
+         */
+        Collection<ITmfStateInterval> threadIntervals = null;
+        ITimeGraphEntry parent = vmEntry.getParent();
+        while (threadIntervals == null && parent != null) {
+            if (parent instanceof VirtualMachineViewEntry) {
+                threadIntervals = ((VirtualMachineViewEntry) parent).getThreadIntervals(vmEntry.getNumericId());
+            }
+            if (parent instanceof TimeGraphEntry) {
+                parent = ((TimeGraphEntry) parent).getParent();
+            }
+        }
+        if (threadIntervals != null) {
+            eventList = new ArrayList<>(threadIntervals.size());
+            long lastEndTime = -1;
+            for (ITmfStateInterval interval : threadIntervals) {
+                if (monitor.isCanceled()) {
+                    return null;
+                }
+                long time = interval.getStartTime();
+                long duration = interval.getEndTime() - time + 1;
+                /*
+                 * FIXME: I think the key for the alpha bug when alpha overlaps
+                 * multiple events is around here
+                 *
+                 * Hint by Patrick: "The problem is that the thread intervals
+                 * are sorted by start time, and drawn in that order.
+                 *
+                 * Given the intervals: Blue [0,10] Alpha [5,15] Red [10,20]
+                 *
+                 * Blue is drawn, then Alpha makes DarkBlue from [5,10] and
+                 * DarkBackground from [10,15], then Red is drawn over [10,20],
+                 * overwriting the DarkBackground. There is no DarkRed.
+                 *
+                 * For this to work you would have to draw all real states
+                 * first, then all alpha states second.
+                 *
+                 * I think this would also have the side-effect that the find
+                 * item used for tool tips would always find the real event and
+                 * never the alpha event. This might be what we want. Right now
+                 * the tool tip has State: (multiple).
+                 *
+                 * But using the Next Event button, we would skip to the next
+                 * real event and not at the preemption event. Maybe not what we
+                 * want.
+                 *
+                 * Maybe what we need is separate thread interval events:
+                 *
+                 * Blue [0,5] Preempted Blue [5,10] Preempted Red [10,15] Red
+                 * [15,20]...
+                 *
+                 * The preempted events would have the real state value, but
+                 * with a flag for alpha to be used in the postDrawEvent."
+                 */
+                if (!interval.getStateValue().isNull()) {
+                    int status = interval.getStateValue().unboxInt();
+                    if (lastEndTime < time && lastEndTime != -1) {
+                        /*
+                         * Add a time event to fill the blanks between intervals
+                         */
+                        eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
+                    }
+                    eventList.add(new TimeEvent(entry, time, duration, status));
+                } else if (lastEndTime == -1) {
+                    eventList.add(new NullTimeEvent(entry, time, duration));
+                }
+                lastEndTime = time + duration;
+            }
+        }
+        return eventList;
+    }
+
+    @Override
+    protected Iterable<ITmfTrace> getTracesToBuild(@Nullable ITmfTrace trace) {
+        if (trace == null) {
+            return NonNullUtils.checkNotNull(Collections.EMPTY_SET);
+        }
+        return NonNullUtils.checkNotNull(Collections.singleton(trace));
+    }
+
+}
diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/VirtualMachineViewEntry.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/VirtualMachineViewEntry.java
new file mode 100644 (file)
index 0000000..40771d3
--- /dev/null
@@ -0,0 +1,308 @@
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.vm.vcpuview;
+
+import java.util.Collection;
+import java.util.Comparator;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.trace.VirtualMachineExperiment;
+import org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.vm.vcpuview.VirtualMachineCommon.Type;
+import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
+
+import com.google.common.collect.Multimap;
+
+/**
+ * An entry, or row, in the Virtual CPU view
+ *
+ * @author Mohamad Gebai
+ */
+public class VirtualMachineViewEntry extends TimeGraphEntry {
+
+    private static final Comparator<ITimeGraphEntry> COMPARATOR = new Comparator<ITimeGraphEntry>() {
+
+        @Override
+        public int compare(@Nullable ITimeGraphEntry o1, @Nullable ITimeGraphEntry o2) {
+
+            int result = 0;
+
+            if ((o1 instanceof VirtualMachineViewEntry) && (o2 instanceof VirtualMachineViewEntry)) {
+                VirtualMachineViewEntry entry1 = (VirtualMachineViewEntry) o1;
+                VirtualMachineViewEntry entry2 = (VirtualMachineViewEntry) o2;
+                result = entry1.getType().compareTo(entry2.getType());
+                if (result == 0) {
+                    result = entry1.getId().compareTo(entry2.getId());
+                }
+            }
+            return result;
+        }
+    };
+
+    private final String fId;
+    private final @Nullable String fVmName;
+    private final ITmfTrace fTrace;
+    private final VirtualMachineExperiment fExperiment;
+    private final Type fType;
+    private final Integer fNid;
+    private @Nullable Multimap<Integer, ITmfStateInterval> fThreadIntervals = null;
+
+    /**
+     * Private constructor using a builder to build an entry
+     *
+     * @param builder
+     *            The builder from which to build this entry
+     */
+    private VirtualMachineViewEntry(VmEntryBuilder builder) {
+        super(builder.fbEntryName, builder.fbStartTime, builder.fbEndTime);
+        fId = builder.fbId;
+        fExperiment = builder.fbExperiment;
+        /* If trace is not set, initialize to experiment */
+        ITmfTrace trace = builder.fbTrace;
+        if (trace == null) {
+            trace = fExperiment;
+        }
+        fTrace = trace;
+        fType = builder.fbType;
+        Integer nid = builder.fbNid;
+        if (nid == null) {
+            nid = -1;
+        }
+        fNid = nid;
+        fVmName = builder.fbVmName;
+        this.sortChildren(COMPARATOR);
+    }
+
+    /**
+     * Builder class that allows to build an entry by setting the parameters
+     * independently, instead of using directly the constructors with many
+     * parameters.
+     *
+     * @author Geneviève Bastien
+     */
+    public static class VmEntryBuilder {
+
+        private final long fbStartTime;
+        private final long fbEndTime;
+        private final VirtualMachineExperiment fbExperiment;
+
+        private String fbEntryName;
+        private String fbId;
+        private Type fbType;
+        private @Nullable String fbVmName;
+        private @Nullable ITmfTrace fbTrace;
+        private @Nullable Integer fbNid;
+
+        /**
+         * Virtual Machine Entry builder constructor.
+         *
+         * @param name
+         *            The name of this entry. It is also the default ID of this
+         *            entry. So the ID does not need to be set if it is the same
+         *            as the name.
+         * @param startTime
+         *            The start time of the entry
+         * @param endTime
+         *            The end time of the entry
+         * @param experiment
+         *            The experiment this entry applies to
+         */
+        public VmEntryBuilder(String name, long startTime, long endTime, VirtualMachineExperiment experiment) {
+            fbEntryName = name;
+            fbStartTime = startTime;
+            fbEndTime = endTime;
+            fbExperiment = experiment;
+            fbId = name;
+            fbType = Type.NULL;
+        }
+
+        /**
+         * Sets the ID of this entry
+         *
+         * @param id
+         *            The ID of the virtual machine entry
+         * @return The builder with updated fields
+         */
+        public VmEntryBuilder setId(String id) {
+            fbId = id;
+            return this;
+        }
+
+        /**
+         * Sets the virtual machine name of this entry
+         *
+         * @param vmName
+         *            The virtual machine name of the virtual machine entry
+         * @return The builder with updated fields
+         */
+        public VmEntryBuilder setVmName(String vmName) {
+            fbVmName = vmName;
+            return this;
+        }
+
+        /**
+         * Sets the trace this entry applies to
+         *
+         * @param trace
+         *            The trace this entry is for
+         * @return The builder with updated fields
+         */
+        public VmEntryBuilder setTrace(ITmfTrace trace) {
+            fbTrace = trace;
+            return this;
+        }
+
+        /**
+         * Sets the type of this entry
+         *
+         * @param type
+         *            The type of the virtual machine entry
+         * @return The builder with updated fields
+         */
+        public VmEntryBuilder setType(Type type) {
+            fbType = type;
+            return this;
+        }
+
+        /**
+         * Sets the numeric ID of this entry. For VM or VCPU types, it is the
+         * quark of the object represented by this entry, for THREAD types, it
+         * is the thread ID of the corresponding thread.
+         *
+         * @param nid
+         *            The numeric ID of the virtual machine entry
+         * @return The builder with updated fields
+         */
+        public VmEntryBuilder setNumericId(Integer nid) {
+            fbNid = nid;
+            return this;
+        }
+
+        /**
+         * Creates a new instance of {@link VirtualMachineViewEntry} with the
+         * fields corresponding to those set in the builder.
+         *
+         * @return A new {@link VirtualMachineViewEntry} object
+         */
+        public VirtualMachineViewEntry build() {
+            switch(fbType) {
+            case VCPU:
+                fbEntryName = Messages.VmView_VCpu + ' ' + fbEntryName;
+                break;
+            case VM:
+                fbEntryName = NonNullUtils.nullToEmptyString(NLS.bind(Messages.VmView_virtualMachine, fbEntryName));
+                break;
+            case NULL:
+            case THREAD:
+            default:
+                break;
+
+            }
+            return new VirtualMachineViewEntry(this);
+        }
+
+    }
+
+    /**
+     * Get the entry's id
+     *
+     * @return the entry's id
+     */
+    public String getId() {
+        return fId;
+    }
+
+    /**
+     * Get the name of the virtual machine this entry belongs to
+     *
+     * @return The name of the virtual machine
+     */
+    public @Nullable String getVmName() {
+        return fVmName;
+    }
+
+    /**
+     * Get the entry's kernel trace
+     *
+     * @return the entry's kernel trace
+     */
+    public ITmfTrace getTrace() {
+        return fTrace;
+    }
+
+    /**
+     * Get the entry's kernel trace
+     *
+     * @return the entry's kernel trace
+     */
+    public VirtualMachineExperiment getExperiment() {
+        return fExperiment;
+    }
+
+    /**
+     * Get the entry Type of this entry. Uses the virtual machine enum
+     * {@link Type}
+     *
+     * @return The entry type
+     */
+    public Type getType() {
+        return fType;
+    }
+
+    /**
+     * Retrieve the numeric ID that represents this entry.
+     *
+     * @return The numeric ID matching the entry
+     */
+    public Integer getNumericId() {
+        return fNid;
+    }
+
+    @Override
+    public boolean hasTimeEvents() {
+        if (fType == Type.NULL) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Get the state intervals for a given thread ID
+     *
+     * @param threadId
+     *            The thread ID for which to get the intervals
+     * @return A collection of intervals for this thread, or {@code null} if no
+     *         intervals are available for this thread
+     */
+    public @Nullable Collection<ITmfStateInterval> getThreadIntervals(Integer threadId) {
+        final Multimap<Integer, ITmfStateInterval> threadIntervals = fThreadIntervals;
+        if (threadIntervals == null) {
+            return null;
+        }
+        return threadIntervals.get(threadId);
+
+    }
+
+    /**
+     * Set the intervals for the threads of the corresponding virtual machine.
+     * This should be called only if the type of this entry is {@link Type#VM}.
+     *
+     * @param threadIntervals
+     *            The map of intervals for each thread ID
+     */
+    public void setThreadIntervals(Multimap<Integer, ITmfStateInterval> threadIntervals) {
+        fThreadIntervals = threadIntervals;
+    }
+
+}
diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/messages.properties b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/messages.properties
new file mode 100644 (file)
index 0000000..84738cf
--- /dev/null
@@ -0,0 +1,18 @@
+###############################################################################
+# Copyright (c) 2016 École Polytechnique de Montréal
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+###############################################################################
+
+VmView_stateTypeName=Resource
+VmView_threads=Threads
+VmView_multipleStates=(multiple)
+VmView_nextResourceActionNameText=Next Resource
+VmView_nextResourceActionToolTipText=Select Next Resource
+VmView_previousResourceActionNameText=Previous Resource
+VmView_previousResourceActionToolTipText=Select Previous Resource
+VmView_VCpu=VCPU
+VmView_virtualMachine=Guest: {0}
diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/package-info.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/vm/vcpuview/package-info.java
new file mode 100644 (file)
index 0000000..8cc1586
--- /dev/null
@@ -0,0 +1,11 @@
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.vm.vcpuview;
\ No newline at end of file
This page took 0.038756 seconds and 5 git commands to generate.