1 /**********************************************************************
2 * Copyright (c) 2014 Ericsson
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
10 * Jonathan Rajotte - Initial support for machine interface lttng 2.6
11 **********************************************************************/
13 package org
.eclipse
.linuxtools
.internal
.lttng2
.control
.ui
.views
.service
;
15 import java
.io
.IOException
;
16 import java
.io
.StringReader
;
17 import java
.math
.BigInteger
;
19 import java
.util
.ArrayList
;
20 import java
.util
.List
;
21 import java
.util
.regex
.Matcher
;
23 import javax
.xml
.parsers
.DocumentBuilder
;
24 import javax
.xml
.parsers
.DocumentBuilderFactory
;
25 import javax
.xml
.parsers
.ParserConfigurationException
;
27 import org
.eclipse
.core
.commands
.ExecutionException
;
28 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
29 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.IBaseEventInfo
;
30 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.IChannelInfo
;
31 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.IDomainInfo
;
32 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.IEventInfo
;
33 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.IFieldInfo
;
34 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.IProbeEventInfo
;
35 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.ISessionInfo
;
36 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.ISnapshotInfo
;
37 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.IUstProviderInfo
;
38 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.LogLevelType
;
39 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.TraceDomainType
;
40 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.TraceEnablement
;
41 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.TraceEventType
;
42 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.TraceLogLevel
;
43 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.impl
.BaseEventInfo
;
44 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.impl
.BufferType
;
45 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.impl
.ChannelInfo
;
46 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.impl
.DomainInfo
;
47 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.impl
.EventInfo
;
48 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.impl
.FieldInfo
;
49 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.impl
.ProbeEventInfo
;
50 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.impl
.SessionInfo
;
51 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.impl
.SnapshotInfo
;
52 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.core
.model
.impl
.UstProviderInfo
;
53 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.ui
.views
.handlers
.XmlMiValidationErrorHandler
;
54 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.ui
.views
.messages
.Messages
;
55 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.ui
.views
.remote
.ICommandResult
;
56 import org
.eclipse
.linuxtools
.internal
.lttng2
.control
.ui
.views
.remote
.ICommandShell
;
57 import org
.eclipse
.osgi
.util
.NLS
;
58 import org
.w3c
.dom
.Document
;
59 import org
.w3c
.dom
.Node
;
60 import org
.w3c
.dom
.NodeList
;
61 import org
.xml
.sax
.InputSource
;
62 import org
.xml
.sax
.SAXException
;
65 * Service for sending LTTng trace control commands to remote host via machine
68 * @author Jonathan Rajotte
70 public class LTTngControlServiceMI
extends LTTngControlService
{
72 // ------------------------------------------------------------------------
74 // ------------------------------------------------------------------------
76 private final DocumentBuilder fDocumentBuilder
;
78 // ------------------------------------------------------------------------
80 // ------------------------------------------------------------------------
86 * the command shell implementation to use
88 * the xsd schema file for validation
89 * @throws ExecutionException
90 * if the creation of the Schema and DocumentBuilder objects
93 public LTTngControlServiceMI(ICommandShell shell
, URL xsdUrl
) throws ExecutionException
{
96 DocumentBuilderFactory docBuilderFactory
= DocumentBuilderFactory
.newInstance();
97 docBuilderFactory
.setValidating(false);
99 // TODO: Add xsd validation for machine interface via mi_lttng.xsd from LTTng
101 fDocumentBuilder
= docBuilderFactory
.newDocumentBuilder();
102 } catch (ParserConfigurationException e
) {
103 throw new ExecutionException(Messages
.TraceControl_XmlDocumentBuilderError
, e
);
106 fDocumentBuilder
.setErrorHandler(new XmlMiValidationErrorHandler());
111 * Generate a Document object from an array of String.
114 * array of strings representing an xml input
115 * @return Document generated from strings input
116 * @throws ExecutionException
117 * when parsing has failed
119 private Document
getDocumentFromStrings(String
[] xmlStrings
) throws ExecutionException
{
120 StringBuilder concatenedString
= new StringBuilder();
121 for (String string
: xmlStrings
) {
122 concatenedString
.append(string
);
124 InputSource stream
= new InputSource(new StringReader(concatenedString
.toString()));
128 document
= fDocumentBuilder
.parse(stream
);
129 } catch (SAXException
| IOException e
) {
130 throw new ExecutionException(Messages
.TraceControl_XmlParsingError
, e
);
137 * Parse, populate and set the internal LTTngVersion variable
140 * the mi xml output of lttng version
141 * @throws ExecutionException
142 * when xml extraction fail
144 public void setVersion(String
[] xmlOutput
) throws ExecutionException
{
145 Document doc
= getDocumentFromStrings(xmlOutput
);
146 NodeList element
= doc
.getElementsByTagName(MIStrings
.VERSION
);
150 String license
= ""; //$NON-NLS-1$
151 String commit
= ""; //$NON-NLS-1$
152 String name
= ""; //$NON-NLS-1$
153 String description
= ""; //$NON-NLS-1$
154 String url
= ""; //$NON-NLS-1$
155 String fullVersion
= ""; //$NON-NLS-1$
156 if (element
.getLength() == 1) {
157 NodeList child
= element
.item(0).getChildNodes();
158 // Get basic information
159 for (int i
= 0; i
< child
.getLength(); i
++) {
160 Node node
= child
.item(i
);
161 switch (node
.getNodeName()) {
162 case MIStrings
.VERSION_MAJOR
:
163 major
= Integer
.parseInt(node
.getTextContent());
165 case MIStrings
.VERSION_MINOR
:
166 minor
= Integer
.parseInt(node
.getTextContent());
168 case MIStrings
.VERSION_PATCH_LEVEL
:
169 patchLevel
= Integer
.parseInt(node
.getTextContent());
171 case MIStrings
.VERSION_COMMIT
:
172 commit
= node
.getTextContent();
174 case MIStrings
.VERSION_DESCRIPTION
:
175 description
= node
.getTextContent();
177 case MIStrings
.VERSION_LICENSE
:
178 license
= node
.getTextContent();
180 case MIStrings
.VERSION_NAME
:
181 name
= node
.getTextContent();
183 case MIStrings
.VERSION_STR
:
184 fullVersion
= node
.getTextContent();
186 case MIStrings
.VERSION_WEB
:
187 url
= node
.getTextContent();
193 setVersion(new LttngVersion(major
, minor
, patchLevel
, license
, commit
, name
, description
, url
, fullVersion
));
195 throw new ExecutionException(Messages
.TraceControl_UnsupportedVersionError
);
200 public String
[] getSessionNames(IProgressMonitor monitor
) throws ExecutionException
{
201 StringBuffer command
= createCommand(LTTngControlServiceConstants
.COMMAND_LIST
);
202 ICommandResult result
= executeCommand(command
.toString(), monitor
);
204 Document doc
= getDocumentFromStrings(result
.getOutput());
206 NodeList elements
= doc
.getElementsByTagName(MIStrings
.NAME
);
208 ArrayList
<String
> retArray
= new ArrayList
<>();
209 for (int i
= 0; i
< elements
.getLength(); i
++) {
210 Node node
= elements
.item(i
);
211 if (node
.getParentNode().getNodeName().equalsIgnoreCase(MIStrings
.SESSION
)) {
212 retArray
.add(node
.getTextContent());
215 return retArray
.toArray(new String
[retArray
.size()]);
219 public ISessionInfo
getSession(String sessionName
, IProgressMonitor monitor
) throws ExecutionException
{
220 StringBuffer command
= createCommand(LTTngControlServiceConstants
.COMMAND_LIST
, sessionName
);
221 ICommandResult result
= executeCommand(command
.toString(), monitor
);
223 ISessionInfo sessionInfo
= new SessionInfo(sessionName
);
224 Document document
= getDocumentFromStrings(result
.getOutput());
226 NodeList sessionsNode
= document
.getElementsByTagName(MIStrings
.SESSION
);
227 // There should be only one session
228 if (sessionsNode
.getLength() != 1) {
229 throw new ExecutionException(NLS
.bind(Messages
.TraceControl_MiInvalidNumberOfElementError
, MIStrings
.SESSION
));
232 // Populate session information
233 Node rawSession
= sessionsNode
.item(0);
234 parseSession(sessionInfo
, rawSession
);
236 // Fetch the snapshot info
237 if (sessionInfo
.isSnapshotSession()) {
238 ISnapshotInfo snapshot
= getSnapshotInfo(sessionName
, monitor
);
239 sessionInfo
.setSnapshotInfo(snapshot
);
248 * @throws ExecutionException
250 private void parseSession(ISessionInfo sessionInfo
, Node rawSession
) throws ExecutionException
{
251 if (!rawSession
.getNodeName().equalsIgnoreCase(MIStrings
.SESSION
)) {
252 throw new ExecutionException(Messages
.TraceControl_MiInvalidElementError
);
254 NodeList rawSessionInfos
= rawSession
.getChildNodes();
255 for (int i
= 0; i
< rawSessionInfos
.getLength(); i
++) {
256 Node rawInfo
= rawSessionInfos
.item(i
);
257 switch (rawInfo
.getNodeName()) {
259 sessionInfo
.setName(rawInfo
.getTextContent());
262 sessionInfo
.setSessionPath(rawInfo
.getTextContent());
264 case MIStrings
.ENABLED
:
265 sessionInfo
.setSessionState(rawInfo
.getTextContent());
267 case MIStrings
.SNAPSHOT_MODE
:
268 if (rawInfo
.getTextContent().equals(LTTngControlServiceConstants
.TRUE_NUMERICAL
)) {
269 // real name will be set later
270 ISnapshotInfo snapshotInfo
= new SnapshotInfo(""); //$NON-NLS-1$
271 sessionInfo
.setSnapshotInfo(snapshotInfo
);
274 case MIStrings
.LIVE_TIMER_INTERVAL
:
275 // TODO : live mode not supported yet in TMF:lttng-control
277 case MIStrings
.DOMAINS
:
278 // Extract the domains node
279 NodeList rawDomains
= rawInfo
.getChildNodes();
280 IDomainInfo domain
= null;
281 for (int j
= 0; j
< rawDomains
.getLength(); j
++) {
282 if (rawDomains
.item(j
).getNodeName().equalsIgnoreCase(MIStrings
.DOMAIN
)) {
283 domain
= parseDomain(rawDomains
.item(j
));
284 sessionInfo
.addDomain(domain
);
293 if (!sessionInfo
.isSnapshotSession()) {
294 Matcher matcher
= LTTngControlServiceConstants
.TRACE_NETWORK_PATTERN
.matcher(sessionInfo
.getSessionPath());
295 if (matcher
.matches()) {
296 sessionInfo
.setStreamedTrace(true);
302 * Parse a raw domain XML node to a IDomainInfo object
306 * @return a populated {@link DomainInfo} object
307 * @throws ExecutionException
308 * when missing required xml element (type)
310 protected IDomainInfo
parseDomain(Node rawDomain
) throws ExecutionException
{
311 IDomainInfo domain
= null;
313 Node rawType
= getFirstOf(rawDomain
.getChildNodes(), MIStrings
.TYPE
);
314 if (rawType
== null) {
315 throw new ExecutionException(Messages
.TraceControl_MiMissingRequiredError
);
317 String rawTypeString
= rawType
.getTextContent().toLowerCase();
318 TraceDomainType domainType
= TraceDomainType
.valueOfString(rawTypeString
);
319 switch (domainType
) {
321 domain
= new DomainInfo(Messages
.TraceControl_KernelProviderDisplayName
);
322 domain
.setIsKernel(true);
325 domain
= new DomainInfo(Messages
.TraceControl_UstGlobalDomainDisplayName
);
326 domain
.setIsKernel(false);
330 * TODO: Support for JUL JUL substructure and semantic is not the
331 * same as a regular UST or Kernel Domain There is no channel under
332 * JUL domain only events. The channel is activated in UST Channel
334 domain
= new DomainInfo(Messages
.TraceControl_JULDomainDisplayName
);
335 domain
.setIsKernel(false);
338 domain
= new DomainInfo(Messages
.TraceControl_UnknownDomainDisplayName
);
339 domain
.setIsKernel(false);
342 throw new ExecutionException(Messages
.TraceControl_MiInvalidElementError
);
345 NodeList rawInfos
= rawDomain
.getChildNodes();
346 for (int i
= 0; i
< rawInfos
.getLength(); i
++) {
347 Node rawInfo
= rawInfos
.item(i
);
348 switch (rawInfo
.getNodeName()) {
349 case MIStrings
.BUFFER_TYPE
:
350 BufferType bufferType
= BufferType
.valueOfString(rawInfo
.getTextContent());
351 domain
.setBufferType(bufferType
);
353 case MIStrings
.CHANNELS
:
354 ArrayList
<IChannelInfo
> channels
= new ArrayList
<>();
355 parseChannels(rawInfo
.getChildNodes(), channels
);
356 if (channels
.size() > 0) {
357 domain
.setChannels(channels
);
369 * Parse a list of raw channel XML node into an ArrayList of IChannelInfo
372 * List of raw channel XML node
374 * the parsed channels list
375 * @throws ExecutionException
376 * when missing required xml element (type)
378 private static void parseChannels(NodeList rawChannels
, ArrayList
<IChannelInfo
> channels
) throws ExecutionException
{
379 IChannelInfo channel
= null;
380 for (int i
= 0; i
< rawChannels
.getLength(); i
++) {
381 Node rawChannel
= rawChannels
.item(i
);
382 if (rawChannel
.getNodeName().equalsIgnoreCase(MIStrings
.CHANNEL
)) {
383 channel
= new ChannelInfo(""); //$NON-NLS-1$
385 // Populate the channel
386 NodeList rawInfos
= rawChannel
.getChildNodes();
388 for (int j
= 0; j
< rawInfos
.getLength(); j
++) {
389 rawInfo
= rawInfos
.item(j
);
390 switch (rawInfo
.getNodeName()) {
392 channel
.setName(rawInfo
.getTextContent());
394 case MIStrings
.ENABLED
:
395 channel
.setState(TraceEnablement
.valueOfString(rawInfo
.getTextContent()));
397 case MIStrings
.EVENTS
:
398 List
<IEventInfo
> events
= new ArrayList
<>();
399 getEventInfo(rawInfo
.getChildNodes(), events
);
400 channel
.setEvents(events
);
402 case MIStrings
.ATTRIBUTES
:
403 NodeList rawAttributes
= rawInfo
.getChildNodes();
404 for (int k
= 0; k
< rawAttributes
.getLength(); k
++) {
405 Node attribute
= rawAttributes
.item(k
);
406 switch (attribute
.getNodeName()) {
407 case MIStrings
.OVERWRITE_MODE
:
408 channel
.setOverwriteMode(!LTTngControlServiceConstants
.OVERWRITE_MODE_ATTRIBUTE_FALSE_MI
.equalsIgnoreCase(attribute
.getTextContent()));
410 case MIStrings
.SUBBUF_SIZE
:
411 channel
.setSubBufferSize(Long
.valueOf(attribute
.getTextContent()));
413 case MIStrings
.NUM_SUBBUF
:
414 channel
.setNumberOfSubBuffers(Integer
.valueOf(attribute
.getTextContent()));
416 case MIStrings
.SWITCH_TIMER_INTERVAL
:
417 channel
.setSwitchTimer(Long
.valueOf(attribute
.getTextContent()));
419 case MIStrings
.READ_TIMER_INTERVAL
:
420 channel
.setReadTimer(Long
.valueOf(attribute
.getTextContent()));
422 case MIStrings
.OUTPUT_TYPE
:
423 channel
.setOutputType(attribute
.getTextContent());
425 case MIStrings
.TRACEFILE_SIZE
:
426 channel
.setMaxSizeTraceFiles(Integer
.parseInt(attribute
.getTextContent()));
428 case MIStrings
.TRACEFILE_COUNT
:
429 channel
.setMaxNumberTraceFiles(Integer
.parseInt(attribute
.getTextContent()));
431 case MIStrings
.LIVE_TIMER_INTERVAL
:
432 // TODO: currently not supported by tmf
443 channels
.add(channel
);
450 public ISnapshotInfo
getSnapshotInfo(String sessionName
, IProgressMonitor monitor
) throws ExecutionException
{
451 // TODO A session can have multiple snapshot output. This need to be
452 // supported in the future.
453 // Currently the SessionInfo object does not support multiple snashot
455 // For now only keep the last one.
456 StringBuffer command
= createCommand(LTTngControlServiceConstants
.COMMAND_LIST_SNAPSHOT_OUTPUT
, LTTngControlServiceConstants
.OPTION_SESSION
, sessionName
);
457 ICommandResult result
= executeCommand(command
.toString(), monitor
);
458 Document doc
= getDocumentFromStrings(result
.getOutput());
459 NodeList rawSnapshotsOutputs
= doc
.getElementsByTagName(MIStrings
.SNAPSHOT_OUTPUTS
);
461 ISnapshotInfo snapshotInfo
= new SnapshotInfo(""); //$NON-NLS-1$
463 // TODO: tmf does not have a notion of a ctrl url.
464 for (int i
= 0; i
< rawSnapshotsOutputs
.getLength(); i
++) {
465 NodeList rawSnapshotOutput
= rawSnapshotsOutputs
.item(i
).getChildNodes();
466 for (int j
= 0; j
< rawSnapshotOutput
.getLength(); j
++) {
467 Node rawInfo
= rawSnapshotOutput
.item(j
);
468 switch (rawInfo
.getNodeName()) {
470 snapshotInfo
.setId(Integer
.parseInt(rawInfo
.getTextContent()));
473 snapshotInfo
.setName(rawInfo
.getTextContent());
475 case MIStrings
.SNAPSHOT_CTRL_URL
:
476 // The use of the ctrl_url for the snapshot path is to assure
477 // basic support. Refactoring is necessary in lttng and
479 // See http://bugs.lttng.org/issues/828 (+comment)
480 snapshotInfo
.setSnapshotPath(rawInfo
.getTextContent());
488 // Check if the snapshot output is Streamed
489 Matcher matcher2
= LTTngControlServiceConstants
.TRACE_NETWORK_PATTERN
.matcher(snapshotInfo
.getSnapshotPath());
490 if (matcher2
.matches()) {
491 snapshotInfo
.setStreamedSnapshot(true);
498 public List
<IBaseEventInfo
> getKernelProvider(IProgressMonitor monitor
) throws ExecutionException
{
499 StringBuffer command
= createCommand(LTTngControlServiceConstants
.COMMAND_LIST_KERNEL
);
500 ICommandResult result
= executeCommand(command
.toString(), monitor
, false);
501 List
<IBaseEventInfo
> events
= new ArrayList
<>();
503 if (isError(result
) && result
.getErrorOutput() != null) {
504 // Ignore the following 2 cases:
505 // Spawning a session daemon
506 // Error: Unable to list kernel events
508 // Error: Unable to list kernel events
509 if (ignoredPattern(result
.getErrorOutput(), LTTngControlServiceConstants
.LIST_KERNEL_NO_KERNEL_PROVIDER_PATTERN
)) {
512 throw new ExecutionException(Messages
.TraceControl_CommandError
+ LTTngControlServiceConstants
.COMMAND_LIST_KERNEL
);
515 Document document
= getDocumentFromStrings(result
.getOutput());
516 NodeList rawEvents
= document
.getElementsByTagName(MIStrings
.EVENT
);
517 getBaseEventInfo(rawEvents
, events
);
522 public List
<IUstProviderInfo
> getUstProvider(IProgressMonitor monitor
) throws ExecutionException
{
523 StringBuffer command
= createCommand(LTTngControlServiceConstants
.COMMAND_LIST_UST
);
525 command
.append(LTTngControlServiceConstants
.OPTION_FIELDS
);
528 ICommandResult result
= executeCommand(command
.toString(), monitor
, false);
529 List
<IUstProviderInfo
> allProviders
= new ArrayList
<>();
531 if (isError(result
) && result
.getErrorOutput() != null) {
532 // Ignore the following 2 cases:
533 // Spawning a session daemon
534 // Error: Unable to list UST events: Listing UST events failed
536 // Error: Unable to list UST events: Listing UST events failed
537 if (ignoredPattern(result
.getErrorOutput(), LTTngControlServiceConstants
.LIST_UST_NO_UST_PROVIDER_PATTERN
)) {
540 throw new ExecutionException(Messages
.TraceControl_CommandError
+ LTTngControlServiceConstants
.COMMAND_LIST_UST
);
543 Document document
= getDocumentFromStrings(result
.getOutput());
544 NodeList rawProviders
= document
.getElementsByTagName(MIStrings
.PID
);
546 IUstProviderInfo providerInfo
= null;
548 for (int i
= 0; i
< rawProviders
.getLength(); i
++) {
549 Node provider
= rawProviders
.item(i
);
550 Node name
= getFirstOf(provider
.getChildNodes(), MIStrings
.NAME
);
552 throw new ExecutionException(Messages
.TraceControl_MiInvalidProviderError
);
554 providerInfo
= new UstProviderInfo(name
.getTextContent());
557 NodeList infos
= provider
.getChildNodes();
558 for (int j
= 0; j
< infos
.getLength(); j
++) {
559 Node info
= infos
.item(j
);
560 switch (info
.getNodeName()) {
561 case MIStrings
.PID_ID
:
562 providerInfo
.setPid(Integer
.parseInt(info
.getTextContent()));
564 case MIStrings
.EVENTS
:
565 List
<IBaseEventInfo
> events
= new ArrayList
<>();
566 NodeList rawEvents
= info
.getChildNodes();
567 getBaseEventInfo(rawEvents
, events
);
568 providerInfo
.setEvents(events
);
574 allProviders
.add(providerInfo
);
581 public ISessionInfo
createSession(ISessionInfo sessionInfo
, IProgressMonitor monitor
) throws ExecutionException
{
582 if (sessionInfo
.isStreamedTrace()) {
583 return createStreamedSession(sessionInfo
, monitor
);
586 StringBuffer command
= prepareSessionCreationCommand(sessionInfo
);
588 ICommandResult result
= executeCommand(command
.toString(), monitor
);
590 Document document
= getDocumentFromStrings(result
.getOutput());
591 NodeList sessions
= document
.getElementsByTagName(MIStrings
.SESSION
);
593 // Number of session should be equal to 1
594 if (sessions
.getLength() != 1) {
595 throw new ExecutionException(Messages
.TraceControl_CommandError
+ " " + command
+ "\n" //$NON-NLS-1$//$NON-NLS-2$
596 + NLS
.bind(Messages
.TraceControl_UnexpectedNumberOfElementError
, MIStrings
.SESSION
) + " " + sessions
.getLength()); //$NON-NLS-1$
599 // Fetch a session from output
600 ISessionInfo outputSession
= new SessionInfo(""); //$NON-NLS-1$
601 parseSession(outputSession
, sessions
.item(0));
603 // Verify session name
604 if ((outputSession
.getName().equals("")) || (!"".equals(sessionInfo
.getName()) && !outputSession
.getName().equals(sessionInfo
.getName()))) { //$NON-NLS-1$ //$NON-NLS-2$
605 // Unexpected name returned
606 throw new ExecutionException(Messages
.TraceControl_CommandError
+ " " + command
+ "\n" + //$NON-NLS-1$ //$NON-NLS-2$
607 Messages
.TraceControl_UnexpectedNameError
+ ": " + outputSession
.getName()); //$NON-NLS-1$
610 // Verify session path
611 if (!sessionInfo
.isSnapshotSession() &&
612 ((outputSession
.getSessionPath() == null) || ((sessionInfo
.getSessionPath() != null) && (!outputSession
.getSessionPath().contains(sessionInfo
.getSessionPath()))))) {
614 throw new ExecutionException(Messages
.TraceControl_CommandError
+ " " + command
+ "\n" + //$NON-NLS-1$ //$NON-NLS-2$
615 Messages
.TraceControl_UnexpectedPathError
+ ": " + outputSession
.getName()); //$NON-NLS-1$
618 if (sessionInfo
.isSnapshotSession()) {
619 // Make it a snapshot session - content of snapshot info need to
620 // set afterwards using getSession() or getSnapshotInfo()
621 outputSession
.setSnapshotInfo(new SnapshotInfo("")); //$NON-NLS-1$
624 return outputSession
;
627 private ISessionInfo
createStreamedSession(ISessionInfo sessionInfo
, IProgressMonitor monitor
) throws ExecutionException
{
629 StringBuffer command
= prepareStreamedSessionCreationCommand(sessionInfo
);
631 ICommandResult result
= executeCommand(command
.toString(), monitor
);
633 Document document
= getDocumentFromStrings(result
.getOutput());
634 NodeList sessions
= document
.getElementsByTagName(MIStrings
.SESSION
);
636 // Number of session should be equal to 1
637 if (sessions
.getLength() != 1) {
638 throw new ExecutionException(Messages
.TraceControl_CommandError
+ " " + command
+ "\n" //$NON-NLS-1$//$NON-NLS-2$
639 + NLS
.bind(Messages
.TraceControl_UnexpectedNumberOfElementError
, MIStrings
.SESSION
) + " " + sessions
.getLength()); //$NON-NLS-1$
642 // Fetch a session from output
643 ISessionInfo outputSession
= new SessionInfo(""); //$NON-NLS-1$
644 parseSession(outputSession
, sessions
.item(0));
646 // Verify session name
647 if ((outputSession
.getName().equals("")) || (!"".equals(sessionInfo
.getName()) && !outputSession
.getName().equals(sessionInfo
.getName()))) { //$NON-NLS-1$ //$NON-NLS-2$
648 // Unexpected name returned
649 throw new ExecutionException(Messages
.TraceControl_CommandError
+ " " + command
+ "\n" + //$NON-NLS-1$ //$NON-NLS-2$
650 Messages
.TraceControl_UnexpectedNameError
+ ": " + outputSession
.getName()); //$NON-NLS-1$
653 sessionInfo
.setName(outputSession
.getName());
654 sessionInfo
.setStreamedTrace(true);
656 // Verify session path
657 if (sessionInfo
.getNetworkUrl() != null) {
658 if (!sessionInfo
.isSnapshotSession() && (outputSession
.getSessionPath() == null)) {
660 throw new ExecutionException(Messages
.TraceControl_CommandError
+ " " + command
+ "\n" + //$NON-NLS-1$ //$NON-NLS-2$
661 Messages
.TraceControl_UnexpectedPathError
+ ": " + outputSession
.getName()); //$NON-NLS-1$
664 if (sessionInfo
.isSnapshotSession()) {
665 sessionInfo
.setStreamedTrace(false);
667 sessionInfo
.setSessionPath(outputSession
.getSessionPath());
668 // Check file protocol
669 Matcher matcher
= LTTngControlServiceConstants
.TRACE_FILE_PROTOCOL_PATTERN
.matcher(outputSession
.getSessionPath());
670 if (matcher
.matches()) {
671 sessionInfo
.setStreamedTrace(false);
676 // When using controlUrl and dataUrl the full session path is not known
678 // and will be set later on when listing the session
684 public void destroySession(String sessionName
, IProgressMonitor monitor
) throws ExecutionException
{
685 String newName
= formatParameter(sessionName
);
687 StringBuffer command
= createCommand(LTTngControlServiceConstants
.COMMAND_DESTROY_SESSION
, newName
);
689 ICommandResult result
= executeCommand(command
.toString(), monitor
, false);
690 String
[] errorOutput
= result
.getErrorOutput();
692 if (isError(result
) && (errorOutput
!= null)) {
693 // Don't treat this as an error
694 if (ignoredPattern(errorOutput
, LTTngControlServiceConstants
.SESSION_NOT_FOUND_ERROR_PATTERN
)) {
698 throw new ExecutionException(Messages
.TraceControl_CommandError
+ " " + command
.toString() + "\n" + formatOutput(result
)); //$NON-NLS-1$ //$NON-NLS-2$
701 // Check for action effect
702 Document doc
= getDocumentFromStrings(result
.getOutput());
703 NodeList sessions
= doc
.getElementsByTagName(MIStrings
.SESSION
);
704 if (sessions
.getLength() != 1) {
705 throw new ExecutionException(NLS
.bind(Messages
.TraceControl_MiInvalidNumberOfElementError
, MIStrings
.SESSION
));
708 Node rawSessionName
= getFirstOf(sessions
.item(0).getChildNodes(), MIStrings
.NAME
);
709 if (rawSessionName
== null) {
710 throw new ExecutionException(Messages
.TraceControl_MiMissingRequiredError
);
714 if (!rawSessionName
.getTextContent().equals(sessionName
)) {
715 throw new ExecutionException(NLS
.bind(Messages
.TraceControl_UnexpectedValueError
, rawSessionName
.getTextContent(), sessionName
));
721 * array of string that make up a command line
722 * @return string buffer with created command line
725 protected StringBuffer
createCommand(String
... strings
) {
726 StringBuffer command
= new StringBuffer();
727 command
.append(LTTngControlServiceConstants
.CONTROL_COMMAND_MI_XML
);
728 command
.append(getTracingGroupOption());
729 for (String string
: strings
) {
730 command
.append(string
);
736 * @param xmlBaseEvents
737 * a Node list of base xml event element
739 * list of event generated by the parsing of the xml event
741 * @throws ExecutionException
742 * when a raw event is not a complete/valid xml event
744 private static void getBaseEventInfo(NodeList xmlBaseEvents
, List
<IBaseEventInfo
> events
) throws ExecutionException
{
745 IBaseEventInfo eventInfo
= null;
746 for (int i
= 0; i
< xmlBaseEvents
.getLength(); i
++) {
747 NodeList rawInfos
= xmlBaseEvents
.item(i
).getChildNodes();
749 if (xmlBaseEvents
.item(i
).getNodeName().equalsIgnoreCase(MIStrings
.EVENT
)) {
750 Node rawName
= getFirstOf(rawInfos
, MIStrings
.NAME
);
751 if (rawName
== null) {
752 throw new ExecutionException(Messages
.TraceControl_MiMissingRequiredError
);
754 eventInfo
= new BaseEventInfo(rawName
.getTextContent());
756 // Populate the event
757 for (int j
= 0; j
< rawInfos
.getLength(); j
++) {
758 Node infoNode
= rawInfos
.item(j
);
759 switch (infoNode
.getNodeName()) {
761 eventInfo
.setEventType(infoNode
.getTextContent());
763 case MIStrings
.LOGLEVEL
:
764 eventInfo
.setLogLevel(infoNode
.getTextContent());
766 case MIStrings
.EVENT_FIELDS
:
767 List
<IFieldInfo
> fields
= new ArrayList
<>();
768 getFieldInfo(infoNode
.getChildNodes(), fields
);
769 eventInfo
.setFields(fields
);
775 events
.add(eventInfo
);
781 * @param xmlBaseEvents
782 * a Node list of xml event element linked to a session
784 * list of event generated by the parsing of the xml event
786 * @throws ExecutionException
787 * when a raw event is not a complete/valid xml event
789 static void getEventInfo(NodeList xmlEvents
, List
<IEventInfo
> events
) throws ExecutionException
{
790 IEventInfo eventInfo
= null;
791 for (int i
= 0; i
< xmlEvents
.getLength(); i
++) {
792 NodeList rawInfos
= xmlEvents
.item(i
).getChildNodes();
794 if (xmlEvents
.item(i
).getNodeName().equalsIgnoreCase(MIStrings
.EVENT
)) {
795 Node rawName
= getFirstOf(rawInfos
, MIStrings
.NAME
);
796 if (rawName
== null) {
797 throw new ExecutionException(Messages
.TraceControl_MiMissingRequiredError
);
800 eventInfo
= new EventInfo(rawName
.getTextContent());
803 for (int j
= 0; j
< rawInfos
.getLength(); j
++) {
804 Node infoNode
= rawInfos
.item(j
);
805 switch (infoNode
.getNodeName()) {
807 eventInfo
.setEventType(infoNode
.getTextContent());
809 case MIStrings
.LOGLEVEL_TYPE
:
810 eventInfo
.setLogLevelType(LogLevelType
.valueOfString(infoNode
.getTextContent()));
812 case MIStrings
.LOGLEVEL
:
813 eventInfo
.setLogLevel(TraceLogLevel
.valueOfString(infoNode
.getTextContent()));
815 case MIStrings
.ENABLED
:
816 eventInfo
.setState(TraceEnablement
.valueOfString(infoNode
.getTextContent()));
818 case MIStrings
.FILTER
:
820 // See bug 334 http://bugs.lttng.org/issues/334 from
822 // For now we emulate the non-mi behavior and simply put
824 eventInfo
.setFilterExpression("with filter"); //$NON-NLS-1$
826 case MIStrings
.EXCLUSION
:
827 // TODO: Currently not supported by tmf
828 // ExclusionS element is ignored
835 boolean isProbeFunction
= (eventInfo
.getEventType().equals(TraceEventType
.PROBE
)) || (eventInfo
.getEventType().equals(TraceEventType
.FUNCTION
));
836 if (isProbeFunction
) {
837 IProbeEventInfo probeEvent
= new ProbeEventInfo(eventInfo
);
838 eventInfo
= probeEvent
;
840 Node rawDataNode
= null;
841 switch (probeEvent
.getEventType()) {
845 Node rawAttributes
= getFirstOf(rawInfos
, MIStrings
.ATTRIBUTES
);
846 if (rawAttributes
== null) {
847 throw new ExecutionException(Messages
.TraceControl_MiMissingRequiredError
);
849 rawDataNode
= getFirstOf(rawAttributes
.getChildNodes(), MIStrings
.PROBE_ATTRIBUTES
);
856 throw new ExecutionException(Messages
.TraceControl_MiInvalidElementError
);
859 if (rawDataNode
== null) {
860 throw new ExecutionException(Messages
.TraceControl_MiInvalidElementError
);
864 NodeList rawDatas
= rawDataNode
.getChildNodes();
865 for (int j
= 0; j
< rawDatas
.getLength(); j
++) {
866 Node rawData
= rawDatas
.item(j
);
867 switch (rawData
.getNodeName()) {
868 case MIStrings
.SYMBOL_NAME
:
869 probeEvent
.setSymbol(rawData
.getTextContent());
871 case MIStrings
.ADDRESS
:
872 probeEvent
.setAddress(String
.format("%#016x", new BigInteger(rawData
.getTextContent()))); //$NON-NLS-1$
874 case MIStrings
.OFFSET
:
875 probeEvent
.setOffset(String
.format("%#016x", new BigInteger(rawData
.getTextContent()))); //$NON-NLS-1$
883 // Syscalls does not have name.
884 // Let put one to make sure this is user friendly via UI
885 if (eventInfo
.getEventType().equals(TraceEventType
.SYSCALL
)) {
886 eventInfo
.setName(TraceEventType
.SYSCALL
.getInName());
890 events
.add(eventInfo
);
897 * a list of xml event_field element
899 * a list of field generated by xml parsing
900 * @throws ExecutionException
901 * when parsing fail or required elements are missing
903 private static void getFieldInfo(NodeList fieldsList
, List
<IFieldInfo
> fields
) throws ExecutionException
{
904 IFieldInfo fieldInfo
= null;
905 for (int i
= 0; i
< fieldsList
.getLength(); i
++) {
906 Node field
= fieldsList
.item(i
);
907 if (field
.getNodeName().equalsIgnoreCase(MIStrings
.EVENT_FIELD
)) {
909 Node name
= getFirstOf(field
.getChildNodes(), MIStrings
.NAME
);
911 throw new ExecutionException(Messages
.TraceControl_MiMissingRequiredError
);
913 fieldInfo
= new FieldInfo(name
.getTextContent());
915 // Populate the field information
916 NodeList infos
= field
.getChildNodes();
917 for (int j
= 0; j
< infos
.getLength(); j
++) {
918 Node info
= infos
.item(j
);
919 switch (info
.getNodeName()) {
921 fieldInfo
.setFieldType(info
.getTextContent());
927 fields
.add(fieldInfo
);
933 * Retrieve the fist instance of a given node with tag name equal to tagName
937 * the list of Node to search against
939 * the tag name of the desired node
940 * @return the first occurrence of a node with a tag name equals to tagName
942 private static Node
getFirstOf(NodeList nodeList
, String tagName
) {
944 for (int i
= 0; i
< nodeList
.getLength(); i
++) {
945 if (nodeList
.item(i
).getNodeName() == tagName
) {
946 node
= nodeList
.item(i
);