From 6d02c5c1779cd9f9cf2b3a37bca68408b7d4129a Mon Sep 17 00:00:00 2001 From: Houssem Daoud Date: Mon, 21 Mar 2016 09:42:01 -0400 Subject: [PATCH] analysis.io: Introduce the input/output linux analysis MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Houssem Daoud Reviewed-on: https://git.eclipse.org/r/69667 Reviewed-by: Hudson CI Reviewed-by: Matthew Khouzam Tested-by: Matthew Khouzam --- .../META-INF/MANIFEST.MF | 9 +- .../plugin.properties | 2 +- .../plugin.xml | 9 + .../os/linux/core/inputoutput/Attributes.java | 66 +++ .../InputOutputAnalysisModule.java | 79 ++++ .../core/inputoutput/IoOperationType.java | 40 ++ .../os/linux/core/inputoutput/Messages.java | 34 ++ .../linux/core/inputoutput/StateValues.java | 33 ++ .../core/inputoutput/messages.properties | 9 + .../linux/core/inputoutput/package-info.java | 10 + .../os/linux/core/inputoutput/BlockIO.java | 80 ++++ .../core/inputoutput/DiskWriteModel.java | 418 ++++++++++++++++++ .../inputoutput/InputOutputStateProvider.java | 181 ++++++++ .../os/linux/core/inputoutput/Request.java | 163 +++++++ .../handlers/BlockFrontMergeHandler.java | 69 +++ .../inputoutput/handlers/BlockRqComplete.java | 66 +++ .../handlers/BlockRqInsertHandler.java | 66 +++ .../handlers/BlockRqIssueHandler.java | 71 +++ .../handlers/MergeRequestsHandler.java | 70 +++ .../handlers/StateDumpHandler.java | 57 +++ .../inputoutput/handlers/SysEntryHandler.java | 52 +++ .../inputoutput/handlers/SysExitHandler.java | 91 ++++ .../inputoutput/handlers/package-info.java | 11 + .../linux/core/inputoutput/package-info.java | 11 + 24 files changed, 1694 insertions(+), 3 deletions(-) create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/Attributes.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/InputOutputAnalysisModule.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/IoOperationType.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/Messages.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/StateValues.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/messages.properties create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/package-info.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/BlockIO.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/DiskWriteModel.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/InputOutputStateProvider.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/Request.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockFrontMergeHandler.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockRqComplete.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockRqInsertHandler.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockRqIssueHandler.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/MergeRequestsHandler.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/StateDumpHandler.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/SysEntryHandler.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/SysExitHandler.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/package-info.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/package-info.java diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF index 3aac568a11..1ee4a17503 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF @@ -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" diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/plugin.properties b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/plugin.properties index a2ce49c91b..da9e549812 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/plugin.properties +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/plugin.properties @@ -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 diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/plugin.xml b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/plugin.xml index fbb793191d..29c0d4b834 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/plugin.xml +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/plugin.xml @@ -51,5 +51,14 @@ class="org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace"> + + + + 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 index 0000000000..f3d4a55ea0 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/Attributes.java @@ -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 index 0000000000..5e77ed0e26 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/InputOutputAnalysisModule.java @@ -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 getDependentAnalyses() { + Set 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 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 index 0000000000..21ff4588eb --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/IoOperationType.java @@ -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 index 0000000000..68885d3c43 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/Messages.java @@ -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 index 0000000000..9c1c42203e --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/StateValues.java @@ -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 index 0000000000..973be19868 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/messages.properties @@ -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 index 0000000000..93da287b35 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/inputoutput/package-info.java @@ -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 index 0000000000..a07e62fa2f --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/BlockIO.java @@ -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 index 0000000000..31f4e0d817 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/DiskWriteModel.java @@ -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> fDriverQueue = new HashMap<>(); + private final Map> 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 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 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 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 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 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 index 0000000000..4a02107063 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/InputOutputStateProvider.java @@ -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 fDisks = new HashMap<>(); + private final Map 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 buildEventNames(IKernelAnalysisEventLayout layout) { + ImmutableMap.Builder 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 index 0000000000..1fcf320070 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/Request.java @@ -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 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 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 index 0000000000..7b906a0a7a --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockFrontMergeHandler.java @@ -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 index 0000000000..be3596c61a --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockRqComplete.java @@ -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 index 0000000000..6f861da510 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockRqInsertHandler.java @@ -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 index 0000000000..ac5c9eab44 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/BlockRqIssueHandler.java @@ -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 index 0000000000..00cc1f76b7 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/MergeRequestsHandler.java @@ -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 index 0000000000..83e309534b --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/StateDumpHandler.java @@ -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 index 0000000000..13e4e95d89 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/SysEntryHandler.java @@ -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 index 0000000000..ec356067f0 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/SysExitHandler.java @@ -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 index 0000000000..1f4e50c39d --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/handlers/package-info.java @@ -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 index 0000000000..b31cd54fbc --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/inputoutput/package-info.java @@ -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; -- 2.34.1