From 500d5c41f4d6b981af620ca93c9b356936bc6294 Mon Sep 17 00:00:00 2001
From: Guilliano Molaire
Date: Wed, 23 Apr 2014 12:51:11 -0400
Subject: [PATCH] TMF: Possibility to generate a session configuration from a
ISessionInfo
With this feature we are able to generate a XML session configuration which
can be used to recreate a trace session on the target side.
Change-Id: I9786f322842b5166376f67d522907fa6bdc84edb
Signed-off-by: Guilliano Molaire
Reviewed-on: https://git.eclipse.org/r/23425
Tested-by: Hudson CI
Reviewed-by: Matthew Khouzam
Reviewed-by: Genevieve Bastien
Tested-by: Genevieve Bastien
---
.../META-INF/MANIFEST.MF | 3 +-
.../lttng2/core/tests/AllTests.java | 3 +-
.../lttng2/core/tests/session/AllTests.java | 26 +
.../session/SessionConfigGeneratorTest.java | 155 +++++
.../test_invalid.lttng | 55 ++
.../test_valid.lttng | 56 ++
.../META-INF/MANIFEST.MF | 3 +-
.../lttng2/core/session/Messages.java | 46 ++
.../core/session/SessionConfigGenerator.java | 539 ++++++++++++++++++
.../lttng2/core/session/messages.properties | 23 +
.../lttng2/core/session/session.xsd | 295 ++++++++++
11 files changed, 1201 insertions(+), 3 deletions(-)
create mode 100644 org.eclipse.linuxtools.lttng2.core.tests/src/org/eclipse/linuxtools/lttng2/core/tests/session/AllTests.java
create mode 100644 org.eclipse.linuxtools.lttng2.core.tests/src/org/eclipse/linuxtools/lttng2/core/tests/session/SessionConfigGeneratorTest.java
create mode 100644 org.eclipse.linuxtools.lttng2.core.tests/test_session_config_files/test_invalid.lttng
create mode 100644 org.eclipse.linuxtools.lttng2.core.tests/test_session_config_files/test_valid.lttng
create mode 100644 org.eclipse.linuxtools.lttng2.core/src/org/eclipse/linuxtools/lttng2/core/session/Messages.java
create mode 100644 org.eclipse.linuxtools.lttng2.core/src/org/eclipse/linuxtools/lttng2/core/session/SessionConfigGenerator.java
create mode 100644 org.eclipse.linuxtools.lttng2.core/src/org/eclipse/linuxtools/lttng2/core/session/messages.properties
create mode 100644 org.eclipse.linuxtools.lttng2.core/src/org/eclipse/linuxtools/lttng2/core/session/session.xsd
diff --git a/org.eclipse.linuxtools.lttng2.core.tests/META-INF/MANIFEST.MF b/org.eclipse.linuxtools.lttng2.core.tests/META-INF/MANIFEST.MF
index ebfb28e627..5497d26999 100644
--- a/org.eclipse.linuxtools.lttng2.core.tests/META-INF/MANIFEST.MF
+++ b/org.eclipse.linuxtools.lttng2.core.tests/META-INF/MANIFEST.MF
@@ -9,6 +9,7 @@ Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Require-Bundle: org.junit;bundle-version="4.0.0",
org.eclipse.core.runtime,
- org.eclipse.linuxtools.lttng2.core;bundle-version="3.0.0"
+ org.eclipse.linuxtools.lttng2.core;bundle-version="3.0.0",
+ org.eclipse.linuxtools.tmf.core;bundle-version="3.0.0"
Export-Package: org.eclipse.linuxtools.lttng2.core.tests;x-friends:="org.eclipse.linuxtools.lttng.alltests",
org.eclipse.linuxtools.lttng2.core.tests.control.model.impl;x-internal:=true
diff --git a/org.eclipse.linuxtools.lttng2.core.tests/src/org/eclipse/linuxtools/lttng2/core/tests/AllTests.java b/org.eclipse.linuxtools.lttng2.core.tests/src/org/eclipse/linuxtools/lttng2/core/tests/AllTests.java
index 6248314ea8..41ff5dcaae 100644
--- a/org.eclipse.linuxtools.lttng2.core.tests/src/org/eclipse/linuxtools/lttng2/core/tests/AllTests.java
+++ b/org.eclipse.linuxtools.lttng2.core.tests/src/org/eclipse/linuxtools/lttng2/core/tests/AllTests.java
@@ -22,7 +22,8 @@ import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
ActivatorTest.class,
- org.eclipse.linuxtools.lttng2.core.tests.control.model.impl.AllTests.class
+ org.eclipse.linuxtools.lttng2.core.tests.control.model.impl.AllTests.class,
+ org.eclipse.linuxtools.lttng2.core.tests.session.AllTests.class
})
public class AllTests {
diff --git a/org.eclipse.linuxtools.lttng2.core.tests/src/org/eclipse/linuxtools/lttng2/core/tests/session/AllTests.java b/org.eclipse.linuxtools.lttng2.core.tests/src/org/eclipse/linuxtools/lttng2/core/tests/session/AllTests.java
new file mode 100644
index 0000000000..985e99cd69
--- /dev/null
+++ b/org.eclipse.linuxtools.lttng2.core.tests/src/org/eclipse/linuxtools/lttng2/core/tests/session/AllTests.java
@@ -0,0 +1,26 @@
+/**********************************************************************
+ * Copyright (c) 2014 Ã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
+ *
+ * Contributors:
+ * Guilliano Molaire - Initial API and implementation
+ *********************************************************************/
+package org.eclipse.linuxtools.lttng2.core.tests.session;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * Run all the tests in the lttng2.core.session plugin.
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ SessionConfigGeneratorTest.class
+})
+public class AllTests {
+
+}
diff --git a/org.eclipse.linuxtools.lttng2.core.tests/src/org/eclipse/linuxtools/lttng2/core/tests/session/SessionConfigGeneratorTest.java b/org.eclipse.linuxtools.lttng2.core.tests/src/org/eclipse/linuxtools/lttng2/core/tests/session/SessionConfigGeneratorTest.java
new file mode 100644
index 0000000000..78fb9ea68f
--- /dev/null
+++ b/org.eclipse.linuxtools.lttng2.core.tests/src/org/eclipse/linuxtools/lttng2/core/tests/session/SessionConfigGeneratorTest.java
@@ -0,0 +1,155 @@
+/**********************************************************************
+ * Copyright (c) 2014 Ã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
+ *
+ * Contributors:
+ * Guilliano Molaire - Initial API and implementation
+ *********************************************************************/
+package org.eclipse.linuxtools.lttng2.core.tests.session;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.linuxtools.internal.lttng2.core.Activator;
+import org.eclipse.linuxtools.internal.lttng2.core.control.model.IDomainInfo;
+import org.eclipse.linuxtools.internal.lttng2.core.control.model.ISessionInfo;
+import org.eclipse.linuxtools.internal.lttng2.core.control.model.TraceSessionState;
+import org.eclipse.linuxtools.internal.lttng2.core.control.model.impl.BufferType;
+import org.eclipse.linuxtools.internal.lttng2.core.control.model.impl.SessionInfo;
+import org.eclipse.linuxtools.lttng2.core.session.SessionConfigGenerator;
+import org.eclipse.linuxtools.lttng2.core.session.SessionConfigStrings;
+import org.eclipse.linuxtools.lttng2.core.tests.control.model.impl.ModelImplFactory;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * This class contains tests for the class {@link SessionConfigGenerator}.
+ */
+public class SessionConfigGeneratorTest {
+
+ // ------------------------------------------------------------------------
+ // Test data
+ // ------------------------------------------------------------------------
+
+ /** Session files for validation */
+ private static final File VALID_SESSION_FILE = new File("../org.eclipse.linuxtools.lttng2.core.tests/test_session_config_files/test_valid.lttng");
+ private static final File INVALID_SESSION_FILE = new File("../org.eclipse.linuxtools.lttng2.core.tests/test_session_config_files/test_invalid.lttng");
+
+ private static final String SESSION_FILENAME = "test_session." + SessionConfigStrings.SESSION_CONFIG_FILE_EXTENSION;
+ private static final IPath SESSION_FILE_PATH = Activator.getDefault().getStateLocation().addTrailingSeparator().append(SESSION_FILENAME);
+ private static final String TRACE_SESSION_PATH = "/home/user/folder";
+
+ private static final String SESSION_NAME_1 = "session1";
+ private static final String SESSION_NAME_2 = "session2";
+ private static final String SESSION_NAME_3 = "session3";
+
+ /** Session informations for generation tests */
+ private ISessionInfo fValidSessionInfo = null;
+ private ISessionInfo fValidSessionSnapshotInfo = null;
+ private ISessionInfo fInvalidSessionInfo = null;
+
+ // ------------------------------------------------------------------------
+ // Housekeeping
+ // ------------------------------------------------------------------------
+ /**
+ * Perform pre-test initialization.
+ */
+ @Before
+ public void setUp() {
+ /* A valid domain with shared buffer type */
+ ModelImplFactory factory = new ModelImplFactory();
+ IDomainInfo domain = factory.getDomainInfo1();
+ domain.setBufferType(BufferType.BUFFER_SHARED);
+
+ /* The valid sessions */
+ fValidSessionInfo = new SessionInfo(SESSION_NAME_1);
+ fValidSessionInfo.setSessionPath(TRACE_SESSION_PATH);
+ fValidSessionInfo.setSessionState(TraceSessionState.ACTIVE);
+ fValidSessionInfo.addDomain(domain);
+
+ fValidSessionSnapshotInfo = new SessionInfo(SESSION_NAME_2);
+ fValidSessionSnapshotInfo.setSessionPath(TRACE_SESSION_PATH);
+ fValidSessionSnapshotInfo.setSessionState(TraceSessionState.ACTIVE);
+ fValidSessionSnapshotInfo.addDomain(domain);
+ fValidSessionSnapshotInfo.setSnapshotInfo(factory.getSnapshotInfo1());
+
+ /* The invalid session contains an event with an invalid type */
+ fInvalidSessionInfo = factory.getSessionInfo2();
+ fInvalidSessionInfo.setName(SESSION_NAME_3);
+ }
+
+ /**
+ * Delete the session file created
+ */
+ @After
+ public void tearUp() {
+ /* Tear up the file created if it exists */
+ File sessionConfigurationFile = SESSION_FILE_PATH.toFile();
+ if (sessionConfigurationFile.exists()) {
+ sessionConfigurationFile.delete();
+ }
+
+ }
+
+ // ------------------------------------------------------------------------
+ // Tests
+ // ------------------------------------------------------------------------
+
+ /**
+ * Test method for {@link SessionConfigGenerator#sessionValidate(File)}
+ */
+ @Test
+ public void testSessionValidate() {
+ File testSessionFile = VALID_SESSION_FILE;
+ if ((testSessionFile == null) || !testSessionFile.exists()) {
+ fail("Session test file does not exist");
+ }
+ IStatus status = SessionConfigGenerator.sessionValidate(testSessionFile);
+ if (!status.isOK()) {
+ fail(status.getMessage());
+ }
+
+ testSessionFile = INVALID_SESSION_FILE;
+ if ((testSessionFile == null) || !testSessionFile.exists()) {
+ fail("Session test file does not exist");
+ }
+ assertFalse(SessionConfigGenerator.sessionValidate(testSessionFile).isOK());
+ }
+
+ /**
+ * Test method for
+ * {@link SessionConfigGenerator#generateSessionConfig(Set, IPath)}
+ */
+ @Test
+ public void testGenerateSessionConfig() {
+ /* Should fail since it's empty */
+ final Set sessions = new HashSet<>();
+ assertFalse(SessionConfigGenerator.generateSessionConfig(sessions, SESSION_FILE_PATH).isOK());
+
+ /* Add a valid session and validate */
+ sessions.add(fValidSessionInfo);
+ assertTrue(SessionConfigGenerator.generateSessionConfig(sessions, SESSION_FILE_PATH).isOK());
+ assertTrue(SessionConfigGenerator.sessionValidate(SESSION_FILE_PATH.toFile()).isOK());
+
+ /* Add a valid snapshot session and validate */
+ sessions.add(fValidSessionSnapshotInfo);
+ assertTrue(SessionConfigGenerator.generateSessionConfig(sessions, SESSION_FILE_PATH).isOK());
+ assertTrue(SessionConfigGenerator.sessionValidate(SESSION_FILE_PATH.toFile()).isOK());
+
+ /* Add an invalid session */
+ sessions.add(fInvalidSessionInfo);
+ assertFalse(SessionConfigGenerator.generateSessionConfig(sessions, SESSION_FILE_PATH).isOK());
+ }
+}
diff --git a/org.eclipse.linuxtools.lttng2.core.tests/test_session_config_files/test_invalid.lttng b/org.eclipse.linuxtools.lttng2.core.tests/test_session_config_files/test_invalid.lttng
new file mode 100644
index 0000000000..d13f485874
--- /dev/null
+++ b/org.eclipse.linuxtools.lttng2.core.tests/test_session_config_files/test_invalid.lttng
@@ -0,0 +1,55 @@
+
+
+
+
+ auto-20140323-130527
+ false
+
+
+ GLOBAL
+
+
+ channel0
+ DISCARD
+ 4
+ 0
+ 0
+ 0
+ 0
+ false
+ 262144
+ 200000
+ SPLICE
+
+
+ exit_syscall
+ true
+ TRACEPOINT
+
+
+
+
+
+
+
+
+
diff --git a/org.eclipse.linuxtools.lttng2.core.tests/test_session_config_files/test_valid.lttng b/org.eclipse.linuxtools.lttng2.core.tests/test_session_config_files/test_valid.lttng
new file mode 100644
index 0000000000..4dea4df351
--- /dev/null
+++ b/org.eclipse.linuxtools.lttng2.core.tests/test_session_config_files/test_valid.lttng
@@ -0,0 +1,56 @@
+
+
+
+
+ auto-20140323-130527
+ false
+
+
+ KERNEL
+ GLOBAL
+
+
+ channel0
+ DISCARD
+ 4
+ 0
+ 0
+ 0
+ 0
+ false
+ 262144
+ 200000
+ SPLICE
+
+
+ exit_syscall
+ true
+ TRACEPOINT
+
+
+
+
+
+
+
+
+
diff --git a/org.eclipse.linuxtools.lttng2.core/META-INF/MANIFEST.MF b/org.eclipse.linuxtools.lttng2.core/META-INF/MANIFEST.MF
index 94c7cbe27f..744585be53 100644
--- a/org.eclipse.linuxtools.lttng2.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.linuxtools.lttng2.core/META-INF/MANIFEST.MF
@@ -8,7 +8,8 @@ Bundle-SymbolicName: org.eclipse.linuxtools.lttng2.core;singleton:=true
Bundle-Activator: org.eclipse.linuxtools.internal.lttng2.core.Activator
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Require-Bundle: org.eclipse.core.runtime
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.linuxtools.tmf.core;bundle-version="3.0.0"
Export-Package: org.eclipse.linuxtools.internal.lttng2.core;x-friends:="org.eclipse.linuxtools.lttng2.core.tests",
org.eclipse.linuxtools.internal.lttng2.core.control.model;x-friends:="org.eclipse.linuxtools.lttng2.ui,org.eclipse.linuxtools.lttng2.ui.tests,org.eclipse.linuxtools.lttng2.core.tests",
org.eclipse.linuxtools.internal.lttng2.core.control.model.impl;x-friends:="org.eclipse.linuxtools.lttng2.ui,org.eclipse.linuxtools.lttng2.ui.tests,org.eclipse.linuxtools.lttng2.core.tests",
diff --git a/org.eclipse.linuxtools.lttng2.core/src/org/eclipse/linuxtools/lttng2/core/session/Messages.java b/org.eclipse.linuxtools.lttng2.core/src/org/eclipse/linuxtools/lttng2/core/session/Messages.java
new file mode 100644
index 0000000000..b58bd33986
--- /dev/null
+++ b/org.eclipse.linuxtools.lttng2.core/src/org/eclipse/linuxtools/lttng2/core/session/Messages.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Ã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
+ *
+ * Contributors:
+ * Guilliano Molaire - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng2.core.session;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Externalized message strings from the lttng2.core.control.session
+ *
+ * @author Guilliano Molaire
+ * @since 3.0
+ */
+@SuppressWarnings("javadoc")
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.linuxtools.lttng2.core.control.session.messages"; //$NON-NLS-1$
+
+ public static String SessionConfigXML_BadRequirementType;
+ public static String SessionConfigXML_DomainTypeMissing;
+ public static String SessionConfigXML_EventTypeMissing;
+ public static String SessionConfigXML_InvalidSessionInfoList;
+ public static String SessionConfigXML_InvalidTraceSessionPath;
+ public static String SessionConfigXML_UnknownEventType;
+ public static String SessionConfigXML_UnknownDomainBufferType;
+ public static String SessionConfigXML_SessionConfigGenerationError;
+ public static String SessionConfigXML_XmlParseError;
+ public static String SessionConfigXML_XmlValidateError;
+ public static String SessionConfigXML_XmlValidationError;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
diff --git a/org.eclipse.linuxtools.lttng2.core/src/org/eclipse/linuxtools/lttng2/core/session/SessionConfigGenerator.java b/org.eclipse.linuxtools.lttng2.core/src/org/eclipse/linuxtools/lttng2/core/session/SessionConfigGenerator.java
new file mode 100644
index 0000000000..692862eb36
--- /dev/null
+++ b/org.eclipse.linuxtools.lttng2.core/src/org/eclipse/linuxtools/lttng2/core/session/SessionConfigGenerator.java
@@ -0,0 +1,539 @@
+/**********************************************************************
+ * Copyright (c) 2014 Ã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
+ *
+ * Contributors:
+ * Guilliano Molaire - Initial API and implementation
+ *********************************************************************/
+package org.eclipse.linuxtools.lttng2.core.session;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Set;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.linuxtools.internal.lttng2.core.Activator;
+import org.eclipse.linuxtools.internal.lttng2.core.control.model.IChannelInfo;
+import org.eclipse.linuxtools.internal.lttng2.core.control.model.IDomainInfo;
+import org.eclipse.linuxtools.internal.lttng2.core.control.model.IEventInfo;
+import org.eclipse.linuxtools.internal.lttng2.core.control.model.ISessionInfo;
+import org.eclipse.linuxtools.internal.lttng2.core.control.model.TraceEnablement;
+import org.eclipse.linuxtools.internal.lttng2.core.control.model.TraceEventType;
+import org.eclipse.linuxtools.internal.lttng2.core.control.model.TraceLogLevel;
+import org.eclipse.linuxtools.internal.lttng2.core.control.model.TraceSessionState;
+import org.eclipse.osgi.util.NLS;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * Class for generating a session configuration file. A session configuration is
+ * used to configure a trace session. It is a XML formatted file that contains
+ * values defining the behavior of that specific trace session.
+ *
+ * Kernel session configuration example:
+ *
+ *
+ * {@code
+ *
+ *
+ * test_kernel
+ *
+ *
+ * KERNEL
+ * GLOBAL
+ *
+ *
+ * channel0
+ * false
+ * DISCARD
+ * 262144
+ * 4
+ * 0
+ * 200000
+ * SPLICE
+ * 0
+ * 0
+ * 0
+ *
+ *
+ * true
+ * SYSCALL
+ *
+ *
+ * snd_soc_cache_sync
+ * true
+ * TRACEPOINT
+ *
+ *
+ *
+ *
+ *
+ *
+ * false
+ *
+ *
+ *
+ * }
+ *
+ *
+ *
+ *
+ * @author Guilliano Molaire
+ * @since 3.0
+ */
+public final class SessionConfigGenerator {
+
+ /** The name of the session schema */
+ private static final String SESSION_XSD_FILENAME = "session.xsd"; //$NON-NLS-1$
+
+ /** The indent size used for the session configuration XML file */
+ private static final String INDENT_AMOUNT_PROPERTY_NAME = "{http://xml.apache.org/xslt}indent-amount"; //$NON-NLS-1$
+ private static final String INDENT_AMOUNT_PROPERTY_VALUE = "4"; //$NON-NLS-1$
+
+ /**
+ * Private constructor. The class should not be instantiated.
+ */
+ private SessionConfigGenerator() {
+ }
+
+ // ---------------------------------------------------------
+ // Methods to generate session configuration files
+ // ---------------------------------------------------------
+
+ /**
+ * Generates a session configuration file from a set of session information.
+ *
+ * @param sessions
+ * The session informations
+ * @param sessionFileDestination
+ * The path of the locally saved session configuration file
+ * @return The status of the session configuration generation
+ */
+ public static IStatus generateSessionConfig(Set sessions, IPath sessionFileDestination) {
+ /* Parameters validation */
+ if (sessions == null || sessions.isEmpty()) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.SessionConfigXML_InvalidSessionInfoList);
+ } else if (sessionFileDestination == null) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.SessionConfigXML_InvalidTraceSessionPath);
+ }
+
+ /* Generate the session configuration file */
+ try {
+ Document sessionConfigDocument = generateSessionConfig(sessions);
+
+ if (sessionConfigDocument != null) {
+ saveSessionConfig(sessionConfigDocument, sessionFileDestination.toString());
+ } else {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.SessionConfigXML_SessionConfigGenerationError);
+ }
+ } catch (TransformerException | IllegalArgumentException | ParserConfigurationException e) {
+ Activator.getDefault().logError("Error generating the session configuration file: " + sessionFileDestination.toString(), e); //$NON-NLS-1$
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage());
+ }
+
+ return Status.OK_STATUS;
+ }
+
+ /**
+ * Generates a session configuration from a set of session informations.
+ *
+ * @param sessions
+ * The session informations
+ * @return The document with all session configuration nodes
+ * @throws IllegalArgumentException
+ * On an illegal argument inside sessions
+ * @throws ParserConfigurationException
+ * On an parser configuration error
+ */
+ private static Document generateSessionConfig(Iterable sessions) throws IllegalArgumentException, ParserConfigurationException {
+ DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+
+ Document document = docBuilder.newDocument();
+
+ Element rootElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_SESSIONS);
+ document.appendChild(rootElement);
+
+ for (ISessionInfo session : sessions) {
+ /* All elements under "sessions" elements */
+ Element sessionElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_SESSION);
+
+ /* Contents of session element */
+ String enabled = session.getSessionState().equals(TraceSessionState.ACTIVE) ? SessionConfigStrings.CONFIG_STRING_TRUE : SessionConfigStrings.CONFIG_STRING_FALSE;
+
+ addElementContent(document, sessionElement, SessionConfigStrings.CONFIG_ELEMENT_NAME, session.getName());
+ addElementContent(document, sessionElement, SessionConfigStrings.CONFIG_ELEMENT_STARTED, enabled);
+
+ if (session.isSnapshotSession()) {
+ /* If it's a snapshot, we must add an attribute telling it is */
+ Element attributesElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_ATTRIBUTES);
+ addElementContent(document, attributesElement, SessionConfigStrings.CONFIG_ELEMENT_SNAPSHOT_MODE, SessionConfigStrings.CONFIG_STRING_TRUE);
+ sessionElement.appendChild(attributesElement);
+ }
+
+ sessionElement.appendChild(getDomainsElement(document, session));
+ sessionElement.appendChild(getOutputElement(document, session));
+ rootElement.appendChild(sessionElement);
+ }
+
+ return document;
+ }
+
+ // ---------------------------------------------------------
+ // Getters for each element of the configuration file
+ // ---------------------------------------------------------
+
+ /**
+ * Gets the 'domains' element after creating it.
+ *
+ * @param document
+ * The document in which the nodes are being added
+ * @param session
+ * The session informations
+ * @return The domains element as an XML element
+ */
+ private static Element getDomainsElement(Document document, ISessionInfo session) {
+ Element domainsElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_DOMAINS);
+
+ for (IDomainInfo domain : session.getDomains()) {
+ Element domainElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_DOMAIN);
+
+ /*
+ * Add everything specific to a domain
+ *
+ * TODO: We suppose here that domain is either kernel or UST. It
+ * will have to change if other domains are supported
+ */
+ String domainType = domain.isKernel() ? SessionConfigStrings.CONFIG_DOMAIN_TYPE_KERNEL : SessionConfigStrings.CONFIG_DOMAIN_TYPE_UST;
+ addElementContent(document, domainElement, SessionConfigStrings.CONFIG_ELEMENT_TYPE, domainType);
+
+ String bufferType = null;
+ switch (domain.getBufferType()) {
+ case BUFFER_PER_UID:
+ bufferType = SessionConfigStrings.CONFIG_BUFFER_TYPE_PER_UID;
+ break;
+ case BUFFER_PER_PID:
+ bufferType = SessionConfigStrings.CONFIG_BUFFER_TYPE_PER_PID;
+ break;
+ case BUFFER_SHARED:
+ bufferType = SessionConfigStrings.CONFIG_BUFFER_TYPE_GLOBAL;
+ break;
+ case BUFFER_TYPE_UNKNOWN:
+ default:
+ throw new IllegalArgumentException(Messages.SessionConfigXML_UnknownDomainBufferType);
+ }
+ addElementContent(document, domainElement, SessionConfigStrings.CONFIG_ELEMENT_DOMAIN_BUFFER_TYPE, bufferType);
+
+ /* Add the channels */
+ domainElement.appendChild(getChannelsElement(document, domain.isKernel(), domain.getChannels()));
+ domainsElement.appendChild(domainElement);
+ }
+
+ return domainsElement;
+ }
+
+ /**
+ * Gets the 'output' element after creating it. If the session is a
+ * snapshot, it will be composed of a snapshot outputs element. Otherwise,
+ * it will contain the consumer output element.
+ *
+ * @param document
+ * The document in which the nodes are being added
+ * @param session
+ * The session informations
+ * @return The output element as an XML node
+ */
+ private static Element getOutputElement(Document document, ISessionInfo session) {
+ Element outputElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_OUTPUT);
+
+ if (session.isSnapshotSession()) {
+ outputElement.appendChild(getSnapshotOuputsElement(document, session));
+ } else if (session.isStreamedTrace()) {
+ outputElement.appendChild(getNetOutputElement(document, session));
+ } else {
+ outputElement.appendChild(getConsumerOutputElement(document, session));
+ }
+
+ return outputElement;
+ }
+
+ /**
+ * Gets the 'channels' element after creating it.
+ *
+ * @param document
+ * The document in which the nodes are being added
+ * @param isKernel
+ * Is it a kernel domain type
+ * @param channels
+ * The channels to be added as elements
+ * @return The channels element as an XML element
+ */
+ private static Element getChannelsElement(Document document, boolean isKernel, IChannelInfo[] channels) {
+ Element channelsElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_CHANNELS);
+
+ for (IChannelInfo channel : channels) {
+ Element channelElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_CHANNEL);
+
+ /* Add everything related to a channel */
+ addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_NAME, channel.getName());
+
+ String overwriteMode = channel.isOverwriteMode() ? SessionConfigStrings.CONFIG_OVERWRITE_MODE_OVERWRITE : SessionConfigStrings.CONFIG_OVERWRITE_MODE_DISCARD;
+ String enabled = channel.getState().equals(TraceEnablement.ENABLED) ? SessionConfigStrings.CONFIG_STRING_TRUE : SessionConfigStrings.CONFIG_STRING_FALSE;
+
+ addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_ENABLED, enabled);
+ addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_OVERWRITE_MODE, overwriteMode);
+ addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_SUBBUFFER_SIZE, channel.getSubBufferSize());
+ addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_SUBBUFFER_COUNT, channel.getNumberOfSubBuffers());
+ addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_SWITCH_TIMER_INTERVAL, channel.getSwitchTimer());
+ addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_READ_TIMER_INTERVAL, channel.getReadTimer());
+
+ String outputType = channel.getOutputType().startsWith(SessionConfigStrings.CONFIG_OUTPUT_TYPE_MMAP) ?
+ outputType = SessionConfigStrings.CONFIG_OUTPUT_TYPE_MMAP : SessionConfigStrings.CONFIG_OUTPUT_TYPE_SPLICE;
+ addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_OUTPUT_TYPE, outputType);
+ addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_TRACEFILE_SIZE, channel.getMaxSizeTraceFiles());
+ addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_TRACEFILE_COUNT, channel.getMaxNumberTraceFiles());
+
+ /*
+ * TODO: Replace the 0 value by the channel live timer property from
+ * SessionInfo once live session tracing is supported
+ */
+ addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_LIVE_TIMER_INTERVAL, SessionConfigStrings.CONFIG_STRING_ZERO);
+
+ /* Add the events */
+ channelElement.appendChild(getEventsElement(document, isKernel, channel.getEvents()));
+ channelsElement.appendChild(channelElement);
+ }
+
+ return channelsElement;
+ }
+
+ /**
+ * Gets the 'events' element after creating it. It is composed of the event
+ * informations from a list of IEventInfo.
+ *
+ * @param document
+ * The document in which the nodes are being added
+ * @param isKernel
+ * Is the domain type kernel
+ * @param events
+ * The event informations to be added
+ * @return An element containing all the event informations as XML elements
+ */
+ private static Element getEventsElement(Document document, boolean isKernel, IEventInfo[] events) {
+ Element eventsElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_EVENTS);
+
+ for (IEventInfo event : events) {
+ Element eventElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_EVENT);
+
+ /* Enabled attribute */
+ String enabled = event.getState().equals(TraceEnablement.ENABLED) ? SessionConfigStrings.CONFIG_STRING_TRUE : SessionConfigStrings.CONFIG_STRING_FALSE;
+
+ /* Add the attributes to the event node */
+ addElementContent(document, eventElement, SessionConfigStrings.CONFIG_ELEMENT_NAME, event.getName());
+ addElementContent(document, eventElement, SessionConfigStrings.CONFIG_ELEMENT_ENABLED, enabled);
+ TraceEventType eventType = event.getEventType();
+ if (!eventType.equals(TraceEventType.UNKNOWN)) {
+ addElementContent(document, eventElement, SessionConfigStrings.CONFIG_ELEMENT_TYPE, eventType.getInName().toUpperCase());
+ } else {
+ throw new IllegalArgumentException(Messages.SessionConfigXML_UnknownEventType);
+ }
+
+ /* Specific to UST session config: the log level */
+ if (!isKernel && !event.getLogLevel().equals(TraceLogLevel.LEVEL_UNKNOWN)) {
+ addElementContent(document, eventElement, SessionConfigStrings.CONFIG_ELEMENT_LOGLEVEL, event.getLogLevel().ordinal());
+ }
+
+ /* Add the node to the parent node events */
+ eventsElement.appendChild(eventElement);
+ }
+
+ return eventsElement;
+ }
+
+ /**
+ * Gets the 'consumer_output' element after creating it.
+ *
+ * @param document
+ * The document in which the nodes are being added
+ * @param session
+ * The session informations
+ * @return The consumer output element with his informations as XML elements
+ */
+ private static Element getConsumerOutputElement(Document document, ISessionInfo session) {
+ Element consumerOutputElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_CONSUMER_OUTPUT);
+ Element destinationElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_DESTINATION);
+
+ /* Value of consumer output element */
+ addElementContent(document, consumerOutputElement, SessionConfigStrings.CONFIG_ELEMENT_ENABLED, SessionConfigStrings.CONFIG_STRING_TRUE);
+
+ if (session.isStreamedTrace()) {
+ /* If it is a streamed session, add the net output element */
+ destinationElement.appendChild(getNetOutputElement(document, session));
+ } else {
+ addElementContent(document, destinationElement, SessionConfigStrings.CONFIG_ELEMENT_PATH, session.getSessionPath());
+ }
+
+ consumerOutputElement.appendChild(destinationElement);
+ return consumerOutputElement;
+ }
+
+ /**
+ * Gets the 'net_output' element after creating it. It is composed of the
+ * control and data URIs.
+ *
+ * @param document
+ * The document in which the nodes are being added
+ * @param session
+ * The session informations
+ * @return The net output element
+ */
+ private static Element getNetOutputElement(Document document, ISessionInfo session) {
+ Element netOutputElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_NET_OUTPUT);
+
+ String networkUrl = session.getNetworkUrl();
+ String controlUri = networkUrl == null ? session.getControlUrl() : networkUrl;
+ String dataUri = networkUrl == null ? session.getDataUrl() : networkUrl;
+ addElementContent(document, netOutputElement, SessionConfigStrings.CONFIG_ELEMENT_CONTROL_URI, controlUri);
+ addElementContent(document, netOutputElement, SessionConfigStrings.CONFIG_ELEMENT_DATA_URI, dataUri);
+
+ return netOutputElement;
+ }
+
+ /**
+ * Gets the 'snapshot_outputs' element after creating it.
+ *
+ * @param document
+ * The document in which the nodes are being added
+ * @param session
+ * The session informations
+ * @return The snapshot outputs element with snapshot informations as XML
+ * elements
+ */
+ private static Element getSnapshotOuputsElement(Document document, ISessionInfo session) {
+ Element snapshotOutputsElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_SNAPSHOT_OUTPUTS);
+ Element outputElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_OUTPUT);
+
+ /* Add the name of the snapshot and the max size element */
+ addElementContent(document, outputElement, SessionConfigStrings.CONFIG_ELEMENT_NAME, session.getSnapshotInfo().getName());
+
+ /*
+ * TODO: find the proper max size value of output element. For now it is
+ * set to the default 0 value which means unlimited for lttng.
+ */
+ addElementContent(document, outputElement, SessionConfigStrings.CONFIG_ELEMENT_MAX_SIZE, SessionConfigStrings.CONFIG_STRING_ZERO);
+ outputElement.appendChild(getConsumerOutputElement(document, session));
+
+ snapshotOutputsElement.appendChild(outputElement);
+ return snapshotOutputsElement;
+ }
+
+ // ---------------------------------------------------------
+ // Utilities
+ // ---------------------------------------------------------
+
+ /**
+ * Validates the session configuration file against its schema.
+ *
+ * @param sessionFile
+ * The session configuration file
+ * @return The status of the validation
+ */
+ public static IStatus sessionValidate(File sessionFile) {
+ URL url = SessionConfigGenerator.class.getResource(SESSION_XSD_FILENAME);
+ SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ Source xmlSource = new StreamSource(sessionFile);
+
+ try {
+ Schema schema = schemaFactory.newSchema(url);
+ Validator validator = schema.newValidator();
+ validator.validate(xmlSource);
+ } catch (SAXParseException e) {
+ String error = NLS.bind(Messages.SessionConfigXML_XmlParseError, e.getLineNumber(), e.getLocalizedMessage());
+ Activator.getDefault().logError(error);
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, error, e);
+ } catch (SAXException e) {
+ String error = NLS.bind(Messages.SessionConfigXML_XmlValidationError, e.getLocalizedMessage());
+ Activator.getDefault().logError(error);
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, error, e);
+ } catch (IOException e) {
+ String error = Messages.SessionConfigXML_XmlValidateError;
+ Activator.getDefault().logError("IO exception occurred", e); //$NON-NLS-1$
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, error, e);
+ }
+ return Status.OK_STATUS;
+ }
+
+ /**
+ * Saves the session configuration into a XML file.
+ *
+ * @param document
+ * The document representing the session configuration file
+ * @param destination
+ * The path of the locally saved session configuration file
+ * @throws TransformerException
+ * On an transformation process
+ */
+ private static void saveSessionConfig(Document document, String destination) throws TransformerException {
+ /* Write the content into a XML file */
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ Transformer transformer = transformerFactory.newTransformer();
+
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
+ transformer.setOutputProperty(INDENT_AMOUNT_PROPERTY_NAME, INDENT_AMOUNT_PROPERTY_VALUE);
+
+ DOMSource source = new DOMSource(document);
+ StreamResult result = new StreamResult(new File(destination));
+
+ transformer.transform(source, result);
+ }
+
+ /**
+ * Adds to a parent node an element with his content.
+ *
+ * @param document
+ * The document in which the nodes are being added
+ * @param parent
+ * The parent node that contains the element and his content
+ * @param elementName
+ * The element container name
+ * @param elementContent
+ * The content itself
+ */
+ private static void addElementContent(Document document, Element parent, String elementName, Object elementContent) {
+ Element contentElement = document.createElement(elementName);
+ contentElement.appendChild(document.createTextNode(elementContent.toString()));
+ parent.appendChild(contentElement);
+ }
+}
diff --git a/org.eclipse.linuxtools.lttng2.core/src/org/eclipse/linuxtools/lttng2/core/session/messages.properties b/org.eclipse.linuxtools.lttng2.core/src/org/eclipse/linuxtools/lttng2/core/session/messages.properties
new file mode 100644
index 0000000000..c0d252d198
--- /dev/null
+++ b/org.eclipse.linuxtools.lttng2.core/src/org/eclipse/linuxtools/lttng2/core/session/messages.properties
@@ -0,0 +1,23 @@
+###############################################################################
+# Copyright (c) 2014 É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
+#
+# Contributors:
+# Guilliano Molaire - Initial API and implementation
+###############################################################################
+
+SessionConfigXML_BadRequirementType=The requirement type is not supported
+SessionConfigXML_DomainTypeMissing=The domain requirement type is missing
+SessionConfigXML_EventTypeMissing=The event requirement type is missing
+SessionConfigXML_InvalidSessionInfoList=The list of session is empty or null
+SessionConfigXML_InvalidTraceSessionPath=The trace session path is not valid
+SessionConfigXML_UnknownEventType=The event type is not handled by the session configuration
+SessionConfigXML_UnknownDomainBufferType=The domain buffer type is not handled by the session configuration
+SessionConfigXML_SessionConfigGenerationError=An error occurred while generating the session configuration file
+SessionConfigXML_XmlParseError=XML Parsing error at line {0}: {1}
+SessionConfigXML_XmlValidateError=An error occurred while validating the XML file.
+SessionConfigXML_XmlValidationError=Error validating XML file {0}
diff --git a/org.eclipse.linuxtools.lttng2.core/src/org/eclipse/linuxtools/lttng2/core/session/session.xsd b/org.eclipse.linuxtools.lttng2.core/src/org/eclipse/linuxtools/lttng2/core/session/session.xsd
new file mode 100644
index 0000000000..7c3e9d8fc6
--- /dev/null
+++ b/org.eclipse.linuxtools.lttng2.core/src/org/eclipse/linuxtools/lttng2/core/session/session.xsd
@@ -0,0 +1,295 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--
2.34.1