LTTng: Introduce the virtual machine analysis analysis and core model
authorMohamad Gebai <mohamad.gebai@polymtl.ca>
Thu, 4 Dec 2014 02:40:56 +0000 (21:40 -0500)
committerGenevieve Bastien <gbastien+lttng@versatic.net>
Tue, 23 Dec 2014 15:52:55 +0000 (10:52 -0500)
This patch includes the core part of the virtual machine analysis:

* An experiment type for experiments containing guests and host traces
* A generic model for hypervisors to determine which virtual CPUs of which
guests run on which hosts
* The implementation of that model for the Qemu/KVM hypervisor
* The virtual machine analysis itself, tracking the state of the virtual CPUs
of the guests

Change-Id: I5763687fac627c78ae07b58ec60d907cf7339ff8
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/37600
Reviewed-by: Hudson CI
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
21 files changed:
org.eclipse.tracecompass.lttng2.kernel.core/META-INF/MANIFEST.MF
org.eclipse.tracecompass.lttng2.kernel.core/plugin.xml
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/VcpuStateValues.java [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/VmAttributes.java [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/HostThread.java [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/IVirtualMachineModel.java [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/VirtualCPU.java [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/VirtualMachine.java [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/package-info.java [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/qemukvm/QemuKvmStrings.java [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/qemukvm/QemuKvmVmModel.java [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/qemukvm/package-info.java [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/module/Messages.java [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/module/VirtualMachineCpuAnalysis.java [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/module/VirtualMachineStateProvider.java [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/module/messages.properties [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/module/package-info.java [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/package-info.java [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/trace/VirtualMachineExperiment.java [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/trace/package-info.java [new file with mode: 0644]
org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/lttng2/kernel/core/analysis/kernel/LttngKernelAnalysis.java

index 252b442f42621849c4fcfdf7f6df17cbf1ee8072..08fd169386496d12967849720fe3023d117b59c8 100644 (file)
@@ -16,9 +16,15 @@ Require-Bundle: org.eclipse.core.runtime,
  org.eclipse.tracecompass.tmf.ctf.core,
  org.eclipse.tracecompass.lttng2.control.core
 Export-Package: org.eclipse.tracecompass.internal.lttng2.kernel.core;x-friends:="org.eclipse.tracecompass.lttng2.kernel.ui,org.eclipse.tracecompass.lttng2.kernel.core.tests",
+ org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm;x-friends:="org.eclipse.tracecompass.lttng2.kernel.core.tests,org.eclipse.tracecompass.lttng2.kernel.ui",
+ org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model;x-friends:="org.eclipse.tracecompass.lttng2.kernel.core.tests,org.eclipse.tracecompass.lttng2.kernel.ui",
+ org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.qemukvm;x-friends:="org.eclipse.tracecompass.lttng2.kernel.core.tests,org.eclipse.tracecompass.lttng2.kernel.ui",
+ org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.module;x-friends:="org.eclipse.tracecompass.lttng2.kernel.core.tests,org.eclipse.tracecompass.lttng2.kernel.ui",
+ org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.trace;x-friends:="org.eclipse.tracecompass.lttng2.kernel.ui,org.eclipse.tracecompass.lttng2.kernel.core.tests",
  org.eclipse.tracecompass.internal.lttng2.kernel.core.event.matching,
  org.eclipse.tracecompass.internal.lttng2.kernel.core.trace.layout;x-friends:="org.eclipse.tracecompass.lttng2.kernel.core.tests,org.eclipse.tracecompass.lttng2.kernel.ui",
  org.eclipse.tracecompass.lttng2.kernel.core.analysis.cpuusage,
  org.eclipse.tracecompass.lttng2.kernel.core.analysis.kernel,
  org.eclipse.tracecompass.lttng2.kernel.core.trace
-Import-Package: com.google.common.collect
+Import-Package: com.google.common.collect,
+ com.google.common.hash;version="15.0.0"
index 85cb786cc3d239cd29cc60eb917ee18640d261ac..53a74482c8cd5359b7f3161a58645eb013df5dbb 100644 (file)
             name="%tracetype.type.kernel"
             trace_type="org.eclipse.tracecompass.lttng2.kernel.core.trace.LttngKernelTrace">
       </type>
+      <experiment
+            experiment_type="org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.trace.VirtualMachineExperiment"
+            id="lttng2.analysis.vm.VirtualMachineExperiment"
+            name="Virtual Machine Experiment">
+      </experiment>
    </extension>
    <extension
          point="org.eclipse.linuxtools.tmf.core.analysis">
                class="org.eclipse.tracecompass.lttng2.kernel.core.trace.LttngKernelTrace">
          </tracetype>
       </module>
+      <module
+            analysis_module="org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.module.VirtualMachineCpuAnalysis"
+            automatic="false"
+            id="lttng2.analysis.vm.core.VirtualMachineAnalysisModule"
+            name="Virtual Machine Analysis">
+            <tracetype
+                  applies="true"
+                  class="org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.trace.VirtualMachineExperiment">
+            </tracetype>
+      </module>
    </extension>
 </plugin>
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/VcpuStateValues.java b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/VcpuStateValues.java
new file mode 100644 (file)
index 0000000..445b3b7
--- /dev/null
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ *   Mohamad Gebai - Initial API and implementation
+ *   Geneviève Bastien - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm;
+
+/**
+ * State system values used by the VM analysis
+ *
+ * @author Mohamad Gebai
+ */
+public interface VcpuStateValues {
+
+    /* VCPU Status */
+    /** The virtual CPU state is unknown */
+    int VCPU_UNKNOWN = 0;
+    /** The virtual CPU is idle */
+    int VCPU_IDLE = 1;
+    /** The virtual CPU is running */
+    int VCPU_RUNNING = 2;
+    /** Flag for when the virtual CPU is in hypervisor mode */
+    int VCPU_VMM = 128;
+    /** Flag for when the virtual CPU is preempted */
+    int VCPU_PREEMPT = 256;
+
+}
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/VmAttributes.java b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/VmAttributes.java
new file mode 100644 (file)
index 0000000..6e18a0b
--- /dev/null
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ *   Mohamad Gebai - Initial API and implementation
+ *   Geneviève Bastien - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm;
+
+/**
+ * Attributes used by the VM Analysis
+ *
+ * @author Mohamad Gebai
+ */
+@SuppressWarnings({"nls"})
+public interface VmAttributes {
+
+    /** First-level attributes */
+    String VIRTUAL_MACHINES = "Virtual Machines";
+
+    /** Sub-attributes for virtual CPUs */
+    String STATUS = "Status";
+
+}
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/HostThread.java b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/HostThread.java
new file mode 100644 (file)
index 0000000..fe9c478
--- /dev/null
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ *   Geneviève Bastien - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+
+import com.google.common.hash.HashFunction;
+import com.google.common.hash.Hashing;
+
+/**
+ * This class represents a thread from a specific host. Many machines in an
+ * experiment can have the same thread IDs. This class differentiates the
+ * threads by adding the host ID it belongs to.
+ *
+ * @author Geneviève Bastien
+ */
+public class HostThread {
+
+    private static final HashFunction HF = NonNullUtils.checkNotNull(Hashing.goodFastHash(32));
+
+    private final String fHost;
+    private final Integer fTid;
+
+    /**
+     * Constructor
+     *
+     * @param host
+     *            The host this thread belongs to
+     * @param tid
+     *            The thread ID of this thread
+     */
+    public HostThread(String host, Integer tid) {
+        fHost = host;
+        fTid = tid;
+    }
+
+    @Override
+    public int hashCode() {
+        return HF.newHasher()
+                .putUnencodedChars(fHost)
+                .putInt(fTid).hash().asInt();
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (o instanceof HostThread) {
+            HostThread hostTid = (HostThread) o;
+            if (fTid.equals(hostTid.fTid) &&
+                    fHost.equals(hostTid.fHost)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return "HostTid: [" + fHost + ',' + fTid + ']'; //$NON-NLS-1$
+    }
+
+    /**
+     * Get the thread ID of this thread
+     *
+     * @return The thread ID of this thread
+     */
+    public Integer getTid() {
+        return fTid;
+    }
+
+    /**
+     * Get the host ID of the machine this thread belongs to
+     *
+     * @return The host ID this thread belongs to
+     */
+    public String getHost() {
+        return fHost;
+    }
+
+}
\ No newline at end of file
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/IVirtualMachineModel.java b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/IVirtualMachineModel.java
new file mode 100644 (file)
index 0000000..9b8f19a
--- /dev/null
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ *   Geneviève Bastien - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model;
+
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+
+/**
+ * Interface that represents the model of an hypervisor. Each hypervisor (or
+ * tracing method for an hypervisor) should implement this.
+ *
+ * @author Geneviève Bastien
+ */
+public interface IVirtualMachineModel {
+
+    /**
+     * Get the machine that ran this event
+     *
+     * @param event
+     *            The trace event
+     * @return The machine this event was run on or {@code null} if the machine
+     *         is not one belonging to this model.
+     */
+    @Nullable
+    VirtualMachine getCurrentMachine(ITmfEvent event);
+
+    /**
+     * Get a the set of events required for this model to apply.
+     *
+     * TODO: This should be updated to something else to fit the event layout
+     * generic linux model
+     *
+     * @return The set of required events for this model
+     */
+    Set<String> getRequiredEvents();
+
+    /**
+     * Get the virtual CPU that is entering hypervisor mode with this event.
+     *
+     * "Hypervisor mode" means the virtual CPU of the guest is running on the
+     * host, but it is not running code from the guest, but rather other tasks
+     * from the hypervisor. When hypervisor mode is entered, the process on the
+     * host stops running guest code, so from the guest point of view, the
+     * thread running on this CPU is preempted.
+     *
+     * @param event
+     *            The event being handled
+     * @param ht
+     *            The current thread this event belongs to
+     * @return The virtual CPU entering hypervisor mode or {@code null} if the
+     *         hypervisor is not being entered with this event.
+     */
+    @Nullable
+    VirtualCPU getVCpuEnteringHypervisorMode(ITmfEvent event, HostThread ht);
+
+    /**
+     * Get the virtual CPU that is exiting hypervisor mode with this event.
+     *
+     * "Hypervisor mode" means the virtual CPU of the guest is running on the
+     * host, but it is not running code from the guest, but rather other tasks
+     * from the hypervisor. When hypervisor mode is exited, the process on the
+     * host runs guest code, so from the guest point of view, the thread running
+     * on this CPU is actively running.
+     *
+     * @param event
+     *            The event being handled
+     * @param ht
+     *            The current thread this event belongs to
+     * @return The virutal CPU exiting hypervisor mode or {@code null} if the
+     *         hypervisor is not exiting with this event.
+     */
+    @Nullable
+    VirtualCPU getVCpuExitingHypervisorMode(ITmfEvent event, HostThread ht);
+
+    /**
+     * Get the virtual CPU from a guest that corresponds to a specific thread
+     * from the host
+     *
+     * @param event
+     *            The event being handled
+     * @param ht
+     *            The current thread this event belongs to. This thread should
+     *            be running on the host.
+     * @return The virtual CPU corresponding to this thread or {@code null} if
+     *         no virtual CPU corresponds to the thread
+     */
+    @Nullable
+    VirtualCPU getVirtualCpu(HostThread ht);
+
+    /**
+     * Handles the event. This method will be called for each event required or
+     * optional by the analysis, before any other handling is done on this
+     * event.
+     *
+     * This is where each implementation of the model will build itself,
+     * determine which guests are running on which hosts and get the necessary
+     * information to be able to return the virtual CPUs requested by the other
+     * methods of this interface.
+     *
+     * @param event
+     *            The event being handled. It can come from any trace in the
+     *            experiment
+     */
+    void handleEvent(ITmfEvent event);
+
+}
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/VirtualCPU.java b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/VirtualCPU.java
new file mode 100644 (file)
index 0000000..bb5f974
--- /dev/null
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ *   Geneviève Bastien - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model;
+
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
+
+/**
+ * This class represents a virtual CPU, which is a CPU running on a guest. It
+ * associates the guest CPU ID to a virtual machine of the model.
+ *
+ * @author Geneviève Bastien
+ */
+public class VirtualCPU {
+
+    private static final Table<VirtualMachine, Long, VirtualCPU> VIRTUAL_CPU_TABLE = NonNullUtils.checkNotNull(HashBasedTable.<VirtualMachine, Long, VirtualCPU> create());
+
+    private final VirtualMachine fVm;
+    private final Long fCpuId;
+
+    /**
+     * Return the virtual CPU for to the virtual machine and requested CPU ID
+     *
+     * @param vm
+     *            The virtual machine
+     * @param cpu
+     *            the CPU number
+     * @return the virtual CPU
+     */
+    public static synchronized VirtualCPU getVirtualCPU(VirtualMachine vm, Long cpu) {
+        VirtualCPU ht = VIRTUAL_CPU_TABLE.get(vm, cpu);
+        if (ht == null) {
+            ht = new VirtualCPU(vm, cpu);
+            VIRTUAL_CPU_TABLE.put(vm, cpu, ht);
+        }
+        return ht;
+    }
+
+    private VirtualCPU(VirtualMachine vm, Long cpu) {
+        fVm = vm;
+        fCpuId = cpu;
+    }
+
+    /**
+     * Get the CPU ID of this virtual CPU
+     *
+     * @return The zero-based CPU ID
+     */
+    public Long getCpuId() {
+        return fCpuId;
+    }
+
+    /**
+     * Get the virtual machine object this virtual CPU belongs to
+     *
+     * @return The guest Virtual Machine
+     */
+    public VirtualMachine getVm() {
+        return fVm;
+    }
+
+    @Override
+    public String toString() {
+        return "VirtualCPU: [" + fVm + ',' + fCpuId + ']'; //$NON-NLS-1$
+    }
+
+}
\ No newline at end of file
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/VirtualMachine.java b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/VirtualMachine.java
new file mode 100644 (file)
index 0000000..bf5d54e
--- /dev/null
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ *   Geneviève Bastien - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model;
+
+/**
+ * This class represents a machine, host or guest, in a virtual machine model. A
+ * machine is identified by a trace's host ID.
+ *
+ * @author Geneviève Bastien
+ */
+public class VirtualMachine {
+
+    private static enum MachineType {
+        HOST,
+        GUEST
+    }
+
+    private final long fVmUid;
+    private final String fHostId;
+    private final MachineType fType;
+
+    /**
+     * Create a new host machine. A host is a physical machine that may contain
+     * virtual guest machines.
+     *
+     * @param hostId
+     *            The host ID of the trace(s) this machine represents
+     * @return A {@link VirtualMachine} of type host
+     */
+    public static VirtualMachine newHostMachine(String hostId) {
+        return new VirtualMachine(MachineType.HOST, hostId, -1);
+    }
+
+    /**
+     * Create a new guest machine. A guest is a virtual machine with virtual
+     * CPUs running on a host.
+     *
+     * @param uid
+     *            Some unique identifier of this guest machine that can be used
+     *            in both the guest and the host to match both machines.
+     * @param hostId
+     *            The host ID of the trace(s) this machine represents
+     * @return A {@link VirtualMachine} of type guest.
+     */
+    public static VirtualMachine newGuestMachine(long uid, String hostId) {
+        return new VirtualMachine(MachineType.GUEST, hostId, uid);
+    }
+
+    private VirtualMachine(MachineType type, String hostId, long uid) {
+        fType = type;
+        fVmUid = uid;
+        fHostId = hostId;
+    }
+
+    /**
+     * Return whether this machine is a guest or a host
+     *
+     * @return {@code true} if the machine is a guest, or {@code false} if it is
+     *         a host
+     */
+    public boolean isGuest() {
+        return fType == MachineType.GUEST;
+    }
+
+    /**
+     * Get the unique identifier that is used between the host and the guest to
+     * identify this machine.
+     *
+     * @return The Virtual Machine unique ID.
+     */
+    public long getVmUid() {
+        return fVmUid;
+    }
+
+    /**
+     * Get the host ID of this machine
+     *
+     * @return The host ID of this machine
+     */
+    public String getHostId() {
+        return fHostId;
+    }
+
+    @Override
+    public String toString() {
+        return "VirtualMachine: " + fHostId; //$NON-NLS-1$
+    }
+
+}
\ No newline at end of file
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/package-info.java b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/package-info.java
new file mode 100644 (file)
index 0000000..b30f2be
--- /dev/null
@@ -0,0 +1,14 @@
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ *    École Polytechnique de Montréal - Initial API and implementation
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model;
\ No newline at end of file
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/qemukvm/QemuKvmStrings.java b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/qemukvm/QemuKvmStrings.java
new file mode 100644 (file)
index 0000000..e7adb1d
--- /dev/null
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ *   Mohamad Gebai - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.qemukvm;
+
+/**
+ * Lttng specific strings for the events used by the Qemu/KVM virtual machine
+ * model
+ *
+ * TODO: The whole model should be updated to use the linux event layout. These
+ * event names are LTTng-specific
+ *
+ * @author Mohamad Gebai
+ */
+@SuppressWarnings({ "nls" })
+public interface QemuKvmStrings {
+
+    /* vmsync events */
+
+    /**
+     * Event produced by the host, for a message sent from the guest, received
+     * by the host
+     */
+    String VMSYNC_GH_HOST = "vmsync_gh_host";
+    /**
+     * Event produced by the host, for a message sent from the host, received by
+     * the guest
+     */
+    String VMSYNC_HG_HOST = "vmsync_hg_host";
+    /**
+     * Event produced by the guest, for a message sent from the guest, received
+     * by the host
+     */
+    String VMSYNC_GH_GUEST = "vmsync_gh_guest";
+    /**
+     * Event produced by the guest, for a message sent from the host, received
+     * by the guest
+     */
+    String VMSYNC_HG_GUEST = "vmsync_hg_guest";
+    /**
+     * Event field of previous events, containing a message counter, updated at
+     * each message
+     */
+    String COUNTER_PAYLOAD = "cnt";
+    /**
+     * Event field of previous events, with a unique UID to identify a single
+     * guest on a host
+     */
+    String VM_UID_PAYLOAD = "vm_uid";
+
+    /* kvm entry/exit events */
+    /**
+     * KVM kernel event indicating that virtual machine code is being run
+     */
+    String KVM_ENTRY = "kvm_entry";
+    /**
+     * KVM kernel event indicating that virtual machine code is not run anymore,
+     * but rather hypervisor-specific code
+     */
+    String KVM_EXIT = "kvm_exit";
+    /**
+     * Field from kvm_entry event indicating which virtual CPU is being run
+     */
+    String VCPU_ID = "vcpu_id";
+
+}
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/qemukvm/QemuKvmVmModel.java b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/qemukvm/QemuKvmVmModel.java
new file mode 100644 (file)
index 0000000..7d830d2
--- /dev/null
@@ -0,0 +1,270 @@
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ *   Mohamad Gebai - Initial API and implementation
+ *   Geneviève Bastien - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.qemukvm;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.HostThread;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.IVirtualMachineModel;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.VirtualCPU;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.VirtualMachine;
+import org.eclipse.tracecompass.lttng2.kernel.core.analysis.kernel.LttngKernelAnalysis;
+import org.eclipse.tracecompass.lttng2.kernel.core.analysis.kernel.LttngKernelThreadInformationProvider;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
+import org.eclipse.tracecompass.tmf.core.event.TmfEventField;
+import org.eclipse.tracecompass.tmf.core.event.aspect.TmfCpuAspect;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
+import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
+import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperimentUtils;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * The virtual machine model corresponding to the Qemu/KVM hypervisor. It uses
+ * the kvm_exit/kvm_entry events to identify entry to and exit from the
+ * hypervisor. It also requires vmsync_* events from both guests and hosts to
+ * identify which thread from a host belongs to which machine.
+ *
+ * @author Mohamad Gebai
+ */
+public class QemuKvmVmModel implements IVirtualMachineModel {
+
+    private static final String KVM = "kvm_"; //$NON-NLS-1$
+
+    /* Associate a host's thread to a virtual CPU */
+    private final Map<HostThread, VirtualCPU> fTidToVcpu = new HashMap<>();
+    /* Associate a host's thread to a virtual machine */
+    private final Map<HostThread, VirtualMachine> fTidToVm = new HashMap<>();
+    /* Maps a virtual machine name to a virtual machine */
+    private final Map<String, VirtualMachine> fKnownMachines = new HashMap<>();
+
+    private final TmfExperiment fExperiment;
+
+    static final ImmutableSet<String> REQUIRED_EVENTS = NonNullUtils.checkNotNull(ImmutableSet.of(
+            QemuKvmStrings.KVM_ENTRY,
+            QemuKvmStrings.KVM_EXIT,
+            QemuKvmStrings.VMSYNC_GH_GUEST,
+            QemuKvmStrings.VMSYNC_GH_HOST,
+            QemuKvmStrings.VMSYNC_HG_GUEST,
+            QemuKvmStrings.VMSYNC_HG_HOST
+            ));
+
+    /**
+     * Constructor
+     *
+     * @param exp
+     *            The experiment this model applies to
+     */
+    public QemuKvmVmModel(TmfExperiment exp) {
+        fExperiment = exp;
+    }
+
+    @Override
+    public @Nullable VirtualMachine getCurrentMachine(ITmfEvent event) {
+        final String hostId = event.getTrace().getHostId();
+        VirtualMachine machine = fKnownMachines.get(hostId);
+        if (machine != null) {
+            return machine;
+        }
+
+        /*
+         * TODO: This model wouldn't support a machine (same hostId) being both
+         * a guest and a host
+         */
+
+        /*
+         * This code path would be used only at the beginning of the analysis.
+         * Once all the hostIds have been associated with a virtual machine, the
+         * machines are all cached and the method returns earlier
+         */
+        /* Try to get the virtual machine from the event */
+        String eventName = event.getType().getName();
+        if (eventName.startsWith(KVM)) {
+            /* Only the host machine has kvm_* events, so this is a host */
+            machine = VirtualMachine.newHostMachine(hostId);
+        } else if (eventName.equals(QemuKvmStrings.VMSYNC_GH_GUEST) || eventName.equals(QemuKvmStrings.VMSYNC_HG_GUEST)) {
+            /* Those events are only present in the guests */
+            TmfEventField field = (TmfEventField) event.getContent();
+            ITmfEventField data = field.getField(QemuKvmStrings.VM_UID_PAYLOAD);
+            if (data != null) {
+                machine = VirtualMachine.newGuestMachine((Long) data.getValue(), hostId);
+            }
+        }
+        if (machine != null) {
+            /* Associate the machine to the hostID here, for cached access later */
+            fKnownMachines.put(hostId, machine);
+        }
+        return machine;
+    }
+
+    @Override
+    public Set<String> getRequiredEvents() {
+        return REQUIRED_EVENTS;
+    }
+
+    private @Nullable VirtualMachine findVmFromParent(ITmfEvent event, HostThread ht) {
+        /*
+         * Maybe the parent of the current thread has a VM associated, see if we
+         * can infer the VM for this thread
+         */
+        LttngKernelAnalysis module = getLttngKernelModuleFor(ht.getHost());
+        if (module == null) {
+            return null;
+        }
+
+        Integer ppid = LttngKernelThreadInformationProvider.getParentPid(module, ht.getTid(), event.getTimestamp().getValue());
+        if (ppid == null) {
+            return null;
+        }
+
+        HostThread parentHt = new HostThread(ht.getHost(), ppid);
+        VirtualMachine vm = fTidToVm.get(parentHt);
+        if (vm == null) {
+            return null;
+        }
+        fTidToVm.put(ht, vm);
+
+        return vm;
+    }
+
+    @Override
+    public @Nullable VirtualCPU getVCpuExitingHypervisorMode(ITmfEvent event, HostThread ht) {
+        final String eventName = event.getType().getName();
+
+        /* TODO: Use event layouts for this part also */
+        /*
+         * The KVM_ENTRY event means we are entering a virtual CPU, so exiting
+         * hypervisor mode
+         */
+        if (!eventName.equals(QemuKvmStrings.KVM_ENTRY)) {
+            return null;
+        }
+
+        /*
+         * Are we entering the hypervisor and if so, which virtual CPU is
+         * concerned?
+         */
+        VirtualMachine vm = fTidToVm.get(ht);
+        if (vm == null) {
+            vm = findVmFromParent(event, ht);
+            if (vm == null) {
+                return null;
+            }
+        }
+        /* Associate this thread with the virtual CPU that is going to be run */
+        final ITmfEventField content = event.getContent();
+        long vcpu_id = (Long) content.getField(QemuKvmStrings.VCPU_ID).getValue();
+
+        VirtualCPU virtualCPU = VirtualCPU.getVirtualCPU(vm, vcpu_id);
+        fTidToVcpu.put(ht, virtualCPU);
+
+        return virtualCPU;
+    }
+
+    @Override
+    public @Nullable VirtualCPU getVCpuEnteringHypervisorMode(ITmfEvent event, HostThread ht) {
+        final String eventName = event.getType().getName();
+        /*
+         * The KVM_EXIT event means we are exiting a virtual CPU, so entering
+         * hypervisor mode
+         */
+        if (!eventName.equals(QemuKvmStrings.KVM_EXIT)) {
+            return null;
+        }
+
+        return getVirtualCpu(ht);
+    }
+
+    @Override
+    public @Nullable VirtualCPU getVirtualCpu(HostThread ht) {
+        return fTidToVcpu.get(ht);
+    }
+
+    @Override
+    public void handleEvent(ITmfEvent event) {
+        /* Is the event handled by this model */
+        final String eventName = event.getType().getName();
+        if (!eventName.equals(QemuKvmStrings.VMSYNC_GH_HOST)) {
+            return;
+        }
+
+        final ITmfEventField content = event.getContent();
+        final long ts = event.getTimestamp().getValue();
+        final String hostId = event.getTrace().getHostId();
+
+        Integer cpu = null;
+        Iterable<TmfCpuAspect> aspects = TmfTraceUtils.getEventAspectsOfClass(event.getTrace(), TmfCpuAspect.class);
+        for (TmfCpuAspect aspect : aspects) {
+            Integer thisCpu = aspect.resolve(event);
+            if (!thisCpu.equals(TmfCpuAspect.CPU_UNAVAILABLE)) {
+                cpu = thisCpu;
+                break;
+            }
+        }
+        if (cpu == null) {
+            /* We couldn't find any CPU information, ignore this event */
+            return;
+        }
+
+        /* Find a virtual machine with the vm uid payload value */
+        ITmfEventField data = content.getField(QemuKvmStrings.VM_UID_PAYLOAD);
+        if (data == null) {
+            return;
+        }
+        long vmUid = (Long) data.getValue();
+        for (Entry<String, VirtualMachine> entry : fKnownMachines.entrySet()) {
+            if (entry.getValue().getVmUid() == vmUid) {
+                /*
+                 * We found the VM being run, let's associate it with the thread
+                 * ID
+                 */
+                LttngKernelAnalysis module = getLttngKernelModuleFor(hostId);
+                if (module == null) {
+                    break;
+                }
+                Integer tid = LttngKernelThreadInformationProvider.getThreadOnCpu(module, cpu, ts);
+                if (tid == null) {
+                    /*
+                     * We do not know which process is running at this point. It
+                     * may happen at the beginning of the trace.
+                     */
+                    break;
+                }
+                HostThread ht = new HostThread(hostId, tid);
+                fTidToVm.put(ht, entry.getValue());
+
+                /*
+                 * To make sure siblings are also associated with this VM, also
+                 * add an entry for the parent TID
+                 */
+                Integer ppid = LttngKernelThreadInformationProvider.getParentPid(module, tid, ts);
+                if (ppid != null) {
+                    HostThread parentHt = new HostThread(hostId, ppid);
+                    fTidToVm.put(parentHt, entry.getValue());
+                }
+            }
+        }
+    }
+
+    private @Nullable LttngKernelAnalysis getLttngKernelModuleFor(String hostId) {
+        return TmfExperimentUtils.getAnalysisModuleOfClassForHost(fExperiment, hostId, LttngKernelAnalysis.class);
+    }
+
+}
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/qemukvm/package-info.java b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/model/qemukvm/package-info.java
new file mode 100644 (file)
index 0000000..7f6debb
--- /dev/null
@@ -0,0 +1,14 @@
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ *    École Polytechnique de Montréal - Initial API and implementation
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.qemukvm;
\ No newline at end of file
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/module/Messages.java b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/module/Messages.java
new file mode 100644 (file)
index 0000000..b68f7b5
--- /dev/null
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ *   Geneviève Bastien - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.module;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Externalized message strings from the LTTng Kernel Analysis
+ *
+ * @author Geneviève Bastien
+ */
+@SuppressWarnings("javadoc")
+public class Messages extends NLS {
+    private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.module.messages"; //$NON-NLS-1$
+
+    public static @Nullable String VirtualMachineCPUAnalysis_Help;
+
+    static {
+        // initialize resource bundle
+        NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+    }
+
+    private Messages() {
+    }
+
+    /**
+     * Helper method to expose externalized strings as non-null objects.
+     */
+    public static String getMessage(@Nullable String msg) {
+        if (msg == null) {
+            return ""; //$NON-NLS-1$
+        }
+        return msg;
+    }
+}
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/module/VirtualMachineCpuAnalysis.java b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/module/VirtualMachineCpuAnalysis.java
new file mode 100644 (file)
index 0000000..65f85b3
--- /dev/null
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ *   Mohamad Gebai - Initial API and implementation
+ *   Geneviève Bastien - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.module;
+
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.VcpuStateValues;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.VmAttributes;
+import org.eclipse.tracecompass.lttng2.kernel.core.analysis.kernel.LttngKernelAnalysis;
+import org.eclipse.tracecompass.lttng2.kernel.core.analysis.kernel.LttngKernelThreadInformationProvider;
+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.interval.ITmfStateInterval;
+import org.eclipse.tracecompass.statesystem.core.interval.TmfStateInterval;
+import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
+import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
+import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
+import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
+import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
+import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperimentUtils;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.TreeMultimap;
+
+/**
+ * Module for the virtual machine CPU analysis. It tracks the status of the
+ * virtual CPUs for each guest of the experiment.
+ *
+ * @author Mohamad Gebai
+ * @author Geneviève Bastien
+ */
+public class VirtualMachineCpuAnalysis extends TmfStateSystemAnalysisModule {
+
+    // TODO: Update with event layout when requirements are back */
+    static final Set<String> REQUIRED_EVENTS = NonNullUtils.checkNotNull(ImmutableSet.<String> of(
+            // LttngStrings.SCHED_SWITCH
+            ));
+
+    /* State value for a preempted virtual CPU */
+    private static final ITmfStateValue VCPU_PREEMPT_VALUE = TmfStateValue.newValueInt(VcpuStateValues.VCPU_PREEMPT);
+
+    /**
+     * Constructor
+     */
+    public VirtualMachineCpuAnalysis() {
+        super();
+    }
+
+    @Override
+    protected ITmfStateProvider createStateProvider() {
+        ITmfTrace trace = getTrace();
+        if (!(trace instanceof TmfExperiment)) {
+            throw new IllegalStateException();
+        }
+        return new VirtualMachineStateProvider((TmfExperiment) trace);
+    }
+
+    @Override
+    protected @NonNull StateSystemBackendType getBackendType() {
+        return StateSystemBackendType.FULL;
+    }
+
+    @Override
+    public String getHelpText() {
+        return Messages.getMessage(Messages.VirtualMachineCPUAnalysis_Help);
+    }
+
+    @Override
+    protected Iterable<IAnalysisModule> getDependentAnalyses() {
+        Set<IAnalysisModule> modules = new HashSet<>();
+        /* Depends on the LTTng Kernel analysis modules */
+        for (ITmfTrace trace : TmfTraceManager.getTraceSet(getTrace())) {
+            for (LttngKernelAnalysis module : TmfTraceUtils.getAnalysisModulesOfClass(trace, LttngKernelAnalysis.class)) {
+                modules.add(module);
+            }
+        }
+        return modules;
+    }
+
+    private static Multimap<Integer, ITmfStateInterval> createThreadMultimap() {
+
+        /*
+         * Create the multimap for threads with the appropriate comparator
+         * objects for keys and values
+         */
+        final Multimap<Integer, ITmfStateInterval> map = NonNullUtils.checkNotNull(TreeMultimap.<Integer, ITmfStateInterval> create(
+                new Comparator<Integer>() {
+                    @Override
+                    public int compare(@Nullable Integer arg0, @Nullable Integer arg1) {
+                        /*
+                         * Keys do not have to be sorted, just use natural
+                         * sorting
+                         */
+                        if (arg0 == null || arg1 == null) {
+                            return -1;
+                        }
+                        return arg0.compareTo(arg1);
+                    }
+                }, new Comparator<ITmfStateInterval>() {
+                    @Override
+                    public int compare(@Nullable ITmfStateInterval arg0, @Nullable ITmfStateInterval arg1) {
+                        if (arg0 == null || arg1 == null) {
+                            return 0;
+                        }
+                        if (arg1.getStateValue() == VCPU_PREEMPT_VALUE && arg0.getStateValue() != VCPU_PREEMPT_VALUE) {
+                            /*
+                             * For VCPU_PREEMPT state values, the state has to
+                             * be after any other state that it overlaps,
+                             * because those intervals usually decorate the
+                             * other intervals.
+                             */
+                            if (((Long) arg0.getEndTime()).compareTo(arg1.getStartTime()) < 0) {
+                                return -1;
+                            }
+                            return ((Long) arg0.getStartTime()).compareTo(arg1.getEndTime());
+                        }
+                        /* Otherwise, we use ordering by start time */
+                        return (((Long) arg0.getStartTime()).compareTo(arg1.getStartTime()));
+                    }
+                }));
+        return map;
+    }
+
+    /**
+     * Get the status intervals for the threads from a virtual machine. Those
+     * intervals are correlated with the data from the virtual CPU's preemption
+     * status.
+     *
+     * This method uses the Linux Kernel Analysis data for the thread's status
+     * intervals.
+     *
+     * @param vmQuark
+     *            The quark of the virtual machine
+     * @param start
+     *            The start time of the period to get the intervals from
+     * @param end
+     *            The end time of the period to get the intervals from
+     * @param resolution
+     *            The resolution
+     * @param monitor
+     *            A progress monitor for this task
+     * @return A map of status intervals for the machine's threads, including
+     *         preempted intervals. Intervals from the thread status and the CPU
+     *         preemption status overlap and are ordered such that CPU
+     *         preemption intervals are after any interval they overlap with
+     */
+    public Multimap<Integer, ITmfStateInterval> getUpdatedThreadIntervals(int vmQuark, long start, long end, long resolution, IProgressMonitor monitor) {
+
+        final Multimap<Integer, ITmfStateInterval> map = createThreadMultimap();
+
+        ITmfStateSystem ss = getStateSystem();
+        if (ss == null) {
+            return map;
+        }
+        ITmfTrace trace = getTrace();
+        if (!(trace instanceof TmfExperiment)) {
+            return map;
+        }
+
+        String vmHostId = NonNullUtils.checkNotNull(ss.getAttributeName(vmQuark));
+        LttngKernelAnalysis kernelModule = TmfExperimentUtils.getAnalysisModuleOfClassForHost((TmfExperiment) trace, vmHostId, LttngKernelAnalysis.class);
+        if (kernelModule == null) {
+            return map;
+        }
+
+        /*
+         * Initialize the map with the original status intervals from the kernel
+         * module
+         */
+        for (Integer tid : LttngKernelThreadInformationProvider.getThreadIds(kernelModule)) {
+            if (tid == null) {
+                throw new IllegalStateException();
+            }
+            map.putAll(tid, LttngKernelThreadInformationProvider.getStatusIntervalsForThread(kernelModule, tid, start, end, resolution, monitor));
+            if (monitor.isCanceled()) {
+                return map;
+            }
+        }
+
+        try {
+            /* Correlate thread information with virtual CPU information */
+            for (Integer vcpuQuark : ss.getSubAttributes(vmQuark, false)) {
+                Long virtualCPU = Long.parseLong(ss.getAttributeName(vcpuQuark));
+                Integer statusQuark = ss.getQuarkRelative(vcpuQuark, VmAttributes.STATUS);
+
+                for (ITmfStateInterval cpuInterval : StateSystemUtils.queryHistoryRange(ss, statusQuark, start, end - 1, resolution, monitor)) {
+                    ITmfStateValue stateValue = cpuInterval.getStateValue();
+                    switch (stateValue.getType()) {
+                    case INTEGER:
+                        int value = stateValue.unboxInt();
+                        /*
+                         * If the current CPU is either preempted or in
+                         * hypervisor mode, add preempted intervals to running
+                         * processes
+                         */
+                        if ((value & (VcpuStateValues.VCPU_PREEMPT | VcpuStateValues.VCPU_VMM)) == 0) {
+                            break;
+                        }
+                        Integer threadOnCpu = LttngKernelThreadInformationProvider.getThreadOnCpu(kernelModule, virtualCPU, cpuInterval.getStartTime());
+                        if (threadOnCpu != null) {
+                            map.put(threadOnCpu, new TmfStateInterval(cpuInterval.getStartTime(), cpuInterval.getEndTime(), threadOnCpu, VCPU_PREEMPT_VALUE));
+                        }
+                        break;
+                    case DOUBLE:
+                    case LONG:
+                    case NULL:
+                    case STRING:
+                    default:
+                        break;
+                    }
+
+                }
+            }
+        } catch (AttributeNotFoundException | StateSystemDisposedException e) {
+        }
+        return NonNullUtils.checkNotNull(map);
+    }
+
+}
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/module/VirtualMachineStateProvider.java b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/module/VirtualMachineStateProvider.java
new file mode 100644 (file)
index 0000000..259ffd8
--- /dev/null
@@ -0,0 +1,380 @@
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ *   Mohamad Gebai - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.module;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.Activator;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.VcpuStateValues;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.VmAttributes;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.HostThread;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.IVirtualMachineModel;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.VirtualCPU;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.VirtualMachine;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.qemukvm.QemuKvmVmModel;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.trace.layout.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.internal.lttng2.kernel.core.trace.layout.LttngEventLayout;
+import org.eclipse.tracecompass.lttng2.kernel.core.analysis.kernel.LttngKernelAnalysis;
+import org.eclipse.tracecompass.lttng2.kernel.core.analysis.kernel.LttngKernelThreadInformationProvider;
+import org.eclipse.tracecompass.lttng2.kernel.core.trace.LttngKernelTrace;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
+import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
+import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
+import org.eclipse.tracecompass.tmf.core.event.aspect.TmfCpuAspect;
+import org.eclipse.tracecompass.tmf.core.statesystem.AbstractTmfStateProvider;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
+import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
+import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperimentUtils;
+
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
+
+/**
+ * This is the state provider which translates the virtual machine experiment
+ * events to a state system.
+ *
+ * Attribute tree:
+ *
+ * <pre>
+ * |- Virtual Machines
+ * |  |- <Guest Host ID> -> Friendly name (trace name)
+ * |  |  |- <VCPU number>
+ * |  |  |  |- Status -> <Status value>
+ * </pre>
+ *
+ * The status value of the VCPUs are either {@link VcpuStateValues#VCPU_IDLE},
+ * {@link VcpuStateValues#VCPU_UNKNOWN} or {@link VcpuStateValues#VCPU_RUNNING}.
+ * Those three values are ORed with flags {@link VcpuStateValues#VCPU_VMM}
+ * and/or {@link VcpuStateValues#VCPU_PREEMPT} to indicate respectively whether
+ * they are in hypervisor mode or preempted on the host.
+ *
+ * @author Mohamad Gebai
+ */
+public class VirtualMachineStateProvider extends AbstractTmfStateProvider {
+
+    /**
+     * Version number of this state provider. Please bump this if you modify the
+     * contents of the generated state history in some way.
+     */
+    private static final int VERSION = 1;
+
+    private static final int SCHED_SWITCH_INDEX = 0;
+
+    /* TODO: An analysis should support many hypervisor models */
+    private IVirtualMachineModel fModel;
+    private final Table<ITmfTrace, String, Integer> fEventNames;
+    private final Map<ITmfTrace, IKernelAnalysisEventLayout> fLayouts;
+
+    // ------------------------------------------------------------------------
+    // Constructor
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructor
+     *
+     * @param experiment
+     *            The virtual machine experiment
+     */
+    public VirtualMachineStateProvider(TmfExperiment experiment) {
+        super(experiment, ITmfEvent.class, "Virtual Machine State Provider"); //$NON-NLS-1$
+
+        fModel = new QemuKvmVmModel(experiment);
+        Table<ITmfTrace, String, Integer> table = NonNullUtils.checkNotNull(HashBasedTable.<ITmfTrace, String, Integer> create());
+        fEventNames = table;
+        fLayouts = new HashMap<>();
+    }
+
+    // ------------------------------------------------------------------------
+    // Event names management
+    // ------------------------------------------------------------------------
+
+    private void buildEventNames(ITmfTrace trace) {
+        IKernelAnalysisEventLayout layout;
+        if (trace instanceof LttngKernelTrace) {
+            layout = ((LttngKernelTrace) trace).getEventLayout();
+        } else {
+            /* Fall-back to the base LttngEventLayout */
+            layout = LttngEventLayout.getInstance();
+        }
+        fLayouts.put(trace, layout);
+        fEventNames.put(trace, layout.eventSchedSwitch(), SCHED_SWITCH_INDEX);
+    }
+
+    // ------------------------------------------------------------------------
+    // IStateChangeInput
+    // ------------------------------------------------------------------------
+
+    @Override
+    public TmfExperiment getTrace() {
+        ITmfTrace trace = super.getTrace();
+        if (trace instanceof TmfExperiment) {
+            return (TmfExperiment) trace;
+        }
+        throw new IllegalStateException("VirtualMachineStateProvider: The associated trace should be an experiment"); //$NON-NLS-1$
+    }
+
+    @Override
+    public int getVersion() {
+        return VERSION;
+    }
+
+    @Override
+    public VirtualMachineStateProvider getNewInstance() {
+        TmfExperiment trace = getTrace();
+        return new VirtualMachineStateProvider(trace);
+    }
+
+    @Override
+    protected void eventHandle(@Nullable ITmfEvent event) {
+        if (event == null) {
+            return;
+        }
+
+        /* Is the event managed by this analysis */
+        final String eventName = event.getType().getName();
+
+        /* TODO When requirements work again, don't hardcode this */
+        if (!eventName.equals("sched_switch") && //$NON-NLS-1$
+                !fModel.getRequiredEvents().contains(eventName)) {
+            return;
+        }
+
+        ITmfStateValue value;
+
+        final ITmfEventField content = event.getContent();
+        final long ts = event.getTimestamp().getValue();
+        final String hostId = event.getTrace().getHostId();
+        try {
+            /* Do we know this trace's role yet? */
+            VirtualMachine host = fModel.getCurrentMachine(event);
+            if (host == null) {
+                return;
+            }
+
+            /* Make sure guest traces are added to the state system */
+            if (host.isGuest()) {
+                /*
+                 * If event from a guest OS, make sure the guest exists in the
+                 * state system
+                 */
+                int vmQuark = -1;
+                try {
+                    vmQuark = ss.getQuarkRelative(getNodeVirtualMachines(), host.getHostId());
+                } catch (AttributeNotFoundException e) {
+                    /*
+                     * We should enter this catch only once per machine, so it
+                     * is not so costly to do compared with adding the trace's
+                     * name for each guest event
+                     */
+                    vmQuark = ss.getQuarkRelativeAndAdd(getNodeVirtualMachines(), host.getHostId());
+                    TmfStateValue machineName = TmfStateValue.newValueString(event.getTrace().getName());
+                    ss.modifyAttribute(ts, machineName, vmQuark);
+                }
+            }
+
+            /* Have the hypervisor models handle the event first */
+            fModel.handleEvent(event);
+
+            /* Handle the event here */
+            if (!fEventNames.containsRow(event.getTrace())) {
+                buildEventNames(event.getTrace());
+            }
+            Integer idx = fEventNames.get(event.getTrace(), eventName);
+            int intval = (idx == null ? -1 : idx.intValue());
+            switch (intval) {
+            case SCHED_SWITCH_INDEX: // "sched_switch":
+            /*
+             * Fields: string prev_comm, int32 prev_tid, int32 prev_prio, int64
+             * prev_state, string next_comm, int32 next_tid, int32 next_prio
+             */
+            {
+                Integer prevTid = ((Long) content.getField(fLayouts.get(event.getTrace()).fieldPrevTid()).getValue()).intValue();
+                Integer nextTid = ((Long) content.getField(fLayouts.get(event.getTrace()).fieldNextTid()).getValue()).intValue();
+
+                if (prevTid == null || nextTid == null) {
+                    break;
+                }
+
+                if (host.isGuest()) {
+                    /* Get the event's CPU */
+                    Integer cpu = null;
+                    Iterable<TmfCpuAspect> aspects = TmfTraceUtils.getEventAspectsOfClass(event.getTrace(), TmfCpuAspect.class);
+                    for (TmfCpuAspect aspect : aspects) {
+                        if (!aspect.resolve(event).equals(TmfCpuAspect.CPU_UNAVAILABLE)) {
+                            cpu = aspect.resolve(event);
+                            break;
+                        }
+                    }
+                    if (cpu == null) {
+                        /*
+                         * We couldn't find any CPU information, ignore this
+                         * event
+                         */
+                        break;
+                    }
+
+                    /*
+                     * If sched switch is from a guest, just update the status
+                     * of the virtual CPU to either idle or running
+                     */
+                    int curStatusQuark = ss.getQuarkRelativeAndAdd(getNodeVirtualMachines(), host.getHostId(),
+                            cpu.toString(), VmAttributes.STATUS);
+                    value = TmfStateValue.newValueInt(VcpuStateValues.VCPU_IDLE);
+                    if (nextTid > 0) {
+                        value = TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING);
+                    }
+                    ss.modifyAttribute(ts, value, curStatusQuark);
+                    break;
+                }
+
+                /* Event is not from a guest */
+                /* Verify if the previous thread corresponds to a virtual CPU */
+                HostThread ht = new HostThread(hostId, prevTid);
+                VirtualCPU vcpu = fModel.getVirtualCpu(ht);
+
+                /*
+                 * If previous thread is virtual CPU, update status of the
+                 * virtual CPU to preempted
+                 */
+                if (vcpu != null) {
+                    VirtualMachine vm = vcpu.getVm();
+
+                    int curStatusQuark = ss.getQuarkRelativeAndAdd(getNodeVirtualMachines(), vm.getHostId(),
+                            vcpu.getCpuId().toString(), VmAttributes.STATUS);
+
+                    /* Add the preempted flag to the status */
+                    value = ss.queryOngoingState(curStatusQuark);
+                    int newVal = Math.max(VcpuStateValues.VCPU_UNKNOWN, value.unboxInt());
+                    value = TmfStateValue.newValueInt(newVal | VcpuStateValues.VCPU_PREEMPT);
+                    ss.modifyAttribute(ts, value, curStatusQuark);
+                }
+
+                /* Verify if the next thread corresponds to a virtual CPU */
+                ht = new HostThread(hostId, nextTid);
+                vcpu = fModel.getVirtualCpu(ht);
+
+                /*
+                 * If next thread is virtual CPU, update status of the virtual
+                 * CPU the previous status
+                 */
+                if (vcpu != null) {
+                    VirtualMachine vm = vcpu.getVm();
+                    int curStatusQuark = ss.getQuarkRelativeAndAdd(getNodeVirtualMachines(), vm.getHostId(),
+                            vcpu.getCpuId().toString(), VmAttributes.STATUS);
+
+                    /* Remove the preempted flag from the status */
+                    value = ss.queryOngoingState(curStatusQuark);
+                    int newVal = Math.max(VcpuStateValues.VCPU_UNKNOWN, value.unboxInt());
+                    value = TmfStateValue.newValueInt(newVal & ~VcpuStateValues.VCPU_PREEMPT);
+                    ss.modifyAttribute(ts, value, curStatusQuark);
+
+                }
+
+            }
+                break;
+
+            default:
+            /* Other events not covered by the main switch */
+            {
+                HostThread ht = getCurrentHostThread(event, ts);
+                if (ht == null) {
+                    break;
+                }
+
+                /*
+                 * Are we entering the hypervisor mode and if so, which virtual
+                 * CPU is concerned?
+                 */
+                VirtualCPU virtualCpu = fModel.getVCpuEnteringHypervisorMode(event, ht);
+                if (virtualCpu != null) {
+                    /* Add the hypervisor flag to the status */
+                    VirtualMachine vm = virtualCpu.getVm();
+                    int curStatusQuark = ss.getQuarkRelativeAndAdd(getNodeVirtualMachines(), vm.getHostId(),
+                            Long.toString(virtualCpu.getCpuId()), VmAttributes.STATUS);
+                    value = ss.queryOngoingState(curStatusQuark);
+                    int newVal = Math.max(VcpuStateValues.VCPU_UNKNOWN, value.unboxInt());
+                    value = TmfStateValue.newValueInt(newVal | VcpuStateValues.VCPU_VMM);
+                    ss.modifyAttribute(ts, value, curStatusQuark);
+                }
+
+                /*
+                 * Are we exiting the hypervisor mode and if so, which virtual
+                 * CPU is concerned?
+                 */
+                virtualCpu = fModel.getVCpuExitingHypervisorMode(event, ht);
+                if (virtualCpu != null) {
+                    /* Remove the hypervisor flag from the status */
+                    VirtualMachine vm = virtualCpu.getVm();
+                    int curStatusQuark = ss.getQuarkRelativeAndAdd(getNodeVirtualMachines(), vm.getHostId(),
+                            Long.toString(virtualCpu.getCpuId()), VmAttributes.STATUS);
+                    value = ss.queryOngoingState(curStatusQuark);
+                    int newVal = Math.max(VcpuStateValues.VCPU_UNKNOWN, value.unboxInt());
+                    value = TmfStateValue.newValueInt(newVal & ~VcpuStateValues.VCPU_VMM);
+                    ss.modifyAttribute(ts, value, curStatusQuark);
+                }
+
+            }
+                break;
+            }
+
+        } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
+            Activator.getDefault().logError("Error handling event in VirtualMachineStateProvider", e); //$NON-NLS-1$
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Convenience methods for commonly-used attribute tree locations
+    // ------------------------------------------------------------------------
+
+    private int getNodeVirtualMachines() {
+        return ss.getQuarkAbsoluteAndAdd(VmAttributes.VIRTUAL_MACHINES);
+    }
+
+    private @Nullable HostThread getCurrentHostThread(ITmfEvent event, long ts) {
+        /* Get the LTTng kernel analysis for the host */
+        String hostId = event.getTrace().getHostId();
+        LttngKernelAnalysis module = TmfExperimentUtils.getAnalysisModuleOfClassForHost(getTrace(), hostId, LttngKernelAnalysis.class);
+        if (module == null) {
+            return null;
+        }
+
+        /* Get the CPU the event is running on */
+        Integer cpu = null;
+        Iterable<TmfCpuAspect> aspects = TmfTraceUtils.getEventAspectsOfClass(event.getTrace(), TmfCpuAspect.class);
+        for (TmfCpuAspect aspect : aspects) {
+            if (!aspect.resolve(event).equals(TmfCpuAspect.CPU_UNAVAILABLE)) {
+                cpu = aspect.resolve(event);
+                break;
+            }
+        }
+        if (cpu == null) {
+            /* We couldn't find any CPU information, ignore this event */
+            return null;
+        }
+
+        Integer currentTid = LttngKernelThreadInformationProvider.getThreadOnCpu(module, cpu, ts);
+        if (currentTid == null) {
+            return null;
+        }
+        return new HostThread(hostId, currentTid);
+    }
+
+}
\ No newline at end of file
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/module/messages.properties b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/module/messages.properties
new file mode 100644 (file)
index 0000000..7f89d62
--- /dev/null
@@ -0,0 +1,13 @@
+###############################################################################
+# Copyright (c) 2014 É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
+#
+# Contributors:
+#     Geneviève Bastien - Initial API and implementation
+###############################################################################
+
+VirtualMachineCPUAnalysis_Help=Tracks the state of the virtual CPUs of the guest virtual machine in an experiment. It also interrelate the CPU information with the information from thread status of each guest.
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/module/package-info.java b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/module/package-info.java
new file mode 100644 (file)
index 0000000..ef9c73e
--- /dev/null
@@ -0,0 +1,14 @@
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ *    École Polytechnique de Montréal - Initial API and implementation
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.module;
\ No newline at end of file
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/package-info.java b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/package-info.java
new file mode 100644 (file)
index 0000000..2efb6c7
--- /dev/null
@@ -0,0 +1,14 @@
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ *    École Polytechnique de Montréal - Initial API and implementation
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm;
\ No newline at end of file
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/trace/VirtualMachineExperiment.java b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/trace/VirtualMachineExperiment.java
new file mode 100644 (file)
index 0000000..d6816f7
--- /dev/null
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ *   Mohamad Gebai - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.trace;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
+import org.eclipse.tracecompass.tmf.ctf.core.event.CtfTmfEvent;
+
+/**
+ * Experiment class containing traces from physical machine and the virtual
+ * guests running on them.
+ *
+ * @author Mohamad Gebai
+ */
+public class VirtualMachineExperiment extends TmfExperiment {
+
+    /**
+     * Default constructor. Needed by the extension point.
+     */
+    @SuppressWarnings("null")
+    public VirtualMachineExperiment() {
+        this("default", Collections.EMPTY_SET); //$NON-NLS-1$
+    }
+
+    /**
+     * Constructor with traces and id
+     *
+     * @param id
+     *            The ID of this experiment
+     * @param traces
+     *            The set of traces that are part of this experiment
+     */
+    public VirtualMachineExperiment(String id, Set<ITmfTrace> traces) {
+        super(CtfTmfEvent.class, id, traces.toArray(new ITmfTrace[traces.size()]), TmfExperiment.DEFAULT_INDEX_PAGE_SIZE, null);
+    }
+
+}
diff --git a/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/trace/package-info.java b/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/vm/trace/package-info.java
new file mode 100644 (file)
index 0000000..0bcb5e3
--- /dev/null
@@ -0,0 +1,14 @@
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ *    École Polytechnique de Montréal - Initial API and implementation
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.trace;
\ No newline at end of file
index 8f3ea2d3a975764776596ef3fb857ad3a359f2ac..4471a3be7819fb15afbdb677bff2b373e830d8ea 100644 (file)
@@ -56,22 +56,22 @@ public class LttngKernelAnalysis extends TmfStateSystemAnalysisModule {
     private static final ImmutableSet<String> OPTIONAL_EVENTS = ImmutableSet.of(
             // FIXME These cannot be declared statically anymore, they depend on
             // the OriginTracer of the kernel trace.
-//            LttngStrings.EXIT_SYSCALL,
-//            LttngStrings.IRQ_HANDLER_ENTRY,
-//            LttngStrings.IRQ_HANDLER_EXIT,
-//            LttngStrings.SOFTIRQ_ENTRY,
-//            LttngStrings.SOFTIRQ_EXIT,
-//            LttngStrings.SOFTIRQ_RAISE,
-//            LttngStrings.SCHED_PROCESS_FORK,
-//            LttngStrings.SCHED_PROCESS_EXIT,
-//            LttngStrings.SCHED_PROCESS_FREE,
-//            LttngStrings.SCHED_SWITCH,
-//            LttngStrings.STATEDUMP_PROCESS_STATE,
-//            LttngStrings.SCHED_WAKEUP,
-//            LttngStrings.SCHED_WAKEUP_NEW,
-//
-//            /* FIXME Add the prefix for syscalls */
-//            LttngStrings.SYSCALL_PREFIX
+            // LttngStrings.EXIT_SYSCALL,
+            // LttngStrings.IRQ_HANDLER_ENTRY,
+            // LttngStrings.IRQ_HANDLER_EXIT,
+            // LttngStrings.SOFTIRQ_ENTRY,
+            // LttngStrings.SOFTIRQ_EXIT,
+            // LttngStrings.SOFTIRQ_RAISE,
+            // LttngStrings.SCHED_PROCESS_FORK,
+            // LttngStrings.SCHED_PROCESS_EXIT,
+            // LttngStrings.SCHED_PROCESS_FREE,
+            // LttngStrings.SCHED_SWITCH,
+            // LttngStrings.STATEDUMP_PROCESS_STATE,
+            // LttngStrings.SCHED_WAKEUP,
+            // LttngStrings.SCHED_WAKEUP_NEW,
+            //
+            // /* FIXME Add the prefix for syscalls */
+            // LttngStrings.SYSCALL_PREFIX
             );
 
     /** The requirements as an immutable set */
This page took 0.046403 seconds and 5 git commands to generate.