blob: ba1481417e1c62fddc8682d12b8be47661edd99e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 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 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Mohamad Gebai - Initial API and implementation
*******************************************************************************/
package org.eclipse.tracecompass.incubator.internal.virtual.machine.analysis.core.virtual.resources;
import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.analysis.os.linux.core.trace.DefaultEventLayout;
import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
import org.eclipse.tracecompass.incubator.internal.virtual.machine.analysis.core.IVirtualMachineEventHandler;
import org.eclipse.tracecompass.incubator.internal.virtual.machine.analysis.core.data.VcpuStateValues;
import org.eclipse.tracecompass.incubator.internal.virtual.machine.analysis.core.model.IVirtualEnvironmentModel;
import org.eclipse.tracecompass.incubator.internal.virtual.machine.analysis.core.virtual.resources.handlers.QemuKvmEventHandler;
import org.eclipse.tracecompass.incubator.internal.virtual.machine.analysis.core.virtual.resources.handlers.SchedSwitchEventHandler;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.statesystem.AbstractTmfStateProvider;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
/**
* 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 VirtualResourcesStateProvider 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 final IVirtualEnvironmentModel fModel;
private final Multimap<String, IVirtualMachineEventHandler> fEventNames = HashMultimap.create();
private final Collection<IVirtualMachineEventHandler> fHandlers;
private final Map<ITmfTrace, IKernelAnalysisEventLayout> fLayouts;
// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
/**
* Constructor
*
* @param experiment
* The virtual machine experiment
* @param model
* The virtual environment model
*/
public VirtualResourcesStateProvider(TmfExperiment experiment, IVirtualEnvironmentModel model) {
super(experiment, "Virtual Machine State Provider"); //$NON-NLS-1$
fModel = model;
fLayouts = new HashMap<>();
fHandlers = ImmutableSet.of(new SchedSwitchEventHandler(), new QemuKvmEventHandler());
}
// ------------------------------------------------------------------------
// Event names management
// ------------------------------------------------------------------------
private void buildEventNames(ITmfTrace trace) {
IKernelAnalysisEventLayout layout;
if (trace instanceof IKernelTrace) {
layout = ((IKernelTrace) trace).getKernelEventLayout();
} else {
/* Fall-back to the base LttngEventLayout */
layout = DefaultEventLayout.getInstance();
}
fLayouts.put(trace, layout);
fHandlers.forEach(handler -> {
handler.getRequiredEvents(layout).forEach(event -> {
fEventNames.put(event, handler);
});
});
}
// ------------------------------------------------------------------------
// 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 VirtualResourcesStateProvider getNewInstance() {
TmfExperiment trace = getTrace();
return new VirtualResourcesStateProvider(trace, fModel);
}
@Override
protected void eventHandle(@Nullable ITmfEvent event) {
if (event == null) {
return;
}
/* Is the event managed by this analysis */
final String eventName = event.getName();
IKernelAnalysisEventLayout eventLayout = fLayouts.get(event.getTrace());
if (eventLayout == null) {
buildEventNames(event.getTrace());
eventLayout = fLayouts.get(event.getTrace());
if (eventLayout == null) {
return;
}
}
ITmfStateSystemBuilder ss = checkNotNull(getStateSystemBuilder());
Collection<IVirtualMachineEventHandler> handlers = fEventNames.get(eventName);
if (handlers.isEmpty()) {
return;
}
IVirtualEnvironmentModel virtEnv = fModel;
for (IVirtualMachineEventHandler handler : handlers) {
handler.handleEvent(ss, event, virtEnv, eventLayout);
}
}
}