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
--- /dev/null
+/*******************************************************************************
+ * 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());
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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();
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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")));
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * 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();
+ }
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * 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 });
+ }
+}
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"
--- /dev/null
+/*******************************************************************************
+ * 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;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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;
+}
--- /dev/null
+/*******************************************************************************
+ * 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();
+ }
+}