analysis.io: Introduce the input/output linux analysis
authorHoussem Daoud <houssemmh@gmail.com>
Mon, 21 Mar 2016 13:42:01 +0000 (09:42 -0400)
committerGenevieve Bastien <gbastien+lttng@versatic.net>
Wed, 6 Apr 2016 17:43:45 +0000 (13:43 -0400)
This analysis uses the block_* events to track the requests to the disks
and the number of sectors read and written. It also stores the reads and
writes by process from the syscalls.

Change-Id: I6e1b00d53eb3a217b01a906d4d1fd566e53481ef
Signed-off-by: Geneviève Bastien <gbastien+lttng@versatic.net>
Signed-off-by: Houssem Daoud <houssemmh@gmail.com>
Reviewed-on: https://git.eclipse.org/r/69667
Reviewed-by: Hudson CI
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
24 files changed:
analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF
analysis/org.eclipse.tracecompass.analysis.os.linux.core/plugin.properties
analysis/org.eclipse.tracecompass.analysis.os.linux.core/plugin.xml
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/Attributes.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/InputOutputAnalysisModule.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/IoOperationType.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/Messages.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/StateValues.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/messages.properties [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/package-info.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/BlockIO.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/DiskWriteModel.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/InputOutputStateProvider.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/Request.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockFrontMergeHandler.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockRqComplete.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockRqInsertHandler.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockRqIssueHandler.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/MergeRequestsHandler.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/StateDumpHandler.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/SysEntryHandler.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/SysExitHandler.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/package-info.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/package-info.java [new file with mode: 0644]

index 3aac568a111362fc4911f3e02aa2ba3900f06dab..1ee4a17503e2b8ac93f2fce9c04d0a4d0a4341db 100644 (file)
@@ -13,13 +13,16 @@ Require-Bundle: org.eclipse.core.runtime,
  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,
@@ -27,6 +30,8 @@ Export-Package: org.eclipse.tracecompass.analysis.os.linux.core.contextswitch,
  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"
index a2ce49c91bf3ba4fc34cffc9ce9f5ef21c75ddbd..da9e549812f3253ad64ab39dd7387ba7cc09dc66 100644 (file)
@@ -20,4 +20,4 @@ analysis.cpuusage = CPU usage
 analysis.latency = System Call Latency
 analysis.contextswitch = Context switch
 analysis.kernelmemory = Kernel memory usage
-
+analysis.io = Input/Output
index fbb793191d9b9cae3b6e3ca06e7f8d0cce88f8a2..29c0d4b83476f78ed7412cc5606ea2a778dfbffc 100644 (file)
                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>
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/Attributes.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/Attributes.java
new file mode 100644 (file)
index 0000000..f3d4a55
--- /dev/null
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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";
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/InputOutputAnalysisModule.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/InputOutputAnalysisModule.java
new file mode 100644 (file)
index 0000000..5e77ed0
--- /dev/null
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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;
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/IoOperationType.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/IoOperationType.java
new file mode 100644 (file)
index 0000000..21ff458
--- /dev/null
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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;
+    }
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/Messages.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/Messages.java
new file mode 100644 (file)
index 0000000..68885d3
--- /dev/null
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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() {
+    }
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/StateValues.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/StateValues.java
new file mode 100644 (file)
index 0000000..9c1c422
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * 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);
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/messages.properties b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/messages.properties
new file mode 100644 (file)
index 0000000..973be19
--- /dev/null
@@ -0,0 +1,9 @@
+###############################################################################
+# 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
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/package-info.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/package-info.java
new file mode 100644 (file)
index 0000000..93da287
--- /dev/null
@@ -0,0 +1,10 @@
+/*******************************************************************************
+ * 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;
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/BlockIO.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/BlockIO.java
new file mode 100644 (file)
index 0000000..a07e62f
--- /dev/null
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * 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;
+    }
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/DiskWriteModel.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/DiskWriteModel.java
new file mode 100644 (file)
index 0000000..31f4e0d
--- /dev/null
@@ -0,0 +1,418 @@
+/*******************************************************************************
+ * 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$
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/InputOutputStateProvider.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/InputOutputStateProvider.java
new file mode 100644 (file)
index 0000000..4a02107
--- /dev/null
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * 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);
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/Request.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/Request.java
new file mode 100644 (file)
index 0000000..1fcf320
--- /dev/null
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * 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();
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockFrontMergeHandler.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockFrontMergeHandler.java
new file mode 100644 (file)
index 0000000..7b906a0
--- /dev/null
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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);
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockRqComplete.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockRqComplete.java
new file mode 100644 (file)
index 0000000..be3596c
--- /dev/null
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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);
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockRqInsertHandler.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockRqInsertHandler.java
new file mode 100644 (file)
index 0000000..6f861da
--- /dev/null
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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);
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockRqIssueHandler.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockRqIssueHandler.java
new file mode 100644 (file)
index 0000000..ac5c9ea
--- /dev/null
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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);
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/MergeRequestsHandler.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/MergeRequestsHandler.java
new file mode 100644 (file)
index 0000000..00cc1f7
--- /dev/null
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * 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);
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/StateDumpHandler.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/StateDumpHandler.java
new file mode 100644 (file)
index 0000000..83e3095
--- /dev/null
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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);
+        }
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/SysEntryHandler.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/SysEntryHandler.java
new file mode 100644 (file)
index 0000000..13e4e95
--- /dev/null
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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);
+    }
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/SysExitHandler.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/SysExitHandler.java
new file mode 100644 (file)
index 0000000..ec35606
--- /dev/null
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * 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);
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/package-info.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/package-info.java
new file mode 100644 (file)
index 0000000..1f4e50c
--- /dev/null
@@ -0,0 +1,11 @@
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput.handlers;
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/package-info.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/package-info.java
new file mode 100644 (file)
index 0000000..b31cd54
--- /dev/null
@@ -0,0 +1,11 @@
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput;
This page took 0.049716 seconds and 5 git commands to generate.