org.eclipse.tracecompass.common.core,
org.eclipse.tracecompass.tmf.core,
org.eclipse.tracecompass.segmentstore.core,
- org.eclipse.tracecompass.analysis.timing.core
+ org.eclipse.tracecompass.analysis.timing.core,
+ org.eclipse.tracecompass.statesystem.core
Import-Package: com.google.common.base,
com.google.common.collect,
- com.google.common.hash;version="15.0.0"
+ com.google.common.hash,
+ com.google.common.primitives
Export-Package: org.eclipse.tracecompass.analysis.os.linux.core.contextswitch,
org.eclipse.tracecompass.analysis.os.linux.core.cpuusage,
org.eclipse.tracecompass.analysis.os.linux.core.event.aspect,
+ org.eclipse.tracecompass.analysis.os.linux.core.inputoutput,
org.eclipse.tracecompass.analysis.os.linux.core.kernel,
org.eclipse.tracecompass.analysis.os.linux.core.kernelmemoryusage,
org.eclipse.tracecompass.analysis.os.linux.core.latency,
org.eclipse.tracecompass.analysis.os.linux.core.signals,
org.eclipse.tracecompass.analysis.os.linux.core.trace,
org.eclipse.tracecompass.internal.analysis.os.linux.core;x-internal:=true,
+ org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput;x-friends:="org.eclipse.tracecompass.analysis.os.linux.core.tests",
+ org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.handlers;x-internal:=true,
org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel;x-friends:="org.eclipse.tracecompass.analysis.os.linux.core.tests",
org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers;x-friends:="org.eclipse.tracecompass.analysis.os.linux.core.tests",
org.eclipse.tracecompass.internal.analysis.os.linux.core.latency.statistics;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui,org.eclipse.tracecompass.analysis.os.linux.core.tests"
analysis.latency = System Call Latency
analysis.contextswitch = Context switch
analysis.kernelmemory = Kernel memory usage
-
+analysis.io = Input/Output
class="org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace">
</tracetype>
</module>
+ <module
+ analysis_module="org.eclipse.tracecompass.analysis.os.linux.core.inputoutput.InputOutputAnalysisModule"
+ id="org.eclipse.tracecompass.analysis.os.linux.inputoutput"
+ name="%analysis.io">
+ <tracetype
+ applies="true"
+ class="org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace">
+ </tracetype>
+ </module>
</extension>
</plugin>
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput;
+
+/**
+ * This file defines all the attribute names used in the handler. Both the
+ * construction and query steps should use them.
+ *
+ * These should not be externalized! The values here are used as-is in the
+ * history file on disk, so they should be kept the same to keep the file format
+ * compatible. If a view shows attribute names directly, the localization should
+ * be done on the viewer side.
+ *
+ * @author Houssem Daoud
+ * @since 2.0
+ *
+ */
+@SuppressWarnings({ "nls" })
+public interface Attributes {
+
+ /* First-level attributes */
+
+ /** Root attribute for disks */
+ String DISKS = "Disks";
+ /** Root attribute of the waiting queue requests */
+ String WAITING_QUEUE = "Waiting_queue";
+ /** Root attribute of the driver queue requests */
+ String DRIVER_QUEUE = "Driver_queue";
+ /** Length of the driver queue */
+ String DRIVER_QUEUE_LENGTH = "driverqueue_length";
+ /** Length of the waiting queue */
+ String WAITING_QUEUE_LENGTH = "waitingqueue_length";
+ /** Base sector of the request */
+ String CURRENT_REQUEST = "Current_request";
+ /** Size of a request */
+ String REQUEST_SIZE = "Request_size";
+ /**
+ * Contains the request in the waiting queue to which this request was
+ * merged
+ */
+ String MERGED_IN = "merged_in";
+ /** The request in the waiting queue this driver request was issued from */
+ String ISSUED_FROM = "issued_from";
+ /** Number of sectors read */
+ String SECTORS_READ = "sectors_read";
+ /** Number of sectors written */
+ String SECTORS_WRITTEN = "sectors_written";
+
+ /** System call root attribute */
+ String SYSTEM_CALLS_ROOT = "system_calls";
+
+ /** Root attribute for thread r/w */
+ String THREADS = "Threads";
+ /** Number of bytes read by a thread */
+ String BYTES_READ = "bytes_read";
+ /** Number of bytes written by a thread */
+ String BYTES_WRITTEN = "bytes_written";
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.InputOutputStateProvider;
+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.TmfTraceUtils;
+
+/**
+ * State System Module for Input Output traces
+ *
+ * @author Houssem Daoud
+ * @since 2.0
+ */
+public class InputOutputAnalysisModule extends TmfStateSystemAnalysisModule {
+
+ /** The ID of this analysis module */
+ public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.inputoutput"; //$NON-NLS-1$
+
+ @Override
+ protected ITmfStateProvider createStateProvider() {
+ ITmfTrace trace = checkNotNull(getTrace());
+ IKernelAnalysisEventLayout layout;
+
+ if (trace instanceof IKernelTrace) {
+ layout = ((IKernelTrace) trace).getKernelEventLayout();
+ } else {
+ /* Fall-back to the base LttngEventLayout */
+ layout = IKernelAnalysisEventLayout.DEFAULT_LAYOUT;
+ }
+
+ return new InputOutputStateProvider(trace, layout);
+ }
+
+ @Override
+ protected StateSystemBackendType getBackendType() {
+ return StateSystemBackendType.FULL;
+ }
+
+ @Override
+ protected Iterable<IAnalysisModule> getDependentAnalyses() {
+ Set<IAnalysisModule> modules = new HashSet<>();
+
+ ITmfTrace trace = getTrace();
+ if (trace == null) {
+ throw new IllegalStateException();
+ }
+ /*
+ * This analysis depends on the LTTng kernel analysis, so it's added to
+ * dependent modules.
+ */
+ Iterable<KernelAnalysisModule> kernelModules = TmfTraceUtils.getAnalysisModulesOfClass(trace, KernelAnalysisModule.class);
+ for (KernelAnalysisModule kernelModule : kernelModules) {
+ /* Only add the first one we find, if there is one */
+ modules.add(kernelModule);
+ break;
+ }
+ return modules;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput;
+
+/**
+ * Enum type for IO operations
+ *
+ * @author Geneviève Bastien
+ * @since 2.0
+ */
+public enum IoOperationType {
+
+ /**
+ * Write to the disk
+ */
+ WRITE,
+ /**
+ * Read on the disk
+ */
+ READ;
+
+ /**
+ * Get the BIO type from the rwbs value of a block operation.
+ *
+ * @param rwbs
+ * The rwbs value of the block operation
+ * @return The BIO type
+ */
+ public static IoOperationType getType(int rwbs) {
+ /* Even is a "read", odd is a "write" */
+ return (rwbs % 2 == 0) ? READ : WRITE;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Externalized message strings from the I/O Analysis
+ *
+ * @author Houssem Daoud
+ * @since 2.0
+ */
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.linuxtools.lttng2.kernel.core.inputoutput.analysis.messages"; //$NON-NLS-1$
+
+ /** Help text for the IO analysis */
+ public static @Nullable String LttngInputOutputModule_Help;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput;
+
+import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
+import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
+
+/**
+ * State values that are used in the io analysis event handlers.
+ *
+ * @author Houssem Daoud
+ * @since 2.0
+ */
+public interface StateValues {
+
+ /* IO Operation type values */
+ /** Value for write request */
+ int WRITING_REQUEST = 1;
+ /** Value for read requests */
+ int READING_REQUEST = 2;
+
+ /** State value for write requests */
+ ITmfStateValue WRITING_REQUEST_VALUE = TmfStateValue.newValueInt(WRITING_REQUEST);
+ /** State value for read requests */
+ ITmfStateValue READING_REQUEST_VALUE = TmfStateValue.newValueInt(READING_REQUEST);
+}
--- /dev/null
+###############################################################################
+# 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
+###############################################################################
+LttngInputOutputModule_Help=Builds the Kernel I/O state system
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput;
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput;
+
+import org.eclipse.tracecompass.analysis.os.linux.core.inputoutput.IoOperationType;
+
+/**
+ * Class that represents a block IO structure of the os kernel
+ *
+ * @author Houssem Daoud
+ */
+public class BlockIO {
+
+ private final Long fSector;
+ private final int fNrSector;
+ private final DiskWriteModel fDisk;
+ private final IoOperationType fType;
+
+ /**
+ * Constructor
+ *
+ * @param sector
+ * Start sector of this block IO
+ * @param nr_sector
+ * The number of sectors from this block IO
+ * @param disk
+ * The disk this BIO is on
+ * @param rwbs
+ * The rwbs value of a block operation
+ */
+ public BlockIO(Long sector, int nr_sector, DiskWriteModel disk, int rwbs) {
+ fSector = sector;
+ fNrSector = nr_sector;
+ fDisk = disk;
+ fType = IoOperationType.getType(rwbs);
+ }
+
+ /**
+ * Get the base sector of this BIO
+ *
+ * @return The base sector
+ */
+ public Long getSector() {
+ return fSector;
+ }
+
+ /**
+ * Get the number of sectors of this BIO
+ *
+ * @return The number of sectors
+ */
+ public int getNrSector() {
+ return fNrSector;
+ }
+
+ /**
+ * Get the disk this block IO is for
+ *
+ * @return The disk of this BIO
+ */
+ public DiskWriteModel getDisk() {
+ return fDisk;
+ }
+
+ /**
+ * Get the type of BIO
+ *
+ * @return The type of BIO
+ */
+ public IoOperationType getType() {
+ return fType;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.analysis.os.linux.core.inputoutput.Attributes;
+import org.eclipse.tracecompass.analysis.os.linux.core.inputoutput.IoOperationType;
+import org.eclipse.tracecompass.analysis.os.linux.core.inputoutput.StateValues;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.Activator;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
+import org.eclipse.tracecompass.statesystem.core.StateSystemBuilderUtils;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
+import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
+import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
+import org.eclipse.tracecompass.tmf.core.statesystem.TmfAttributePool;
+import org.eclipse.tracecompass.tmf.core.statesystem.TmfAttributePool.QueueType;
+import org.eclipse.tracecompass.tmf.core.util.Pair;
+
+import com.google.common.hash.HashFunction;
+import com.google.common.hash.Hashing;
+
+/**
+ * Class that represents a disk on a system. This class provides operation to
+ * save the analysis data in a state system.
+ *
+ * @author Houssem Daoud
+ * @since 2.0
+ */
+public class DiskWriteModel {
+
+ private static final HashFunction HF = NonNullUtils.checkNotNull(Hashing.goodFastHash(32));
+
+ private final Integer fDev;
+ private final Map<Long, Pair<Request, Integer>> fDriverQueue = new HashMap<>();
+ private final Map<Long, Pair<Request, Integer>> fWaitingQueue = new HashMap<>();
+ private final ITmfStateSystemBuilder fSs;
+ private final int fDiskQuark;
+ private final TmfAttributePool fWaitingQueueAttrib;
+ private final TmfAttributePool fDriverQueueAttrib;
+ private @Nullable String fDiskname = null;
+
+ /**
+ * Constructor
+ *
+ * @param dev
+ * The device number of the disk
+ * @param ss
+ * The state system this disk will be saved to
+ */
+ public DiskWriteModel(Integer dev, ITmfStateSystemBuilder ss) {
+ fDev = dev;
+ fSs = ss;
+ /* Initialize the state system for this disk */
+ fDiskQuark = fSs.getQuarkAbsoluteAndAdd(Attributes.DISKS, String.valueOf(dev));
+ fSs.getQuarkRelativeAndAdd(fDiskQuark, Attributes.SECTORS_WRITTEN);
+ fSs.getQuarkRelativeAndAdd(fDiskQuark, Attributes.SECTORS_READ);
+ int wqQuark = fSs.getQuarkRelativeAndAdd(fDiskQuark, Attributes.WAITING_QUEUE);
+ fWaitingQueueAttrib = new TmfAttributePool(fSs, wqQuark, QueueType.PRIORITY);
+ fSs.getQuarkRelativeAndAdd(fDiskQuark, Attributes.WAITING_QUEUE_LENGTH);
+ int dqQuark = fSs.getQuarkRelativeAndAdd(fDiskQuark, Attributes.DRIVER_QUEUE);
+ fDriverQueueAttrib = new TmfAttributePool(fSs, dqQuark, QueueType.PRIORITY);
+ fSs.getQuarkRelativeAndAdd(fDiskQuark, Attributes.DRIVER_QUEUE_LENGTH);
+ }
+
+ /**
+ * Set the human readable disk name of this device
+ *
+ * @param diskname
+ * The human readable name of the disk
+ */
+ public void setDiskName(String diskname) {
+ try {
+ fSs.modifyAttribute(fSs.getCurrentEndTime(), TmfStateValue.newValueString(diskname), fDiskQuark);
+ } catch (StateValueTypeException | AttributeNotFoundException e) {
+ Activator.getDefault().logError("Cannot set the diskname for disk " + diskname, e); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Return a request from the waiting queue starting at requested base sector
+ *
+ * @param sector
+ * The sector where the requests starts
+ * @return The request corresponding to this sector, or null if no request
+ * available
+ */
+ public @Nullable Request getWaitingRequest(Long sector) {
+ Pair<Request, Integer> reqQuark = fWaitingQueue.get(sector);
+ if (reqQuark == null) {
+ return null;
+ }
+ return reqQuark.getFirst();
+ }
+
+ /**
+ * Removes the request starting at sector from the waiting queue
+ *
+ * @param ts
+ * The timestamp at which to add this request
+ * @param sector
+ * The sector where the requests starts
+ * @return The quark of the request that was removed or
+ * {@link ITmfStateSystem.INVALID_ATTRIBUTE} if the request was not
+ * present
+ */
+ private int removeWaitingRequest(long ts, Long sector) {
+ Pair<Request, Integer> reqQuark = fWaitingQueue.remove(sector);
+ if (reqQuark == null) {
+ return ITmfStateSystem.INVALID_ATTRIBUTE;
+ }
+ int slotQuark = reqQuark.getSecond();
+ fWaitingQueueAttrib.recycle(slotQuark, ts);
+ return slotQuark;
+ }
+
+ /**
+ * Add a request to the waiting queue. Also saves this request to the state
+ * system
+ *
+ * @param ts
+ * The timestamp at which to add this request
+ * @param request
+ * The requests to put
+ * @return The quark of the request that has been added
+ */
+ public int addWaitingRequest(long ts, Request request) {
+ int slotQuark = insertInWaitingQueue(ts, request);
+ updateQueuesLength(ts);
+ return slotQuark;
+ }
+
+ private int insertInWaitingQueue(long ts, Request request) {
+ ITmfStateValue statusState = request.getType() == IoOperationType.READ ? StateValues.READING_REQUEST_VALUE : StateValues.WRITING_REQUEST_VALUE;
+ int slotQuark = fWaitingQueueAttrib.getAvailable();
+
+ /* Insertion in waiting queue */
+ try {
+ fSs.modifyAttribute(ts, statusState, slotQuark);
+
+ int currentRequestQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.CURRENT_REQUEST);
+ fSs.modifyAttribute(ts, TmfStateValue.newValueLong(request.getSector()), currentRequestQuark);
+
+ int requestSizeQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.REQUEST_SIZE);
+ fSs.modifyAttribute(ts, TmfStateValue.newValueInt(request.getNrSector()), requestSizeQuark);
+
+ int mergedInQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.MERGED_IN);
+ fSs.modifyAttribute(ts, TmfStateValue.nullValue(), mergedInQuark);
+ } catch (StateValueTypeException | AttributeNotFoundException e) {
+ Activator.getDefault().logError("Error inserting request", e); //$NON-NLS-1$
+ }
+ fWaitingQueue.put(request.getSector(), new Pair<>(request, slotQuark));
+
+ return slotQuark;
+ }
+
+ /**
+ * Update a request in the waiting queue. Also saves this request to the
+ * state system. If the request did not exist previously, it will be added
+ * to the queue. Since the sector may have been updated, the initialSector
+ * parameters allows to say which was the original sector this request was
+ * known for.
+ *
+ * @param ts
+ * The timestamp at which to add this request
+ * @param request
+ * The requests to put
+ * @param initialSector
+ * The original base sector of this request.
+ * @return The quark of the request that has been updated
+ */
+ public int updateWaitingRequest(long ts, Request request, Long initialSector) {
+ Pair<Request, Integer> reqQuark = fWaitingQueue.get(initialSector);
+ if (reqQuark == null) {
+ return addWaitingRequest(ts, request);
+ } else if (initialSector != request.getSector()) {
+ fWaitingQueue.remove(initialSector);
+ fWaitingQueue.put(request.getSector(), reqQuark);
+ }
+
+ int slotQuark = reqQuark.getSecond();
+
+ /*
+ * Update the sector, number of sectors and merged in request in waiting
+ * queue
+ */
+ try {
+ int currentRequestQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.CURRENT_REQUEST);
+ fSs.modifyAttribute(ts, TmfStateValue.newValueLong(request.getSector()), currentRequestQuark);
+
+ int requestSizeQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.REQUEST_SIZE);
+ fSs.modifyAttribute(ts, TmfStateValue.newValueInt(request.getNrSector()), requestSizeQuark);
+
+ int mergedInQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.MERGED_IN);
+ fSs.modifyAttribute(ts, TmfStateValue.nullValue(), mergedInQuark);
+ } catch (StateValueTypeException | AttributeNotFoundException e) {
+ Activator.getDefault().logError("Error inserting request", e); //$NON-NLS-1$
+ }
+
+ updateQueuesLength(ts);
+ return slotQuark;
+ }
+
+ /**
+ * Get the size of the waiting queue
+ *
+ * @return The waiting queue size
+ */
+ public int getWaitingQueueSize() {
+ return fWaitingQueue.size();
+ }
+
+ /**
+ * Return a request from the driver queue starting at requested base sector
+ *
+ * @param sector
+ * The sector where the requests starts
+ * @return The request corresponding to this sector, or null if no request
+ * available
+ */
+ public @Nullable Request getDriverRequest(Long sector) {
+ Pair<Request, Integer> reqQuark = fDriverQueue.get(sector);
+ if (reqQuark == null) {
+ return null;
+ }
+ return reqQuark.getFirst();
+ }
+
+ /**
+ * Removes the request starting at sector from the driver queue
+ *
+ * @param ts
+ * The timestamp at which to add this request
+ * @param sector
+ * The sector where the requests starts
+ */
+ private void removeDriverRequest(long ts, Long sector) {
+ Pair<Request, Integer> reqQuark = fDriverQueue.remove(sector);
+ if (reqQuark == null) {
+ return;
+ }
+ fDriverQueueAttrib.recycle(reqQuark.getSecond(), ts);
+ }
+
+ /**
+ * Issues a request to the disk. This method removes the request from the
+ * waiting queue if necessary and adds it to the driver queue.
+ *
+ * @param ts
+ * The timestamp of this operation
+ * @param request
+ * The requests to put
+ * @return The quark of the request that was just issued
+ */
+ public int issueRequest(long ts, Request request) {
+ /* Remove from waiting queue */
+ TmfStateValue issuedFromValue = TmfStateValue.nullValue();
+ int fromQuark = removeWaitingRequest(ts, request.getSector());
+ if (fromQuark != ITmfStateSystem.INVALID_ATTRIBUTE) {
+ String reqQueueId = fSs.getAttributeName(fromQuark);
+ issuedFromValue = TmfStateValue.newValueInt(Integer.parseInt(reqQueueId));
+ }
+
+ ITmfStateValue statusState = request.getType() == IoOperationType.READ ? StateValues.READING_REQUEST_VALUE : StateValues.WRITING_REQUEST_VALUE;
+ int slotQuark = fDriverQueueAttrib.getAvailable();
+
+ /* Insertion in driver queue */
+ try {
+ fSs.modifyAttribute(ts, statusState, slotQuark);
+
+ int currentRequestQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.CURRENT_REQUEST);
+ fSs.modifyAttribute(ts, TmfStateValue.newValueLong(request.getSector()), currentRequestQuark);
+
+ int requestSizeQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.REQUEST_SIZE);
+ fSs.modifyAttribute(ts, TmfStateValue.newValueInt(request.getNrSector()), requestSizeQuark);
+
+ int issuedFromQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.ISSUED_FROM);
+ fSs.modifyAttribute(ts, issuedFromValue, issuedFromQuark);
+ } catch (StateValueTypeException | AttributeNotFoundException e) {
+ Activator.getDefault().logError("Error issuing request", e); //$NON-NLS-1$
+ }
+
+ fDriverQueue.put(request.getSector(), new Pair<>(request, slotQuark));
+ updateQueuesLength(ts);
+ return slotQuark;
+ }
+
+ /**
+ * Completes a request on the disk. It adds to the total of sectors read and
+ * written on this disk. It also removes the request from the driver queue
+ * if necessary.
+ *
+ * @param ts
+ * The timestamp of this operation
+ * @param request
+ * The requests to put
+ */
+ public void completeRequest(long ts, Request request) {
+ /* Add the total number of sectors read or written */
+ try {
+ switch (request.getType()) {
+ case READ:
+ int readQuark = fSs.getQuarkRelativeAndAdd(fDiskQuark, Attributes.SECTORS_READ);
+ StateSystemBuilderUtils.incrementAttributeInt(fSs, ts, readQuark, request.getNrSector());
+ break;
+ case WRITE:
+ int writtenQuark = fSs.getQuarkRelativeAndAdd(fDiskQuark, Attributes.SECTORS_WRITTEN);
+ StateSystemBuilderUtils.incrementAttributeInt(fSs, ts, writtenQuark, request.getNrSector());
+ break;
+ default:
+ throw new IllegalStateException("Complete request: the request cannot be other than READ or WRITE:" + request.getType()); //$NON-NLS-1$
+ }
+ } catch (StateValueTypeException | AttributeNotFoundException e) {
+ Activator.getDefault().logError("Error completing request", e); //$NON-NLS-1$
+ }
+
+ /* Remove the request from driver queue */
+ removeDriverRequest(ts, request.getSector());
+ updateQueuesLength(ts);
+ }
+
+ /**
+ * Merges 2 requests from the waiting queue. The second request will be
+ * removed from the queue while the first one will be udpated
+ *
+ * @param ts
+ * The timestamp of this operation
+ * @param baseRequest
+ * The base request that will be kept
+ * @param mergedRequest
+ * The merged request to be removed from the queue
+ */
+ public void mergeRequests(long ts, Request baseRequest, Request mergedRequest) {
+ int mergedQuark = removeWaitingRequest(ts, mergedRequest.getSector());
+ Long baseSector = baseRequest.getSector();
+ baseRequest.mergeRequest(mergedRequest);
+ int baseQuark = updateWaitingRequest(ts, baseRequest, baseSector);
+ if (mergedQuark != ITmfStateSystem.INVALID_ATTRIBUTE) {
+ /* Add the merge information */
+ try {
+ String reqQueueId = fSs.getAttributeName(baseQuark);
+
+ int issuedFromQuark = fSs.getQuarkRelativeAndAdd(mergedQuark, Attributes.MERGED_IN);
+ fSs.modifyAttribute(ts, TmfStateValue.newValueInt(Integer.parseInt(reqQueueId)), issuedFromQuark);
+ } catch (StateValueTypeException | AttributeNotFoundException e) {
+ Activator.getDefault().logError("Error adding the merged request information", e); //$NON-NLS-1$
+ }
+ }
+ updateQueuesLength(ts);
+ }
+
+ /**
+ * Get the size of the driver queue
+ *
+ * @return The driver queue size
+ */
+ public int getDriverQueueSize() {
+ return fDriverQueue.size();
+ }
+
+ /**
+ * Get the quark corresponding to this disk
+ *
+ * @return The quark in the state system of this disk
+ */
+ public int getDiskQuark() {
+ return fDiskQuark;
+ }
+
+ private void updateQueuesLength(long ts) {
+ try {
+ int fDriverQueueLength = fSs.getQuarkRelativeAndAdd(fDiskQuark, Attributes.DRIVER_QUEUE_LENGTH);
+ fSs.modifyAttribute(ts, TmfStateValue.newValueInt(getDriverQueueSize()), fDriverQueueLength);
+ int fWaitinQueueLength = fSs.getQuarkRelativeAndAdd(fDiskQuark, Attributes.WAITING_QUEUE_LENGTH);
+ fSs.modifyAttribute(ts, TmfStateValue.newValueInt(getWaitingQueueSize()), fWaitinQueueLength);
+ } catch (StateValueTypeException | AttributeNotFoundException e) {
+ Activator.getDefault().logError("Error updating queues lengths", e); //$NON-NLS-1$
+ }
+ }
+
+ // ----------------------------------------------------
+ // Object methods
+ // ----------------------------------------------------
+
+ @Override
+ public int hashCode() {
+ return HF.newHasher().putInt(fDev).hash().asInt();
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (o instanceof DiskWriteModel) {
+ DiskWriteModel disk = (DiskWriteModel) o;
+ if (fDev.equals(disk.fDev)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "Disk: [" + fDev + ',' + fDiskname + ']'; //$NON-NLS-1$
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.analysis.os.linux.core.inputoutput.Attributes;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.Activator;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.handlers.BlockFrontMergeHandler;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.handlers.BlockRqComplete;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.handlers.BlockRqInsertHandler;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.handlers.BlockRqIssueHandler;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.handlers.MergeRequestsHandler;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.handlers.StateDumpHandler;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.handlers.SysEntryHandler;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.handlers.SysExitHandler;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers.KernelEventHandler;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
+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.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.statesystem.AbstractTmfStateProvider;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * State provider for the I/O analysis
+ *
+ * @author Houssem Daoud
+ * @since 2.0
+ */
+public class InputOutputStateProvider extends AbstractTmfStateProvider {
+
+ private static final int VERSION = 1;
+
+ private final Map<Integer, DiskWriteModel> fDisks = new HashMap<>();
+ private final Map<String, KernelEventHandler> fEventNames;
+ private final IKernelAnalysisEventLayout fLayout;
+
+ private final KernelEventHandler fSysEntryHandler;
+ private final KernelEventHandler fSysExitHandler;
+
+ /**
+ * Instantiate a new state provider plugin.
+ *
+ * @param trace
+ * The kernel trace to apply this state provider to
+ * @param layout
+ * The event layout to use for this state provider.
+ */
+ public InputOutputStateProvider(ITmfTrace trace, IKernelAnalysisEventLayout layout) {
+ super(trace, "Input Output Analysis");//$NON-NLS-1$
+ fLayout = layout;
+ fEventNames = buildEventNames(layout);
+ fSysEntryHandler = new SysEntryHandler(layout);
+ fSysExitHandler = new SysExitHandler(layout);
+ }
+
+ private Map<String, KernelEventHandler> buildEventNames(IKernelAnalysisEventLayout layout) {
+ ImmutableMap.Builder<String, KernelEventHandler> builder = ImmutableMap.builder();
+
+ builder.put(layout.eventBlockRqInsert(), new BlockRqInsertHandler(layout, this));
+ builder.put(layout.eventBlockRqIssue(), new BlockRqIssueHandler(layout, this));
+ builder.put(layout.eventBlockRqComplete(), new BlockRqComplete(layout, this));
+ builder.put(layout.eventBlockBioFrontmerge(), new BlockFrontMergeHandler(layout, this));
+ builder.put(layout.eventBlockRqMerge(), new MergeRequestsHandler(layout, this));
+
+ final String eventStatedumpBlockDevice = layout.eventStatedumpBlockDevice();
+ if (eventStatedumpBlockDevice != null) {
+ builder.put(eventStatedumpBlockDevice, new StateDumpHandler(layout, this));
+ }
+
+ return builder.build();
+ }
+
+ @Override
+ public int getVersion() {
+ return VERSION;
+ }
+
+ @Override
+ public InputOutputStateProvider getNewInstance() {
+ return new InputOutputStateProvider(this.getTrace(), this.fLayout);
+ }
+
+ @Override
+ protected void eventHandle(@Nullable ITmfEvent event) {
+
+ if (event == null) {
+ return;
+ }
+
+ final String eventName = event.getName();
+
+ try {
+ final ITmfStateSystemBuilder ss = NonNullUtils.checkNotNull(getStateSystemBuilder());
+ /*
+ * Feed event to the history system if it's known to cause a state
+ * transition.
+ */
+ KernelEventHandler handler = fEventNames.get(eventName);
+ if (handler == null) {
+ if (isSyscallExit(eventName)) {
+ handler = fSysExitHandler;
+ } else if (isSyscallEntry(eventName)) {
+ handler = fSysEntryHandler;
+ }
+ }
+ if (handler != null) {
+ handler.handleEvent(ss, event);
+ }
+ } catch (TimeRangeException | StateValueTypeException | AttributeNotFoundException e) {
+ Activator.getDefault().logError("Exception while building the IO state system", e); //$NON-NLS-1$
+ }
+
+ }
+
+ /**
+ * Get a disk identified by a device ID
+ *
+ * @param deviceId
+ * The device ID of the block device
+ * @return The disk corresponding to the device ID
+ */
+ public DiskWriteModel getDisk(int deviceId) {
+ DiskWriteModel disk = fDisks.get(deviceId);
+ if (disk == null) {
+ disk = new DiskWriteModel(deviceId, checkNotNull(getStateSystemBuilder()));
+ fDisks.put(deviceId, disk);
+ }
+ return disk;
+ }
+
+ private boolean isSyscallEntry(String eventName) {
+ return (eventName.startsWith(fLayout.eventSyscallEntryPrefix())
+ || eventName.startsWith(fLayout.eventCompatSyscallEntryPrefix()));
+ }
+
+ private boolean isSyscallExit(String eventName) {
+ return (eventName.startsWith(fLayout.eventSyscallExitPrefix()) ||
+ eventName.startsWith(fLayout.eventCompatSyscallExitPrefix()));
+ }
+
+ /**
+ * Return the quark corresponding to the threads attributes
+ *
+ * @param ssb
+ * the state system builder
+ * @return The quark of the {@link Attributes#THREADS} node
+ */
+ public static int getNodeThreads(ITmfStateSystemBuilder ssb) {
+ return ssb.getQuarkAbsoluteAndAdd(Attributes.THREADS);
+ }
+
+ /**
+ * Return the quark corresponding to the system call root attributes
+ *
+ * @param ssb
+ * the state system builder
+ * @return The quark of the {@link Attributes#SYSTEM_CALLS_ROOT} node
+ */
+ public static int getNodeSyscalls(ITmfStateSystemBuilder ssb) {
+ return ssb.getQuarkAbsoluteAndAdd(Attributes.SYSTEM_CALLS_ROOT);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.analysis.os.linux.core.inputoutput.IoOperationType;
+
+/**
+ * Represents a request to a disk of the system
+ *
+ * @author Houssem Daoud
+ */
+public class Request {
+
+ private Long fSector;
+ private int fNrSector;
+ private final DiskWriteModel fDisk;
+ private final List<BlockIO> fBios = new ArrayList<>();
+ private @Nullable Integer fIssuedFrom = null;
+ private IoOperationType fType;
+
+ /**
+ * Constructor
+ *
+ * @param disk
+ * The disk for this request
+ * @param sector
+ * The base sector of this request
+ * @param rwbs
+ * The read/write bits
+ */
+ public Request(DiskWriteModel disk, Long sector, int rwbs) {
+ fSector = sector;
+ fNrSector = 0;
+ fDisk = disk;
+ fType = IoOperationType.getType(rwbs);
+ }
+
+ /**
+ * Constructor from a Block IO structure
+ *
+ * @param bio
+ * The BIO to start this request from
+ */
+ public Request(BlockIO bio) {
+ fSector = bio.getSector();
+ fNrSector = bio.getNrSector();
+ fType = bio.getType();
+ fBios.add(0, bio);
+ fDisk = bio.getDisk();
+ }
+
+ /**
+ * Get the base sector of this request
+ *
+ * @return The base sector
+ */
+ public Long getSector() {
+ return fSector;
+ }
+
+ /**
+ * Get the number of sectors of this request
+ *
+ * @return The number of sectors
+ */
+ public int getNrSector() {
+ return fNrSector;
+ }
+
+ /**
+ * Updates the number of sectors for this request
+ *
+ * @param nrSector
+ * The new number of sectors
+ */
+ public void setNrSector(int nrSector) {
+ fNrSector = nrSector;
+ }
+
+ /**
+ * Get the disk this request is for
+ *
+ * @return The disk of this BIO
+ */
+ public DiskWriteModel getDisk() {
+ return fDisk;
+ }
+
+ /**
+ * Get the type of request
+ *
+ * @return The type of request
+ */
+ public IoOperationType getType() {
+ return fType;
+ }
+
+ /**
+ * Set the read/write mode of this request
+ *
+ * @param rwbs
+ * The read/write bits of the request
+ */
+ public void setType(int rwbs) {
+ fType = IoOperationType.getType(rwbs);
+ }
+
+ /**
+ * Get the list of BIOs included in this request
+ *
+ * @return The list of BIOs
+ */
+ public List<BlockIO> getBios() {
+ return Collections.unmodifiableList(fBios);
+ }
+
+ /**
+ * Get the request this request is based on
+ *
+ * @return The quark of the request this is issued from
+ */
+ public @Nullable Integer getIssuedFrom() {
+ return fIssuedFrom;
+ }
+
+ /**
+ * Insert the BIO into this request
+ *
+ * @param bio
+ * The Block IO to insert in this request
+ */
+ public void insertBio(BlockIO bio) {
+ fBios.add(bio);
+ fNrSector += bio.getNrSector();
+ if (bio.getSector() < getSector()) {
+ fSector = bio.getSector();
+ }
+ }
+
+ /**
+ * Merges a request into this one
+ *
+ * @param request
+ * The second request to merge
+ */
+ public void mergeRequest(Request request) {
+ fBios.addAll(request.getBios());
+ fNrSector = getNrSector() + request.getNrSector();
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput.handlers;
+
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.BlockIO;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.DiskWriteModel;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.InputOutputStateProvider;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.Request;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers.KernelEventHandler;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
+
+/**
+ * IO Request merge event handler
+ *
+ * @author Houssem Daoud
+ */
+public class BlockFrontMergeHandler extends KernelEventHandler {
+
+ private final InputOutputStateProvider fStateProvider;
+
+ /**
+ * Constructor
+ *
+ * @param layout
+ * event layout
+ * @param sp
+ * The state provider calling this handler
+ */
+ public BlockFrontMergeHandler(IKernelAnalysisEventLayout layout, InputOutputStateProvider sp) {
+ super(layout);
+ fStateProvider = sp;
+ }
+
+ @Override
+ public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event) throws AttributeNotFoundException {
+ ITmfEventField content = event.getContent();
+ long ts = event.getTimestamp().getValue();
+
+ Long sector = NonNullUtils.checkNotNull((Long) content.getField(getLayout().fieldBlockSector()).getValue());
+ Long rqSector = NonNullUtils.checkNotNull((Long) content.getField(getLayout().fieldBlockRqSector()).getValue());
+ int nrSector = ((Long) content.getField(getLayout().fieldBlockNrSector()).getValue()).intValue();
+ int dev = ((Long) content.getField(getLayout().fieldBlockDeviceId()).getValue()).intValue();
+ int rwbs = ((Long) content.getField(getLayout().fieldBlockRwbs()).getValue()).intValue();
+ DiskWriteModel disk = fStateProvider.getDisk(dev);
+
+ Request request = disk.getWaitingRequest(rqSector);
+ if (request == null) {
+ BlockIO bio = new BlockIO(rqSector, Long.valueOf(sector - rqSector).intValue(), disk, rwbs);
+ request = new Request(bio);
+ }
+ BlockIO bio = new BlockIO(sector, nrSector, disk, rwbs);
+ request.insertBio(bio);
+
+ disk.updateWaitingRequest(ts, request, rqSector);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput.handlers;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.DiskWriteModel;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.InputOutputStateProvider;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.Request;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers.KernelEventHandler;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
+
+/**
+ * Request completed event handler
+ *
+ * @author Houssem Daoud
+ */
+public class BlockRqComplete extends KernelEventHandler {
+
+ private final InputOutputStateProvider fStateProvider;
+
+ /**
+ * Constructor
+ *
+ * @param layout
+ * event layout
+ * @param sp
+ * The state provider calling this handler
+ */
+ public BlockRqComplete(IKernelAnalysisEventLayout layout, InputOutputStateProvider sp) {
+ super(layout);
+ fStateProvider = sp;
+ }
+
+ @Override
+ public void handleEvent(@NonNull ITmfStateSystemBuilder ss, @NonNull ITmfEvent event) throws AttributeNotFoundException {
+ ITmfEventField content = event.getContent();
+ long ts = event.getTimestamp().getValue();
+
+ Long sector = NonNullUtils.checkNotNull((Long) content.getField(getLayout().fieldBlockSector()).getValue());
+ int nrSector = ((Long) content.getField(getLayout().fieldBlockNrSector()).getValue()).intValue();
+ int phydisk = ((Long) content.getField(getLayout().fieldBlockDeviceId()).getValue()).intValue();
+ int rwbs = ((Long) content.getField(getLayout().fieldBlockRwbs()).getValue()).intValue();
+ DiskWriteModel disk = fStateProvider.getDisk(phydisk);
+
+ Request request = disk.getDriverRequest(sector);
+ if (request == null) {
+ request = new Request(disk, sector, rwbs);
+ }
+ request.setNrSector(nrSector);
+ request.setType(rwbs);
+ disk.completeRequest(ts, request);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput.handlers;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.BlockIO;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.DiskWriteModel;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.InputOutputStateProvider;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.Request;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers.KernelEventHandler;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
+
+/**
+ * Request insert event handler
+ *
+ * @author Houssem Daoud
+ */
+public class BlockRqInsertHandler extends KernelEventHandler {
+
+ private final InputOutputStateProvider fStateProvider;
+
+ /**
+ * Constructor
+ *
+ * @param layout
+ * event layout
+ * @param sp
+ * The state provider calling this handler
+ */
+ public BlockRqInsertHandler(IKernelAnalysisEventLayout layout, InputOutputStateProvider sp) {
+ super(layout);
+ fStateProvider = sp;
+ }
+
+ @Override
+ public void handleEvent(@NonNull ITmfStateSystemBuilder ss, @NonNull ITmfEvent event) throws AttributeNotFoundException {
+ ITmfEventField content = event.getContent();
+ long ts = event.getTimestamp().getValue();
+
+ int phydisk = ((Long) content.getField(getLayout().fieldBlockDeviceId()).getValue()).intValue();
+ Long sector = NonNullUtils.checkNotNull((Long) content.getField(getLayout().fieldBlockSector()).getValue());
+ int nrSector = ((Long) content.getField(getLayout().fieldBlockNrSector()).getValue()).intValue();
+ int rwbs = ((Long) content.getField(getLayout().fieldBlockRwbs()).getValue()).intValue();
+ DiskWriteModel disk = fStateProvider.getDisk(phydisk);
+
+ if (nrSector == 0) {
+ return;
+ }
+ BlockIO bio = new BlockIO(sector, nrSector, disk, rwbs);
+ Request request = new Request(bio);
+ disk.addWaitingRequest(ts, request);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput.handlers;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.BlockIO;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.DiskWriteModel;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.InputOutputStateProvider;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.Request;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers.KernelEventHandler;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
+
+/**
+ * Request issue event handler
+ *
+ * @author Houssem Daoud
+ */
+public class BlockRqIssueHandler extends KernelEventHandler {
+
+ private final InputOutputStateProvider fStateProvider;
+
+ /**
+ * Constructor
+ *
+ * @param layout
+ * event layout
+ * @param sp
+ * The state provider calling this handler
+ */
+ public BlockRqIssueHandler(IKernelAnalysisEventLayout layout, InputOutputStateProvider sp) {
+ super(layout);
+ fStateProvider = sp;
+ }
+
+ @Override
+ public void handleEvent(@NonNull ITmfStateSystemBuilder ss, @NonNull ITmfEvent event) throws AttributeNotFoundException {
+ ITmfEventField content = event.getContent();
+ long ts = event.getTimestamp().getValue();
+
+ Integer phydisk = ((Long) content.getField(getLayout().fieldBlockDeviceId()).getValue()).intValue();
+ Long sector = NonNullUtils.checkNotNull((Long) content.getField(getLayout().fieldBlockSector()).getValue());
+ Integer nrSector = ((Long) content.getField(getLayout().fieldBlockNrSector()).getValue()).intValue();
+ Integer rwbs = ((Long) content.getField(getLayout().fieldBlockRwbs()).getValue()).intValue();
+ if (nrSector == 0) {
+ return;
+ }
+
+ DiskWriteModel disk = fStateProvider.getDisk(phydisk);
+ Request request = disk.getWaitingRequest(sector);
+ if (request == null) {
+ BlockIO bio = new BlockIO(sector, nrSector, disk, rwbs);
+ request = new Request(bio);
+ }
+ request.setNrSector(nrSector);
+ request.setType(rwbs);
+ disk.issueRequest(ts, request);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput.handlers;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.DiskWriteModel;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.InputOutputStateProvider;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.Request;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers.KernelEventHandler;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
+
+/**
+ * elv_merge_request event handler
+ *
+ * TODO: This event is part of an addons module to lttng. Update this when it is
+ * mainlined in the kernel
+ *
+ * @author Houssem Daoud
+ */
+public class MergeRequestsHandler extends KernelEventHandler {
+
+ private final InputOutputStateProvider fStateProvider;
+
+ /**
+ * Constructor
+ *
+ * @param layout
+ * event layout
+ * @param sp
+ * The state provider calling this handler
+ */
+ public MergeRequestsHandler(IKernelAnalysisEventLayout layout, InputOutputStateProvider sp) {
+ super(layout);
+ fStateProvider = sp;
+ }
+
+ @Override
+ public void handleEvent(@NonNull ITmfStateSystemBuilder ss, @NonNull ITmfEvent event) throws AttributeNotFoundException {
+ ITmfEventField content = event.getContent();
+ long ts = event.getTimestamp().getValue();
+
+ int phydisk = ((Long) content.getField(getLayout().fieldBlockDeviceId()).getValue()).intValue();
+ Long baseRequestSector = NonNullUtils.checkNotNull((Long) content.getField(getLayout().fieldBlockRqSector()).getValue());
+ Long mergedRequestSector = NonNullUtils.checkNotNull((Long) content.getField(getLayout().fieldBlockNextRqSector()).getValue());
+ DiskWriteModel disk = fStateProvider.getDisk(phydisk);
+
+ Request baseRequest = disk.getWaitingRequest(baseRequestSector);
+ if (baseRequest == null) {
+ baseRequest = new Request(disk, baseRequestSector, 0);
+ }
+ Request mergedRequest = disk.getWaitingRequest(mergedRequestSector);
+ if (mergedRequest == null) {
+ mergedRequest = new Request(disk, mergedRequestSector, 0);
+ }
+ disk.mergeRequests(ts, baseRequest, mergedRequest);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput.handlers;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.DiskWriteModel;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.InputOutputStateProvider;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers.KernelEventHandler;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
+
+/**
+ * State dump event handler
+ *
+ * @author Houssem Daoud
+ */
+public class StateDumpHandler extends KernelEventHandler {
+
+ private final InputOutputStateProvider fStateProvider;
+
+ /**
+ * Constructor
+ *
+ * @param layout
+ * event layout
+ * @param sp
+ * The state provider calling this handler
+ */
+ public StateDumpHandler(IKernelAnalysisEventLayout layout, InputOutputStateProvider sp) {
+ super(layout);
+ fStateProvider = sp;
+ }
+
+ @Override
+ public void handleEvent(@NonNull ITmfStateSystemBuilder ss, @NonNull ITmfEvent event) throws AttributeNotFoundException {
+ ITmfEventField content = event.getContent();
+
+ String diskname = (String) event.getContent().getField(getLayout().fieldDiskname()).getValue();
+ int dev = ((Long) content.getField(getLayout().fieldBlockDeviceId()).getValue()).intValue();
+
+ if (diskname != null) {
+ DiskWriteModel disk = fStateProvider.getDisk(dev);
+ disk.setDiskName(diskname);
+ }
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput.handlers;
+
+import org.eclipse.tracecompass.analysis.os.linux.core.event.aspect.LinuxTidAspect;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.InputOutputStateProvider;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers.KernelEventHandler;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
+
+/**
+ * System call entry handler
+ *
+ * @author Houssem Daoud
+ */
+public class SysEntryHandler extends KernelEventHandler {
+
+ /**
+ * Constructor
+ *
+ * @param layout
+ * event layout
+ */
+ public SysEntryHandler(IKernelAnalysisEventLayout layout) {
+ super(layout);
+ }
+
+ @Override
+ public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event) throws AttributeNotFoundException {
+ long ts = event.getTimestamp().getValue();
+ String eventName = event.getName();
+
+ Integer tid = TmfTraceUtils.resolveIntEventAspectOfClassForEvent(event.getTrace(), LinuxTidAspect.class, event);
+ if (tid == null) {
+ return;
+ }
+ int threadSyscallQuark = ss.getQuarkRelativeAndAdd(InputOutputStateProvider.getNodeSyscalls(ss), String.valueOf(tid));
+ TmfStateValue value = TmfStateValue.newValueString(eventName);
+ ss.modifyAttribute(ts, value, threadSyscallQuark);
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 É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.analysis.os.linux.core.inputoutput.handlers;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import java.util.regex.Pattern;
+
+import org.eclipse.tracecompass.analysis.os.linux.core.event.aspect.LinuxTidAspect;
+import org.eclipse.tracecompass.analysis.os.linux.core.inputoutput.Attributes;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.InputOutputStateProvider;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers.KernelEventHandler;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
+import org.eclipse.tracecompass.statesystem.core.StateSystemBuilderUtils;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+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.trace.TmfTraceUtils;
+
+/**
+ * System call exit handler
+ *
+ * @author Houssem Daoud
+ */
+public class SysExitHandler extends KernelEventHandler {
+
+ private static final String SYSCALL_READ_PATTERN = "_[p]?read.*"; //$NON-NLS-1$
+ private static final String SYSCALL_WRITE_PATTERN = "_[p]?write.*"; //$NON-NLS-1$
+
+ private final Pattern fSyscallReadPattern;
+ private final Pattern fSyscallWritePattern;
+
+ /**
+ * Constructor
+ *
+ * @param layout
+ * event layout
+ */
+ public SysExitHandler(IKernelAnalysisEventLayout layout) {
+ super(layout);
+ fSyscallReadPattern = checkNotNull(Pattern.compile('(' + layout.eventSyscallEntryPrefix() + '|' + layout.eventCompatSyscallEntryPrefix() + ')' + SYSCALL_READ_PATTERN));
+ fSyscallWritePattern = checkNotNull(Pattern.compile('(' + layout.eventSyscallEntryPrefix() + '|' + layout.eventCompatSyscallEntryPrefix() + ')' + SYSCALL_WRITE_PATTERN));
+ }
+
+ @Override
+ public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event) throws AttributeNotFoundException {
+ ITmfEventField content = event.getContent();
+ long ts = event.getTimestamp().getValue();
+
+ Integer tid = TmfTraceUtils.resolveIntEventAspectOfClassForEvent(event.getTrace(), LinuxTidAspect.class, event);
+ if (tid == null) {
+ return;
+ }
+
+ int ret = ((Long) content.getField(getLayout().fieldSyscallRet()).getValue()).intValue();
+ /* TODO: Why save the syscall before if we have it in the sys_exit? */
+ int syscallQuark = ss.optQuarkRelative(InputOutputStateProvider.getNodeSyscalls(ss), String.valueOf(tid));
+ if (syscallQuark == ITmfStateSystem.INVALID_ATTRIBUTE) {
+ return;
+ }
+ ITmfStateValue currentSyscall = ss.queryOngoingState(syscallQuark);
+ String syscallValue = currentSyscall.unboxStr();
+ if (ret >= 0) {
+ if (fSyscallReadPattern.matcher(syscallValue).matches()) {
+ int currentProcessNode = ss.getQuarkRelativeAndAdd(InputOutputStateProvider.getNodeThreads(ss), String.valueOf(tid));
+ int readQuark = ss.getQuarkRelativeAndAdd(currentProcessNode, Attributes.BYTES_READ);
+ ss.getQuarkRelativeAndAdd(currentProcessNode, Attributes.BYTES_WRITTEN);
+ StateSystemBuilderUtils.incrementAttributeInt(ss, ts, readQuark, ret);
+ } else if (fSyscallWritePattern.matcher(syscallValue).matches()) {
+ int currentProcessNode = ss.getQuarkRelativeAndAdd(InputOutputStateProvider.getNodeThreads(ss), String.valueOf(tid));
+ ss.getQuarkRelativeAndAdd(currentProcessNode, Attributes.BYTES_READ);
+ int writtenQuark = ss.getQuarkRelativeAndAdd(currentProcessNode, Attributes.BYTES_WRITTEN);
+ StateSystemBuilderUtils.incrementAttributeInt(ss, ts, writtenQuark, ret);
+ }
+ }
+ TmfStateValue value = TmfStateValue.nullValue();
+ ss.modifyAttribute(ts, value, syscallQuark);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput.handlers;
--- /dev/null
+/*******************************************************************************
+ * 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.analysis.os.linux.core.inputoutput;