| author | Alexandre Montplaisir | 2012-03-14 17:27:09 (EDT) |
|---|---|---|
| committer | Francois Chouinard | 2012-03-19 17:43:59 (EDT) |
| commit | b714e56f44c8b93dd4c944c0c245b27fa880e1e8 (patch) (side-by-side diff) | |
| tree | 14ff36a397076d93a7b65d7b9c52ba7e8cb6f78b | |
| parent | 09303135edb89fad4ac52f0e5fdfc1d67a4ccadb (diff) | |
| download | org.eclipse.linuxtools-b714e56f44c8b93dd4c944c0c245b27fa880e1e8.zip org.eclipse.linuxtools-b714e56f44c8b93dd4c944c0c245b27fa880e1e8.tar.gz org.eclipse.linuxtools-b714e56f44c8b93dd4c944c0c245b27fa880e1e8.tar.bz2 | |
Merge Kernel state system input provider
which goes in the lttng2.kernel.core plugin
11 files changed, 1242 insertions, 3 deletions
diff --git a/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/META-INF/MANIFEST.MF b/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/META-INF/MANIFEST.MF index 358462c..b23b5f2 100644 --- a/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/META-INF/MANIFEST.MF +++ b/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/META-INF/MANIFEST.MF @@ -8,7 +8,8 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Require-Bundle: org.junit;bundle-version="3.8.2", org.eclipse.core.runtime;bundle-version="3.7.0", org.eclipse.core.resources;bundle-version="3.7.100", - org.eclipse.linuxtools.lttng.core;bundle-version="0.4.0" + org.eclipse.linuxtools.lttng2.kernel.core;bundle-version="0.1.0", + org.eclipse.linuxtools.tmf.core;bundle-version="0.5.0" Bundle-Localization: plugin Bundle-Activator: org.eclipse.linuxtools.lttng2.kernel.core.tests.Activator Bundle-ActivationPolicy: lazy diff --git a/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/CTFDummyInputTest.java b/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/CTFDummyInputTest.java new file mode 100644 index 0000000..0576a55 --- a/dev/null +++ b/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/CTFDummyInputTest.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson + * Copyright (c) 2010, 2011 École Polytechnique de Montréal + * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com> + * + * 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.linuxtools.lttng2.kernel.core.tests.stateprovider; + +import org.eclipse.linuxtools.internal.lttng2.kernel.core.stateprovider.CTFDummyInput; +import org.junit.BeforeClass; + +/** + * Test the dummy CTF input plugin + * + * @author alexmont + * + */ +public class CTFDummyInputTest extends CTFKernelStateInputTest { + + /* Hiding superclass method */ + @BeforeClass + public static void initialize() { + input = new CTFDummyInput(CTFTestFiles.getTestTrace()); + } + +} diff --git a/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/CTFKernelStateInputTest.java b/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/CTFKernelStateInputTest.java new file mode 100644 index 0000000..411052b --- a/dev/null +++ b/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/CTFKernelStateInputTest.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson + * Copyright (c) 2010, 2011 École Polytechnique de Montréal + * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com> + * + * 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.linuxtools.lttng2.kernel.core.tests.stateprovider; + +import static org.junit.Assert.*; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.eclipse.linuxtools.tmf.core.statesystem.StateSystem; +import org.eclipse.linuxtools.tmf.core.statesystem.helpers.IStateChangeInput; +import org.eclipse.linuxtools.internal.lttng2.kernel.core.stateprovider.CTFKernelStateInput; + +/** + * Tests for the LTTng 2.0 kernel state provider + * + * @author alexmont + * + */ +public class CTFKernelStateInputTest { + + protected static IStateChangeInput input; + + @BeforeClass + public static void initialize() { + input = new CTFKernelStateInput(CTFTestFiles.getTestTrace()); + + } + + @AfterClass + public static void cleanup() { + // + } + + @Test + public void testOpening() { + long testStartTime; + testStartTime = input.getStartTime(); + assertTrue(testStartTime == CTFTestFiles.startTime1); + } + + @Test + public void testRunning() { + StateSystem ss = new StateSystem(); + input.assignTargetStateSystem(ss); + input.getStateSystem(); /* Let's pad that coverage... */ + input.run(); + } + +} diff --git a/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/CTFTestFiles.java b/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/CTFTestFiles.java new file mode 100644 index 0000000..8348dfd --- a/dev/null +++ b/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/CTFTestFiles.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson + * Copyright (c) 2010, 2011 École Polytechnique de Montréal + * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com> + * + * 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.linuxtools.lttng2.kernel.core.tests.stateprovider; + +import java.io.FileNotFoundException; + +import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfEvent; +import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTrace; + +/** + * Definitions used by all tests using CTF trace files + * + * @author alexmont + * + */ +public abstract class CTFTestFiles { + + public final static long NANOSECS_PER_SEC = 1000000000L; + + /* + * To run these tests, you will need to download the following trace, at: + * http://www.dorsal.polymtl.ca/~alexmont/data/trace1.tar.bz2 + * + * and extract it at the root of the project. You can also set up a custom + * path below. + */ + public final static String traceFile1 = "trace1/kernel"; //$NON-NLS-1$ + public final static long startTime1 = 17620320801208L; + + public static CtfTmfTrace trace1 = null; + + public static CtfTmfTrace getTestTrace() { + if (trace1 == null) { + trace1 = new CtfTmfTrace(); + try { + trace1.initTrace("test-trace1", traceFile1, CtfTmfEvent.class); //$NON-NLS-1$ + } catch (FileNotFoundException e) { + /* If we don't have the file, we shouldn't even try the tests... */ + e.printStackTrace(); + return null; + } + } + return trace1; + } + +} diff --git a/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/StateSystemFullHistoryTest.java b/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/StateSystemFullHistoryTest.java new file mode 100644 index 0000000..8830f80 --- a/dev/null +++ b/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/StateSystemFullHistoryTest.java @@ -0,0 +1,333 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson + * Copyright (c) 2010, 2011 École Polytechnique de Montréal + * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com> + * + * 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.linuxtools.lttng2.kernel.core.tests.stateprovider; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.List; + +import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval; +import org.eclipse.linuxtools.tmf.core.statesystem.AttributeNotFoundException; +import org.eclipse.linuxtools.tmf.core.statesystem.StateHistorySystem; +import org.eclipse.linuxtools.tmf.core.statesystem.TimeRangeException; +import org.eclipse.linuxtools.tmf.core.statesystem.backend.historytree.HistoryTreeBackend; +import org.eclipse.linuxtools.tmf.core.statesystem.helpers.HistoryBuilder; +import org.eclipse.linuxtools.tmf.core.statesystem.helpers.IStateChangeInput; +import org.eclipse.linuxtools.tmf.core.statesystem.helpers.IStateHistoryBackend; +import org.eclipse.linuxtools.tmf.core.statevalue.StateValueTypeException; +import org.eclipse.linuxtools.internal.lttng2.kernel.core.stateprovider.CTFKernelStateInput; +import org.junit.*; + +/** + * Unit tests for the StateHistorySystem, which uses a full (non-partial) + * history and the non-threaded CTF kernel handler. + * + * @author alexmont + * + */ +@SuppressWarnings("nls") +public class StateSystemFullHistoryTest { + + protected static File stateFile; + protected static File stateFileBenchmark; + + protected static HistoryBuilder builder; + protected static IStateChangeInput input; + protected static IStateHistoryBackend hp; + protected static StateHistorySystem shs; + + protected static String getTestFileName() { + return "/tmp/statefile.ht"; //$NON-NLS-1$ + } + + @BeforeClass + public static void initialize() { + stateFile = new File(getTestFileName()); + stateFileBenchmark = new File(getTestFileName() + ".benchmark"); //$NON-NLS-1$ + try { + input = new CTFKernelStateInput(CTFTestFiles.getTestTrace()); + hp = new HistoryTreeBackend(stateFile, input.getStartTime()); + builder = new HistoryBuilder(input, hp); + } catch (Exception e) { + e.printStackTrace(); + } + builder.run(); + shs = (StateHistorySystem) builder.getSS(); + } + + @AfterClass + public static void cleanup() { + stateFile.delete(); + stateFileBenchmark.delete(); + } + + /** + * Rebuild independently so we can benchmark it. Too bad JUnit doesn't allow + * us to @Test the @BeforeClass... + */ + @Test + public void testBuild() { + HistoryBuilder zebuilder; + IStateChangeInput zeinput; + IStateHistoryBackend zehp; + + try { + zeinput = new CTFKernelStateInput(CTFTestFiles.getTestTrace()); + zehp = new HistoryTreeBackend(stateFileBenchmark, + zeinput.getStartTime()); + zebuilder = new HistoryBuilder(zeinput, zehp); + zebuilder.run(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void testOpenExistingStateFile() { + IStateHistoryBackend hp2 = null; + StateHistorySystem shs2 = null; + try { + /* 'newStateFile' should have already been created */ + hp2 = new HistoryTreeBackend(stateFile); + shs2 = new StateHistorySystem(hp2, false); + } catch (IOException e) { + e.printStackTrace(); + } + assertTrue(shs2 != null); + } + + @Test + public void testFullQuery1() throws StateValueTypeException, + AttributeNotFoundException, TimeRangeException { + + ITmfStateInterval interval; + int quark, valueInt; + String valueStr; + + shs.loadStateAtTime(17622841472359L); + + quark = shs.getQuarkAbsolute("CPUs", "0", "Current_thread"); + interval = shs.queryState(quark); + valueInt = interval.getStateValue().unboxInt(); + assertTrue(valueInt == 1929); + + quark = shs.getQuarkAbsolute("Threads", "1197", "Exec_name"); + interval = shs.queryState(quark); + valueStr = interval.getStateValue().unboxStr(); + assertTrue(valueStr.equals("apache2")); + + // FIXME fails at the moment (attribute type is int, and = 3129??), I'll + // figure it out later + // quark = shs.getQuarkAbsolute("Threads", "3109", "Exec_mode_stack"); + // interval = shs.getState(quark); + // valueStr = interval.getStateValue().unboxStr(); + // assertTrue( valueStr.equals("bloup") ); + } + + @Test + public void testFullQuery2() { + // + } + + @Test + public void testFullQuery3() { + // + } + + @Test + public void testSingleQuery1() throws AttributeNotFoundException, + TimeRangeException, StateValueTypeException { + + long timestamp = 17622841472359L; + int quark; + ITmfStateInterval interval; + String valueStr; + + quark = shs.getQuarkAbsolute("Threads", "1197", "Exec_name"); + interval = shs.querySingleState(timestamp, quark); + valueStr = interval.getStateValue().unboxStr(); + assertTrue(valueStr.equals("apache2")); + } + + @Test + public void testSingleQuery2() { + // + } + + @Test + public void testSingleQuery3() { + // + } + + @Test + public void testRangeQuery1() throws AttributeNotFoundException, + TimeRangeException, StateValueTypeException { + + long time1 = 17622841472359L; + long time2 = time1 + 1L * CTFTestFiles.NANOSECS_PER_SEC; + int quark; + List<ITmfStateInterval> intervals; + + quark = shs.getQuarkAbsolute("CPUs", "0", "Current_thread"); + intervals = shs.queryHistoryRange(quark, time1, time2); + assertTrue(intervals.size() == 1018); /* Number of context switches! */ + assertTrue(intervals.get(100).getStateValue().unboxInt() == 2974); + assertTrue(intervals.get(205).getEndTime() == 17622977386059L); + } + + /** + * Ask for a time range outside of the trace's range + * + * @throws TimeRangeException + */ + @Test(expected = TimeRangeException.class) + public void testFullQueryInvalidTime1() throws TimeRangeException { + shs.loadStateAtTime(CTFTestFiles.startTime1 + 20L + * CTFTestFiles.NANOSECS_PER_SEC); + + } + + @Test(expected = TimeRangeException.class) + public void testFullQueryInvalidTime2() throws TimeRangeException { + shs.loadStateAtTime(CTFTestFiles.startTime1 - 20L + * CTFTestFiles.NANOSECS_PER_SEC); + + } + + @Test(expected = TimeRangeException.class) + public void testSingleQueryInvalidTime1() + throws AttributeNotFoundException, TimeRangeException { + + int quark = shs.getQuarkAbsolute("CPUs", "0", "Current_thread"); + long time = CTFTestFiles.startTime1 + 20L + * CTFTestFiles.NANOSECS_PER_SEC; + shs.querySingleState(time, quark); + } + + @Test(expected = TimeRangeException.class) + public void testSingleQueryInvalidTime2() + throws AttributeNotFoundException, TimeRangeException { + + int quark = shs.getQuarkAbsolute("CPUs", "0", "Current_thread"); + long time = CTFTestFiles.startTime1 - 20L + * CTFTestFiles.NANOSECS_PER_SEC; + shs.querySingleState(time, quark); + } + + @Test(expected = TimeRangeException.class) + public void testRangeQueryInvalidTime1() throws AttributeNotFoundException, + TimeRangeException { + + int quark = shs.getQuarkAbsolute("CPUs", "0", "Current_thread"); + long time1 = CTFTestFiles.startTime1 - 20L + * CTFTestFiles.NANOSECS_PER_SEC; /* invalid */ + long time2 = CTFTestFiles.startTime1 + 1L + * CTFTestFiles.NANOSECS_PER_SEC; /* valid */ + + shs.queryHistoryRange(quark, time1, time2); + } + + @Test(expected = TimeRangeException.class) + public void testRangeQueryInvalidTime2() throws TimeRangeException, + AttributeNotFoundException { + + int quark = shs.getQuarkAbsolute("CPUs", "0", "Current_thread"); + long time1 = CTFTestFiles.startTime1 + 1L + * CTFTestFiles.NANOSECS_PER_SEC; /* valid */ + long time2 = CTFTestFiles.startTime1 + 20L + * CTFTestFiles.NANOSECS_PER_SEC; /* invalid */ + + shs.queryHistoryRange(quark, time1, time2); + } + + @Test(expected = TimeRangeException.class) + public void testRangeQueryInvalidTime3() throws TimeRangeException, + AttributeNotFoundException { + + int quark = shs.getQuarkAbsolute("CPUs", "0", "Current_thread"); + long time1 = CTFTestFiles.startTime1 - 1L + * CTFTestFiles.NANOSECS_PER_SEC; /* invalid */ + long time2 = CTFTestFiles.startTime1 + 20L + * CTFTestFiles.NANOSECS_PER_SEC; /* invalid */ + + shs.queryHistoryRange(quark, time1, time2); + } + + /** + * Ask for a non-existing attribute + * + * @throws AttributeNotFoundException + */ + @Test(expected = AttributeNotFoundException.class) + public void testQueryInvalidAttribute() throws AttributeNotFoundException { + + shs.getQuarkAbsolute("There", "is", "no", "cow", "level"); + } + + /** + * Query but with the wrong State Value type + * + * @throws StateValueTypeException + * @throws AttributeNotFoundException + * @throws TimeRangeException + */ + @Test(expected = StateValueTypeException.class) + public void testQueryInvalidValuetype1() throws StateValueTypeException, + AttributeNotFoundException, TimeRangeException { + + ITmfStateInterval interval; + int quark; + + shs.loadStateAtTime(17622841472359L); + + quark = shs.getQuarkAbsolute("CPUs", "0", "Current_thread"); + interval = shs.queryState(quark); + interval.getStateValue().unboxStr(); /* + * This is supposed to be a int + * value + */ + } + + @Test(expected = StateValueTypeException.class) + public void testQueryInvalidValuetype2() throws StateValueTypeException, + AttributeNotFoundException, TimeRangeException { + + ITmfStateInterval interval; + int quark; + + shs.loadStateAtTime(17622841472359L); + + quark = shs.getQuarkAbsolute("Threads", "1197", "Exec_name"); + interval = shs.queryState(quark); + interval.getStateValue().unboxInt(); /* + * This is supposed to be a String + * value + */ + } + + @Test + public void testFullAttributeName() throws AttributeNotFoundException { + int quark = shs.getQuarkAbsolute("CPUs", "0", "Current_thread"); + String name = shs.getFullAttributePath(quark); + assertTrue(name.equals("CPUs/0/Current_thread")); + } + + @Test + public void testDebugPrinting() throws FileNotFoundException { + shs.debugPrint(new PrintWriter(new File("/dev/null"))); + } +} diff --git a/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/StateSystemFullThreadedHistoryTest.java b/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/StateSystemFullThreadedHistoryTest.java new file mode 100644 index 0000000..c72c24d --- a/dev/null +++ b/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/StateSystemFullThreadedHistoryTest.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson + * Copyright (c) 2010, 2011 École Polytechnique de Montréal + * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com> + * + * 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.linuxtools.lttng2.kernel.core.tests.stateprovider; + +import java.io.File; + +import org.eclipse.linuxtools.internal.lttng2.kernel.core.stateprovider.CTFKernelStateInput; +import org.eclipse.linuxtools.tmf.core.statesystem.StateHistorySystem; +import org.eclipse.linuxtools.tmf.core.statesystem.backend.historytree.ThreadedHistoryTreeBackend; +import org.eclipse.linuxtools.tmf.core.statesystem.helpers.HistoryBuilder; +import org.eclipse.linuxtools.tmf.core.statesystem.helpers.IStateChangeInput; +import org.eclipse.linuxtools.tmf.core.statesystem.helpers.IStateHistoryBackend; + +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * Variant of the StateSystemFullHistoryTest, which uses the threaded event + * handler instead. + * + * @author alexmont + * + */ +public class StateSystemFullThreadedHistoryTest extends + StateSystemFullHistoryTest { + + /* Hiding the static method in the superclass */ + protected static String getTestFileName() { + return "/tmp/statefile-threaded.ht"; //$NON-NLS-1$ + } + + @BeforeClass + public static void initialize() { + stateFile = new File(getTestFileName()); + stateFileBenchmark = new File(getTestFileName() + ".benchmark"); //$NON-NLS-1$ + try { + input = new CTFKernelStateInput(CTFTestFiles.getTestTrace()); + hp = new ThreadedHistoryTreeBackend(stateFile, + input.getStartTime(), 2000); + builder = new HistoryBuilder(input, hp); + } catch (Exception e) { + e.printStackTrace(); + } + builder.run(); + shs = (StateHistorySystem) builder.getSS(); + } + + @Override + @Test + public void testBuild() { + HistoryBuilder zebuilder; + IStateChangeInput zeinput; + IStateHistoryBackend zehp; + + try { + zeinput = new CTFKernelStateInput(CTFTestFiles.getTestTrace()); + zehp = new ThreadedHistoryTreeBackend(stateFileBenchmark, + zeinput.getStartTime(), 2000); + zebuilder = new HistoryBuilder(zeinput, zehp); + zebuilder.run(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/TestAll.java b/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/TestAll.java new file mode 100644 index 0000000..e53f2e8 --- a/dev/null +++ b/lttng/org.eclipse.linuxtools.lttng2.kernel.core.tests/src/org/eclipse/linuxtools/lttng2/kernel/core/tests/stateprovider/TestAll.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alexandre Montplaisir - Initial implementation + ******************************************************************************/ + +package org.eclipse.linuxtools.lttng2.kernel.core.tests.stateprovider; + +import org.junit.runner.JUnitCore; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * The class <code>TestAll</code> builds a suite that can be used to run all of + * the tests within its package as well as within any subpackages of its + * package. + * + * @author ematkho + * @version $Revision: 1.0 $ + */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ CTFDummyInputTest.class, CTFKernelStateInputTest.class, + StateSystemFullHistoryTest.class, StateSystemFullThreadedHistoryTest.class}) +public class TestAll { + + /** + * Launch the test. + * + * @param args + * the command line arguments + */ + public static void main(String[] args) { + JUnitCore.runClasses(new Class[] { TestAll.class }); + } +} diff --git a/lttng/org.eclipse.linuxtools.lttng2.kernel.core/META-INF/MANIFEST.MF b/lttng/org.eclipse.linuxtools.lttng2.kernel.core/META-INF/MANIFEST.MF index 556f7ac..8d87338 100644 --- a/lttng/org.eclipse.linuxtools.lttng2.kernel.core/META-INF/MANIFEST.MF +++ b/lttng/org.eclipse.linuxtools.lttng2.kernel.core/META-INF/MANIFEST.MF @@ -7,6 +7,8 @@ Bundle-Activator: org.eclipse.linuxtools.internal.lttng2.kernel.core.Activator Bundle-Vendor: %Bundle-Vendor Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-ActivationPolicy: lazy -Export-Package: org.eclipse.linuxtools.internal.lttng2.kernel.core;x-internal:=true +Export-Package: org.eclipse.linuxtools.internal.lttng2.kernel.core;x-friends:="org.eclipse.linuxtools.lttng2.kernel.core.tests", + org.eclipse.linuxtools.internal.lttng2.kernel.core.stateprovider;x-friends:="org.eclipse.linuxtools.lttng2.kernel.core.tests" Bundle-Localization: plugin -Require-Bundle: org.eclipse.core.runtime;bundle-version="3.7.0" +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.7.0", + org.eclipse.linuxtools.tmf.core;bundle-version="0.5.0" diff --git a/lttng/org.eclipse.linuxtools.lttng2.kernel.core/src/org/eclipse/linuxtools/internal/lttng2/kernel/core/stateprovider/CTFDummyInput.java b/lttng/org.eclipse.linuxtools.lttng2.kernel.core/src/org/eclipse/linuxtools/internal/lttng2/kernel/core/stateprovider/CTFDummyInput.java new file mode 100644 index 0000000..af46d9a --- a/dev/null +++ b/lttng/org.eclipse.linuxtools.lttng2.kernel.core/src/org/eclipse/linuxtools/internal/lttng2/kernel/core/stateprovider/CTFDummyInput.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson + * Copyright (c) 2010, 2011 École Polytechnique de Montréal + * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com> + * + * 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.linuxtools.internal.lttng2.kernel.core.stateprovider; + +import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfIterator; +import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfEvent; +import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTrace; +import org.eclipse.linuxtools.tmf.core.statesystem.StateSystem; +import org.eclipse.linuxtools.tmf.core.statesystem.helpers.IStateChangeInput; + +/** + * "Dummy" version of the CTF event input plugin. This one only reads events + * (and creates the Event/EventWrapper objects) but discards them instead of + * inserting them in the Queue. + * + * Only useful for benchmarking purposes. + * + * @author alexmont + * + */ +public class CTFDummyInput implements IStateChangeInput { + + private final CtfIterator iterator; + + /** + * Create a new dummy CTF state change input. + * + * @param traceFile + * The CTF trace to read from (can be any type of CTF trace) + */ + public CTFDummyInput(CtfTmfTrace trace) { + this.iterator = new CtfIterator(trace); + + } + + @SuppressWarnings("unused") + @Override + public void run() { + /* We know currentEvent is unused here, it's by design! */ + CtfTmfEvent currentEvent; + currentEvent = iterator.getCurrentEvent(); + while (iterator.advance()) { + currentEvent = iterator.getCurrentEvent(); + } + } + + @Override + public long getStartTime() { + return iterator.getLocation().getLocation(); + } + + /** + * This dummy input does not insert any state changes anywhere, so this + * method does nothing. + */ + @Override + public void assignTargetStateSystem(StateSystem ss) { + // + } + + /** + * Since there is no target state system in the dummy input, this always + * returns null. + */ + @Override + public StateSystem getStateSystem() { + return null; + } + +} diff --git a/lttng/org.eclipse.linuxtools.lttng2.kernel.core/src/org/eclipse/linuxtools/internal/lttng2/kernel/core/stateprovider/CTFKernelHandler.java b/lttng/org.eclipse.linuxtools.lttng2.kernel.core/src/org/eclipse/linuxtools/internal/lttng2/kernel/core/stateprovider/CTFKernelHandler.java new file mode 100644 index 0000000..c0fb8c4 --- a/dev/null +++ b/lttng/org.eclipse.linuxtools.lttng2.kernel.core/src/org/eclipse/linuxtools/internal/lttng2/kernel/core/stateprovider/CTFKernelHandler.java @@ -0,0 +1,448 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson + * Copyright (c) 2010, 2011 École Polytechnique de Montréal + * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com> + * + * 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.linuxtools.internal.lttng2.kernel.core.stateprovider; + +import java.util.HashMap; +import java.util.Vector; +import java.util.concurrent.BlockingQueue; + +import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfEvent; +import org.eclipse.linuxtools.tmf.core.event.ITmfEventField; +import org.eclipse.linuxtools.tmf.core.statesystem.AttributeNotFoundException; +import org.eclipse.linuxtools.tmf.core.statesystem.StateHistorySystem; +import org.eclipse.linuxtools.tmf.core.statesystem.StateSystem; +import org.eclipse.linuxtools.tmf.core.statesystem.TimeRangeException; +import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue; +import org.eclipse.linuxtools.tmf.core.statevalue.StateValueTypeException; +import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue; + +/** + * This is the reference "state provider" for LTTng 2.0 kernel traces. + * + * @author alexmont + * + */ +class CTFKernelHandler implements Runnable { + + private final BlockingQueue<CtfTmfEvent> inQueue; + private StateSystem ss; + + private CtfTmfEvent currentEvent; + + /* + * We can keep handles to some Attribute Nodes so these don't need to be + * re-found (re-hashed Strings etc.) every new event + */ + Vector<Integer> currentCPUNodes; + Vector<Integer> currentThreadNodes; + + /* Event names HashMap. TODO: This can be discarded once we move to Java 7 */ + private final HashMap<String, Integer> knownEventNames; + + CTFKernelHandler(BlockingQueue<CtfTmfEvent> eventsQueue) { + assert (eventsQueue != null); + this.inQueue = eventsQueue; + currentCPUNodes = new Vector<Integer>(); + currentThreadNodes = new Vector<Integer>(); + + knownEventNames = fillEventNames(); + } + + void assignStateSystem(StateSystem targetSS) { + this.ss = targetSS; + } + + StateSystem getStateSystem() { + return ss; + } + + @Override + public void run() { + if (ss == null) { + System.err.println("Cannot run event manager without assigning a target state system first!"); //$NON-NLS-1$ + return; + } + CtfTmfEvent event; + + try { + event = inQueue.take(); + while (event.getTimestamp() != null) { + processEvent(event); + event = inQueue.take(); + } + /* We've received the last event, clean up */ + closeStateSystem(); + return; + } catch (InterruptedException e) { + /* We've been interrupted abnormally */ + System.out.println("Event handler interrupted!"); //$NON-NLS-1$ + e.printStackTrace(); + } + } + + private void closeStateSystem() { + /* Close the History system, if there is one */ + if (ss.getClass() == StateHistorySystem.class) { + try { + ((StateHistorySystem) ss).closeHistory(currentEvent.getTimestamp().getValue()); + } catch (TimeRangeException e) { + /* + * Since we're using currentEvent.getTimestamp, this shouldn't + * cause any problem + */ + e.printStackTrace(); + } + } + } + + @SuppressWarnings("nls") + private void processEvent(CtfTmfEvent event) { + currentEvent = event; + ITmfEventField content = event.getContent(); + String eventName = event.getType().getName(); + + long ts = event.getTimestamp().getValue(); + int quark; + ITmfStateValue value; + Integer eventCpu = event.getCPU(); + Integer currentCPUNode, currentThreadNode, tidNode; + + /* Adjust the current nodes Vectors if we see a new CPU in an event */ + if (eventCpu >= currentCPUNodes.size()) { + /* We need to add this node to the vector */ + for (Integer i = currentCPUNodes.size(); i < eventCpu + 1; i++) { + quark = ss.getQuarkAbsoluteAndAdd("CPUs", i.toString()); + currentCPUNodes.add(quark); + + quark = ss.getQuarkAbsoluteAndAdd("Threads", "unknown"); + currentThreadNodes.add(quark); + } + } + + currentCPUNode = currentCPUNodes.get(eventCpu); + currentThreadNode = currentThreadNodes.get(eventCpu); + assert (currentCPUNode != null); + assert (currentThreadNode != null); + + try { + /* + * Feed event to the history system if it's known to cause a state + * transition See: + * https://projectwiki.dorsal.polymtl.ca/index.php/State_transitions + */ + switch (getEventIndex(eventName)) { + + case 1: // "exit_syscall": + /* Fields: int64 ret */ + /* Pop "syscall" from the Exec_mode_stack */ + quark = ss.getQuarkRelativeAndAdd(currentThreadNode, + "Exec_mode_stack"); + try { + ss.popAttribute(ts, quark); + } catch (AttributeNotFoundException e1) { + /* + * meh, can happen if we're missing events, we'll just + * silently ignore it. + */ + System.err.println(event.getTimestamp() + + " Popping empty attribute: " + e1.getMessage()); //$NON-NLS-1$ + } + break; + + case 2: // "irq_handler_entry": + /* Fields: int32 irq, string name */ + Integer irqId = ((Long) content.getField("irq").getValue()).intValue(); + + /* Push the IRQ to the CPU's IRQ_stack */ + quark = ss.getQuarkRelativeAndAdd(currentCPUNode, "IRQ_stack"); + value = TmfStateValue.newValueInt(irqId); + ss.pushAttribute(ts, value, quark); + + /* Change the status of the running process to interrupted */ + quark = ss.getQuarkRelativeAndAdd(currentThreadNode, "Status"); + value = TmfStateValue.newValueInt(STATE_PROCESS_STATUS_WAIT_CPU); + ss.modifyAttribute(ts, value, quark); + break; + + case 3: // "irq_handler_exit": + /* Fields: int32 irq, int32 ret */ + int stackDepth = 0; + + /* Pop the IRQ from the CPU's IRQ_stack */ + quark = ss.getQuarkRelativeAndAdd(currentCPUNode, "IRQ_stack"); + try { + ss.popAttribute(ts, quark); + } catch (AttributeNotFoundException e1) { + System.err.print(event.getTimestamp() + + " Popping empty attribute: " + e1.getMessage()); + } + + /* + * If this was the last IRQ on the stack, set the process back + * to running + */ + /* 'quark' should still be valid */ + try { + stackDepth = ss.queryOngoingState(quark).unboxInt(); + } catch (StateValueTypeException e) { + /* IRQ_stack SHOULD be of int type, this shouldn't happen */ + e.printStackTrace(); + } + if (stackDepth == 0) { + quark = ss.getQuarkRelativeAndAdd(currentThreadNode, + "Status"); + value = TmfStateValue.newValueInt(STATE_PROCESS_STATUS_RUN); + ss.modifyAttribute(ts, value, quark); + } + break; + + case 4: // "softirq_entry": + /* Fields: int32 vec */ + break; + + case 5: // "softirq_exit": + /* Fields: int32 vec */ + break; + + case 6: // "softirq_raise": + /* Fields: int32 vec */ + break; + + case 7: // "sched_switch": + /* + * Fields: string prev_comm, int32 prev_tid, int32 prev_prio, + * int64 prev_state, string next_comm, int32 next_tid, int32 + * next_prio + */ + + // prev_comm doesn't seem to get populated... + String prevProcessName = (String) content.getField("prev_comm").getValue(); + Integer prevTid = ((Long) content.getField("prev_tid").getValue()).intValue(); + Long prevState = (Long) content.getField("prev_state").getValue(); + + String nextProcessName = (String) content.getField("next_comm").getValue(); + Integer nextTid = ((Long) content.getField("next_tid").getValue()).intValue(); + + /* Update the name of the process going out (if needed) */ + quark = ss.getQuarkRelativeAndAdd(currentThreadNode, + "Exec_name"); + value = TmfStateValue.newValueString(prevProcessName); + ss.updateOngoingState(value, quark); + + /* Update the currentThreadNodes pointer */ + Integer newCurrentThreadNode = ss.getQuarkAbsoluteAndAdd( + "Threads", nextTid.toString()); + currentThreadNodes.set(eventCpu, newCurrentThreadNode); + + /* Set the status of the new scheduled process */ + quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode, + "Status"); + value = TmfStateValue.newValueInt(STATE_PROCESS_STATUS_RUN); + ss.modifyAttribute(ts, value, quark); + + /* Set the exec name of the new process */ + quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode, + "Exec_name"); + value = TmfStateValue.newValueString(nextProcessName); + ss.modifyAttribute(ts, value, quark); + + /* Set the status of the process that got scheduled out */ + quark = ss.getQuarkAbsoluteAndAdd("Threads", + prevTid.toString(), "Status"); + value = TmfStateValue.newValueInt(prevState.intValue()); + ss.modifyAttribute(ts, value, quark); + + /* Set the current scheduled process on the relevant CPU */ + quark = ss.getQuarkRelativeAndAdd(currentCPUNode, + "Current_thread"); + value = TmfStateValue.newValueInt(nextTid); + ss.modifyAttribute(ts, value, quark); + break; + + case 8: // "sched_process_fork": + /* + * Fields: string parent_comm, int32 parent_tid, string + * child_comm, int32 child_tid + */ + + // String parentProcessName = (String) + // event.getFieldValue("parent_comm"); + String childProcessName = (String) content.getField("child_comm").getValue(); + // assert ( parentProcessName.equals(childProcessName) ); + + Integer parentTid = ((Long) content.getField("parent_tid").getValue()).intValue(); + Integer childTid = ((Long) content.getField("child_tid").getValue()).intValue(); + + tidNode = ss.getQuarkAbsoluteAndAdd("Threads", + childTid.toString()); + + /* + * Add the new process with its known TID, PPID, and initial + * Exec_name + */ + quark = ss.getQuarkRelativeAndAdd(tidNode, "PPID"); + value = TmfStateValue.newValueInt(parentTid); + ss.modifyAttribute(ts, value, quark); + + /* Set the new process' exec_name */ + quark = ss.getQuarkRelativeAndAdd(tidNode, "Exec_name"); + value = TmfStateValue.newValueString(childProcessName); + ss.modifyAttribute(ts, value, quark); + break; + + case 9: // "sched_process_exit": + /* Fields: string comm, int32 tid, int32 prio */ + String processName = (String) content.getField("comm").getValue(); + Integer tid = ((Long) content.getField("tid").getValue()).intValue(); + + /* Update the process' name, if we don't have it */ + quark = ss.getQuarkAbsoluteAndAdd("Threads", tid.toString(), + "Exec_name"); + value = TmfStateValue.newValueString(processName); + ss.updateOngoingState(value, quark); + + /* + * Remove the process and all its sub-attributes from the + * current state + */ + quark = ss.getQuarkAbsoluteAndAdd("Threads", tid.toString()); + ss.removeAttribute(ts, quark); + break; + + case 10: // "sched_process_free": + /* Fields: string comm, int32 tid, int32 prio */ + break; + + // FIXME Not available with CTF. Use event context? + // case LTT_EVENT_EXEC: + // filename = new String((byte[]) event.getField(0)); + // + // /* Change the Exec_name of the process */ + // quark = ss.getQuarkRelativePath(true, currentThreadNode, + // "Exec_name"); + // ss.modifyAttribute(ts, filename, quark); + // break; + + default: + /* Other event types not covered by the main switch */ + + if (eventName.startsWith("sys_") + || eventName.startsWith("compat_sys_")) { + /* + * This is a replacement for the old sys_enter event. Now + * syscall names are listed into the event type + */ + + /* + * Push the syscall name on the Exec_mode_stack of the + * relevant PID + */ + quark = ss.getQuarkRelativeAndAdd(currentThreadNode, + "Exec_mode_stack"); + value = TmfStateValue.newValueString(eventName); + ss.pushAttribute(ts, value, quark); + } + + break; + } // End of switch + + /* + * Statistics + */ + + /* Nb of events total */ + try { + quark = ss.getQuarkAbsoluteAndAdd("Stats", "Event_types", + eventName); + ss.incrementAttribute(ts, quark); + + // /* Nb of events per CPU */ + // ss.incrementAttribute(ts, + // ss.getAttributeQuarkAndAdd(currentCPUNode, "Stats", + // "Event_types", eventType.toString())); + // + // /* Nb of events per process */ + // ss.incrementAttribute(ts, + // ss.getAttributeQuarkAndAdd(currentThreadNode, "Stats", + // "Event_types", eventType.toString())); + + } catch (StateValueTypeException sve) { + /* + * Here's hoping we don't have string values in statistics + * attributes... + */ + sve.printStackTrace(); + } + + // end of big non-indented try + } catch (AttributeNotFoundException ae) { + /* + * This would indicate a problem with the logic of the manager here, + * so it shouldn't happen. + */ + ae.printStackTrace(); + + } catch (TimeRangeException tre) { + /* + * This would happen if the events in the trace aren't ordered + * chronologically, which should never be the case ... + */ + System.err.println("TimeRangeExcpetion caught in the state system's event manager."); + System.err.println("Are the events in the trace correctly ordered?"); + tre.printStackTrace(); + + } catch (StateValueTypeException sve) { + /* + * This would happen if we were trying to push/pop attributes not of + * type integer. Which, once again, should never happen. + */ + sve.printStackTrace(); + } + + } + + @SuppressWarnings("nls") + private static HashMap<String, Integer> fillEventNames() { + /* + * TODO Replace with straight strings in the switch/case once we move to + * Java 7 + */ + /* + * This is still, imo, cleaner than the wtf-were-they-thinking Java + * Enums + */ + HashMap<String, Integer> map = new HashMap<String, Integer>(); + + map.put("exit_syscall", 1); + map.put("irq_handler_entry", 2); + map.put("irq_handler_exit", 3); + map.put("softirq_entry", 4); + map.put("softirq_exit", 5); + map.put("softirq_raise", 6); + map.put("sched_switch", 7); + map.put("sched_process_fork", 8); + map.put("sched_process_exit", 9); + map.put("sched_process_free", 10); + + return map; + } + + private int getEventIndex(String eventName) { + Integer ret = knownEventNames.get(eventName); + return (ret != null) ? ret : -1; + } + + /* Process status */ + private final static int STATE_PROCESS_STATUS_WAIT_CPU = 1; + private final static int STATE_PROCESS_STATUS_RUN = 2; +} diff --git a/lttng/org.eclipse.linuxtools.lttng2.kernel.core/src/org/eclipse/linuxtools/internal/lttng2/kernel/core/stateprovider/CTFKernelStateInput.java b/lttng/org.eclipse.linuxtools.lttng2.kernel.core/src/org/eclipse/linuxtools/internal/lttng2/kernel/core/stateprovider/CTFKernelStateInput.java new file mode 100644 index 0000000..f279599 --- a/dev/null +++ b/lttng/org.eclipse.linuxtools.lttng2.kernel.core/src/org/eclipse/linuxtools/internal/lttng2/kernel/core/stateprovider/CTFKernelStateInput.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson + * Copyright (c) 2010, 2011 École Polytechnique de Montréal + * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com> + * + * 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.linuxtools.internal.lttng2.kernel.core.stateprovider; + +import java.io.IOException; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; + +import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfIterator; +import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfEvent; +import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTrace; +import org.eclipse.linuxtools.tmf.core.statesystem.StateSystem; +import org.eclipse.linuxtools.tmf.core.statesystem.helpers.IStateChangeInput; + +/** + * This is the state change input plugin for TMF's state system which handles + * the LTTng 2.0 kernel traces in CTF format. + * + * It uses the reference handler defined in CTFKernelHandler.java. + * + * @author alexmont + * + */ +public class CTFKernelStateInput implements IStateChangeInput { + + final static int EVENTS_QUEUE_SIZE = 10000; + + private final BlockingQueue<CtfTmfEvent> eventsQueue; + + private final CtfIterator traceReader; + private final CTFKernelHandler eventHandler; + + private final Thread eventHandlerThread; + + private boolean ssAssigned; + + /** + * Instantiate a new state provider plugin. + * + * @param traceFile + * The LTTng 2.0 kernel trace directory + * @throws IOException + * If the directory was not found, or not recognized as a CTF + * trace. + */ + public CTFKernelStateInput(CtfTmfTrace trace) { + eventsQueue = new ArrayBlockingQueue<CtfTmfEvent>(EVENTS_QUEUE_SIZE); + traceReader = new CtfIterator(trace); + eventHandler = new CTFKernelHandler(eventsQueue); + ssAssigned = false; + + eventHandlerThread = new Thread(eventHandler, + "CTF Kernel Event Handler"); //$NON-NLS-1$ + } + + @Override + public void run() { + if (!ssAssigned) { + System.err.println("Cannot start Input thread without a target state system"); //$NON-NLS-1$ + return; + } + + CtfTmfEvent currentEvent; + + eventHandlerThread.start(); + + try { + currentEvent = traceReader.getCurrentEvent(); + while (currentEvent != null) { + traceReader.advance(); + eventsQueue.put(currentEvent); + currentEvent = traceReader.getCurrentEvent(); + } + /* + * We're done reading the trace, insert a null event in the queue to + * stop the handler + */ + eventsQueue.put(CtfTmfEvent.getNullEvent()); + eventHandlerThread.join(); + + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + @Override + public void assignTargetStateSystem(StateSystem ss) { + eventHandler.assignStateSystem(ss); + ssAssigned = true; + } + + @Override + public StateSystem getStateSystem() { + return eventHandler.getStateSystem(); + } + + @Override + public long getStartTime() { + return traceReader.getCtfTmfTrace().getStartTime().getValue(); + } +} |

