lttng.control: remove useless data assignment
[deliverable/tracecompass.git] / lttng / org.eclipse.tracecompass.lttng2.control.core / src / org / eclipse / tracecompass / lttng2 / control / core / session / SessionConfigGenerator.java
1 /**********************************************************************
2 * Copyright (c) 2014 École Polytechnique de Montréal
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Guilliano Molaire - Initial API and implementation
11 *********************************************************************/
12 package org.eclipse.tracecompass.lttng2.control.core.session;
13
14 import java.io.File;
15 import java.io.IOException;
16 import java.net.URL;
17 import java.util.Set;
18
19 import javax.xml.XMLConstants;
20 import javax.xml.parsers.DocumentBuilder;
21 import javax.xml.parsers.DocumentBuilderFactory;
22 import javax.xml.parsers.ParserConfigurationException;
23 import javax.xml.transform.OutputKeys;
24 import javax.xml.transform.Source;
25 import javax.xml.transform.Transformer;
26 import javax.xml.transform.TransformerException;
27 import javax.xml.transform.TransformerFactory;
28 import javax.xml.transform.dom.DOMSource;
29 import javax.xml.transform.stream.StreamResult;
30 import javax.xml.transform.stream.StreamSource;
31 import javax.xml.validation.Schema;
32 import javax.xml.validation.SchemaFactory;
33 import javax.xml.validation.Validator;
34
35 import org.eclipse.core.runtime.IPath;
36 import org.eclipse.core.runtime.IStatus;
37 import org.eclipse.core.runtime.Status;
38 import org.eclipse.jdt.annotation.NonNull;
39 import org.eclipse.osgi.util.NLS;
40 import org.eclipse.tracecompass.internal.lttng2.control.core.Activator;
41 import org.eclipse.tracecompass.internal.lttng2.control.core.model.TraceDomainType;
42 import org.eclipse.tracecompass.internal.lttng2.control.core.model.IChannelInfo;
43 import org.eclipse.tracecompass.internal.lttng2.control.core.model.IDomainInfo;
44 import org.eclipse.tracecompass.internal.lttng2.control.core.model.IEventInfo;
45 import org.eclipse.tracecompass.internal.lttng2.control.core.model.ISessionInfo;
46 import org.eclipse.tracecompass.internal.lttng2.control.core.model.TraceEnablement;
47 import org.eclipse.tracecompass.internal.lttng2.control.core.model.TraceEventType;
48 import org.eclipse.tracecompass.internal.lttng2.control.core.model.TraceLogLevel;
49 import org.eclipse.tracecompass.internal.lttng2.control.core.model.TraceSessionState;
50 import org.w3c.dom.Document;
51 import org.w3c.dom.Element;
52 import org.xml.sax.SAXException;
53 import org.xml.sax.SAXParseException;
54
55 /**
56 * Class for generating a session configuration file. A session configuration is
57 * used to configure a trace session. It is a XML formatted file that contains
58 * values defining the behavior of that specific trace session.
59 * <p>
60 * Kernel session configuration example:
61 *
62 * <pre>
63 * {@code
64 * <sessions>
65 * <session>
66 * <name>test_kernel</name>
67 * <domains>
68 * <domain>
69 * <type>KERNEL</type>
70 * <buffer_type>GLOBAL</buffer_type>
71 * <channels>
72 * <channel>
73 * <name>channel0</name>
74 * <enabled>false</enabled>
75 * <overwrite_mode>DISCARD</overwrite_mode>
76 * <subbuffer_size>262144</subbuffer_size>
77 * <subbuffer_count>4</subbuffer_count>
78 * <switch_timer_interval>0</switch_timer_interval>
79 * <read_timer_interval>200000</read_timer_interval>
80 * <output_type>SPLICE</output_type>
81 * <tracefile_size>0</tracefile_size>
82 * <tracefile_count>0</tracefile_count>
83 * <live_timer_interval>0</live_timer_interval>
84 * <events>
85 * <event>
86 * <enabled>true</enabled>
87 * <type>SYSCALL</type>
88 * </event>
89 * <event>
90 * <name>snd_soc_cache_sync</name>
91 * <enabled>true</enabled>
92 * <type>TRACEPOINT</type>
93 * </event>
94 * </events>
95 * </channel>
96 * </channels>
97 * </domain>
98 * </domains>
99 * <started>false</started>
100 * <output>
101 * <consumer_output>
102 * <enabled>true</enabled>
103 * <destination>
104 * <path>/home/user/lttng-traces/test_kernel</path>
105 * </destination>
106 * </consumer_output>
107 * </output>
108 * </session>
109 * </sessions>
110 * }
111 * </pre>
112 *
113 * </p>
114 *
115 * @author Guilliano Molaire
116 */
117 public final class SessionConfigGenerator {
118
119 /** The name of the session schema */
120 private static final String SESSION_XSD_FILENAME = "session.xsd"; //$NON-NLS-1$
121
122 /** The indent size used for the session configuration XML file */
123 private static final String INDENT_AMOUNT_PROPERTY_NAME = "{http://xml.apache.org/xslt}indent-amount"; //$NON-NLS-1$
124 private static final String INDENT_AMOUNT_PROPERTY_VALUE = "4"; //$NON-NLS-1$
125
126 /**
127 * Private constructor. The class should not be instantiated.
128 */
129 private SessionConfigGenerator() {
130 }
131
132 // ---------------------------------------------------------
133 // Methods to generate session configuration files
134 // ---------------------------------------------------------
135
136 /**
137 * Generates a session configuration file from a set of session information.
138 *
139 * @param sessions
140 * The session informations
141 * @param sessionFileDestination
142 * The path of the locally saved session configuration file
143 * @return The status of the session configuration generation
144 */
145 public static IStatus generateSessionConfig(Set<ISessionInfo> sessions, IPath sessionFileDestination) {
146 /* Parameters validation */
147 if (sessions == null || sessions.isEmpty()) {
148 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.SessionConfigXML_InvalidSessionInfoList);
149 } else if (sessionFileDestination == null) {
150 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.SessionConfigXML_InvalidTraceSessionPath);
151 }
152
153 /* Generate the session configuration file */
154 try {
155 Document sessionConfigDocument = generateSessionConfig(sessions);
156 saveSessionConfig(sessionConfigDocument, sessionFileDestination.toString());
157 } catch (TransformerException | IllegalArgumentException | ParserConfigurationException e) {
158 Activator.getDefault().logError("Error generating the session configuration file: " + sessionFileDestination.toString(), e); //$NON-NLS-1$
159 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage());
160 }
161
162 return Status.OK_STATUS;
163 }
164
165 /**
166 * Generates a session configuration from a set of session informations.
167 *
168 * @param sessions
169 * The session informations
170 * @return The document with all session configuration nodes
171 * @throws IllegalArgumentException
172 * On an illegal argument inside sessions
173 * @throws ParserConfigurationException
174 * On an parser configuration error
175 */
176 private static @NonNull Document generateSessionConfig(Iterable<ISessionInfo> sessions) throws IllegalArgumentException, ParserConfigurationException {
177 DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
178 DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
179
180 Document document = docBuilder.newDocument();
181
182 Element rootElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_SESSIONS);
183 document.appendChild(rootElement);
184
185 for (ISessionInfo session : sessions) {
186 /* All elements under "sessions" elements */
187 Element sessionElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_SESSION);
188
189 /* Contents of session element */
190 String enabled = session.getSessionState().equals(TraceSessionState.ACTIVE) ? SessionConfigStrings.CONFIG_STRING_TRUE : SessionConfigStrings.CONFIG_STRING_FALSE;
191
192 addElementContent(document, sessionElement, SessionConfigStrings.CONFIG_ELEMENT_NAME, session.getName());
193 addElementContent(document, sessionElement, SessionConfigStrings.CONFIG_ELEMENT_STARTED, enabled);
194
195 if (session.isSnapshotSession()) {
196 /* If it's a snapshot, we must add an attribute telling it is */
197 Element attributesElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_ATTRIBUTES);
198 addElementContent(document, attributesElement, SessionConfigStrings.CONFIG_ELEMENT_SNAPSHOT_MODE, SessionConfigStrings.CONFIG_STRING_TRUE);
199 sessionElement.appendChild(attributesElement);
200 }
201
202 sessionElement.appendChild(getDomainsElement(document, session));
203 sessionElement.appendChild(getOutputElement(document, session));
204 rootElement.appendChild(sessionElement);
205 }
206
207 return document;
208 }
209
210 // ---------------------------------------------------------
211 // Getters for each element of the configuration file
212 // ---------------------------------------------------------
213
214 /**
215 * Gets the 'domains' element after creating it.
216 *
217 * @param document
218 * The document in which the nodes are being added
219 * @param session
220 * The session informations
221 * @return The domains element as an XML element
222 */
223 private static Element getDomainsElement(Document document, ISessionInfo session) {
224 Element domainsElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_DOMAINS);
225
226 for (IDomainInfo domain : session.getDomains()) {
227 Element domainElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_DOMAIN);
228
229 String domainType = null;
230 switch (domain.getDomain()) {
231 case KERNEL:
232 domainType = SessionConfigStrings.CONFIG_DOMAIN_TYPE_KERNEL;
233 break;
234 case UST:
235 domainType = SessionConfigStrings.CONFIG_DOMAIN_TYPE_UST;
236 break;
237 // TODO: Add the following cases when more domains are supported
238 case JUL:
239 case LOG4J:
240 case PYTHON:
241 case UNKNOWN:
242 default:
243 break;
244
245 }
246 addElementContent(document, domainElement, SessionConfigStrings.CONFIG_ELEMENT_TYPE, domainType);
247
248 String bufferType = null;
249 switch (domain.getBufferType()) {
250 case BUFFER_PER_UID:
251 bufferType = SessionConfigStrings.CONFIG_BUFFER_TYPE_PER_UID;
252 break;
253 case BUFFER_PER_PID:
254 bufferType = SessionConfigStrings.CONFIG_BUFFER_TYPE_PER_PID;
255 break;
256 case BUFFER_SHARED:
257 bufferType = SessionConfigStrings.CONFIG_BUFFER_TYPE_GLOBAL;
258 break;
259 case BUFFER_TYPE_UNKNOWN:
260 default:
261 throw new IllegalArgumentException(Messages.SessionConfigXML_UnknownDomainBufferType);
262 }
263 addElementContent(document, domainElement, SessionConfigStrings.CONFIG_ELEMENT_DOMAIN_BUFFER_TYPE, bufferType);
264
265 /* Add the channels */
266 domainElement.appendChild(getChannelsElement(document, domain.getDomain(), domain.getChannels()));
267 domainsElement.appendChild(domainElement);
268 }
269
270 return domainsElement;
271 }
272
273 /**
274 * Gets the 'output' element after creating it. If the session is a
275 * snapshot, it will be composed of a snapshot outputs element. Otherwise,
276 * it will contain the consumer output element.
277 *
278 * @param document
279 * The document in which the nodes are being added
280 * @param session
281 * The session informations
282 * @return The output element as an XML node
283 */
284 private static Element getOutputElement(Document document, ISessionInfo session) {
285 Element outputElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_OUTPUT);
286
287 if (session.isSnapshotSession()) {
288 outputElement.appendChild(getSnapshotOuputsElement(document, session));
289 } else if (session.isStreamedTrace()) {
290 outputElement.appendChild(getNetOutputElement(document, session));
291 } else {
292 outputElement.appendChild(getConsumerOutputElement(document, session));
293 }
294
295 return outputElement;
296 }
297
298 /**
299 * Gets the 'channels' element after creating it.
300 *
301 * @param document
302 * The document in which the nodes are being added
303 * @param domain
304 * The domain type ({@link TraceDomainType})
305 * @param channels
306 * The channels to be added as elements
307 * @return The channels element as an XML element
308 */
309 private static Element getChannelsElement(Document document, TraceDomainType domain, IChannelInfo[] channels) {
310 Element channelsElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_CHANNELS);
311
312 for (IChannelInfo channel : channels) {
313 Element channelElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_CHANNEL);
314
315 /* Add everything related to a channel */
316 addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_NAME, channel.getName());
317
318 String overwriteMode = channel.isOverwriteMode() ? SessionConfigStrings.CONFIG_OVERWRITE_MODE_OVERWRITE : SessionConfigStrings.CONFIG_OVERWRITE_MODE_DISCARD;
319 String enabled = channel.getState().equals(TraceEnablement.ENABLED) ? SessionConfigStrings.CONFIG_STRING_TRUE : SessionConfigStrings.CONFIG_STRING_FALSE;
320
321 addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_ENABLED, enabled);
322 addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_OVERWRITE_MODE, overwriteMode);
323 addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_SUBBUFFER_SIZE, channel.getSubBufferSize());
324 addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_SUBBUFFER_COUNT, channel.getNumberOfSubBuffers());
325 addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_SWITCH_TIMER_INTERVAL, channel.getSwitchTimer());
326 addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_READ_TIMER_INTERVAL, channel.getReadTimer());
327
328 String outputType = channel.getOutputType().getInName().startsWith(SessionConfigStrings.CONFIG_OUTPUT_TYPE_MMAP) ?
329 SessionConfigStrings.CONFIG_OUTPUT_TYPE_MMAP : SessionConfigStrings.CONFIG_OUTPUT_TYPE_SPLICE;
330 addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_OUTPUT_TYPE, outputType);
331 addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_TRACEFILE_SIZE, channel.getMaxSizeTraceFiles());
332 addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_TRACEFILE_COUNT, channel.getMaxNumberTraceFiles());
333
334 /*
335 * TODO: Replace the 0 value by the channel live timer property from
336 * SessionInfo once live session tracing is supported
337 */
338 addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_LIVE_TIMER_INTERVAL, SessionConfigStrings.CONFIG_STRING_ZERO);
339
340 /* Add the events */
341 channelElement.appendChild(getEventsElement(document, domain, channel.getEvents()));
342 channelsElement.appendChild(channelElement);
343 }
344
345 return channelsElement;
346 }
347
348 /**
349 * Gets the 'events' element after creating it. It is composed of the event
350 * informations from a list of IEventInfo.
351 *
352 * @param document
353 * The document in which the nodes are being added
354 * @param domain
355 * The domain type ({@link TraceDomainType})
356 * @param events
357 * The event informations to be added
358 * @return An element containing all the event informations as XML elements
359 */
360 private static Element getEventsElement(Document document, TraceDomainType domain, IEventInfo[] events) {
361 Element eventsElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_EVENTS);
362
363 for (IEventInfo event : events) {
364 Element eventElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_EVENT);
365
366 /* Enabled attribute */
367 String enabled = event.getState().equals(TraceEnablement.ENABLED) ? SessionConfigStrings.CONFIG_STRING_TRUE : SessionConfigStrings.CONFIG_STRING_FALSE;
368
369 /* Add the attributes to the event node */
370 addElementContent(document, eventElement, SessionConfigStrings.CONFIG_ELEMENT_NAME, event.getName());
371 addElementContent(document, eventElement, SessionConfigStrings.CONFIG_ELEMENT_ENABLED, enabled);
372 TraceEventType eventType = event.getEventType();
373 if (!eventType.equals(TraceEventType.UNKNOWN)) {
374 addElementContent(document, eventElement, SessionConfigStrings.CONFIG_ELEMENT_TYPE, eventType.getInName().toUpperCase());
375 } else {
376 throw new IllegalArgumentException(Messages.SessionConfigXML_UnknownEventType);
377 }
378
379 /* Specific to UST session config: the log level */
380 if (domain.equals(TraceDomainType.UST) && !event.getLogLevel().equals(TraceLogLevel.LEVEL_UNKNOWN)) {
381 addElementContent(document, eventElement, SessionConfigStrings.CONFIG_ELEMENT_LOGLEVEL, event.getLogLevel().ordinal());
382 }
383
384 /* Add the node to the parent node events */
385 eventsElement.appendChild(eventElement);
386 }
387
388 return eventsElement;
389 }
390
391 /**
392 * Gets the 'consumer_output' element after creating it.
393 *
394 * @param document
395 * The document in which the nodes are being added
396 * @param session
397 * The session informations
398 * @return The consumer output element with his informations as XML elements
399 */
400 private static Element getConsumerOutputElement(Document document, ISessionInfo session) {
401 Element consumerOutputElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_CONSUMER_OUTPUT);
402 Element destinationElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_DESTINATION);
403
404 /* Value of consumer output element */
405 addElementContent(document, consumerOutputElement, SessionConfigStrings.CONFIG_ELEMENT_ENABLED, SessionConfigStrings.CONFIG_STRING_TRUE);
406
407 if (session.isStreamedTrace()) {
408 /* If it is a streamed session, add the net output element */
409 destinationElement.appendChild(getNetOutputElement(document, session));
410 } else {
411 addElementContent(document, destinationElement, SessionConfigStrings.CONFIG_ELEMENT_PATH, session.getSessionPath());
412 }
413
414 consumerOutputElement.appendChild(destinationElement);
415 return consumerOutputElement;
416 }
417
418 /**
419 * Gets the 'net_output' element after creating it. It is composed of the
420 * control and data URIs.
421 *
422 * @param document
423 * The document in which the nodes are being added
424 * @param session
425 * The session informations
426 * @return The net output element
427 */
428 private static Element getNetOutputElement(Document document, ISessionInfo session) {
429 Element netOutputElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_NET_OUTPUT);
430
431 String networkUrl = session.getNetworkUrl();
432 String controlUri = networkUrl == null ? session.getControlUrl() : networkUrl;
433 String dataUri = networkUrl == null ? session.getDataUrl() : networkUrl;
434 addElementContent(document, netOutputElement, SessionConfigStrings.CONFIG_ELEMENT_CONTROL_URI, controlUri);
435 addElementContent(document, netOutputElement, SessionConfigStrings.CONFIG_ELEMENT_DATA_URI, dataUri);
436
437 return netOutputElement;
438 }
439
440 /**
441 * Gets the 'snapshot_outputs' element after creating it.
442 *
443 * @param document
444 * The document in which the nodes are being added
445 * @param session
446 * The session informations
447 * @return The snapshot outputs element with snapshot informations as XML
448 * elements
449 */
450 private static Element getSnapshotOuputsElement(Document document, ISessionInfo session) {
451 Element snapshotOutputsElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_SNAPSHOT_OUTPUTS);
452 Element outputElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_OUTPUT);
453
454 /* Add the name of the snapshot and the max size element */
455 addElementContent(document, outputElement, SessionConfigStrings.CONFIG_ELEMENT_NAME, session.getSnapshotInfo().getName());
456
457 /*
458 * TODO: find the proper max size value of output element. For now it is
459 * set to the default 0 value which means unlimited for lttng.
460 */
461 addElementContent(document, outputElement, SessionConfigStrings.CONFIG_ELEMENT_MAX_SIZE, SessionConfigStrings.CONFIG_STRING_ZERO);
462 outputElement.appendChild(getConsumerOutputElement(document, session));
463
464 snapshotOutputsElement.appendChild(outputElement);
465 return snapshotOutputsElement;
466 }
467
468 // ---------------------------------------------------------
469 // Utilities
470 // ---------------------------------------------------------
471
472 /**
473 * Validates the session configuration file against its schema.
474 *
475 * @param sessionFile
476 * The session configuration file
477 * @return The status of the validation
478 */
479 public static IStatus sessionValidate(File sessionFile) {
480 URL url = SessionConfigGenerator.class.getResource(SESSION_XSD_FILENAME);
481 SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
482 Source xmlSource = new StreamSource(sessionFile);
483
484 try {
485 Schema schema = schemaFactory.newSchema(url);
486 Validator validator = schema.newValidator();
487 validator.validate(xmlSource);
488 } catch (SAXParseException e) {
489 String error = NLS.bind(Messages.SessionConfigXML_XmlParseError, e.getLineNumber(), e.getLocalizedMessage());
490 Activator.getDefault().logError(error);
491 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, error, e);
492 } catch (SAXException e) {
493 String error = NLS.bind(Messages.SessionConfigXML_XmlValidationError, e.getLocalizedMessage());
494 Activator.getDefault().logError(error);
495 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, error, e);
496 } catch (IOException e) {
497 String error = Messages.SessionConfigXML_XmlValidateError;
498 Activator.getDefault().logError("IO exception occurred", e); //$NON-NLS-1$
499 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, error, e);
500 }
501 return Status.OK_STATUS;
502 }
503
504 /**
505 * Saves the session configuration into a XML file.
506 *
507 * @param document
508 * The document representing the session configuration file
509 * @param destination
510 * The path of the locally saved session configuration file
511 * @throws TransformerException
512 * On an transformation process
513 */
514 private static void saveSessionConfig(Document document, String destination) throws TransformerException {
515 /* Write the content into a XML file */
516 TransformerFactory transformerFactory = TransformerFactory.newInstance();
517 Transformer transformer = transformerFactory.newTransformer();
518
519 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
520 transformer.setOutputProperty(INDENT_AMOUNT_PROPERTY_NAME, INDENT_AMOUNT_PROPERTY_VALUE);
521
522 DOMSource source = new DOMSource(document);
523 StreamResult result = new StreamResult(new File(destination));
524
525 transformer.transform(source, result);
526 }
527
528 /**
529 * Adds to a parent node an element with his content.
530 *
531 * @param document
532 * The document in which the nodes are being added
533 * @param parent
534 * The parent node that contains the element and his content
535 * @param elementName
536 * The element container name
537 * @param elementContent
538 * The content itself
539 */
540 private static void addElementContent(Document document, Element parent, String elementName, Object elementContent) {
541 Element contentElement = document.createElement(elementName);
542 contentElement.appendChild(document.createTextNode(elementContent.toString()));
543 parent.appendChild(contentElement);
544 }
545 }
This page took 0.043255 seconds and 5 git commands to generate.