lttng: Fix not being able to get available context with LTTng 2.8
[deliverable/tracecompass.git] / lttng / org.eclipse.tracecompass.lttng2.control.ui / src / org / eclipse / tracecompass / internal / lttng2 / control / ui / views / service / LTTngControlServiceMI.java
CommitLineData
0df4af5f 1/**********************************************************************
ed902a2b 2 * Copyright (c) 2014, 2015 Ericsson
0df4af5f
JRJ
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 * Jonathan Rajotte - Initial support for machine interface lttng 2.6
e5237dc5 11 * Bernd Hufmann - Fix check for live session
0df4af5f
JRJ
12 **********************************************************************/
13
9bc60be7 14package org.eclipse.tracecompass.internal.lttng2.control.ui.views.service;
0df4af5f 15
364dcfaf
BH
16import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
17
0df4af5f
JRJ
18import java.io.IOException;
19import java.io.StringReader;
6651c1b4 20import java.math.BigInteger;
0df4af5f
JRJ
21import java.net.URL;
22import java.util.ArrayList;
23import java.util.List;
24import java.util.regex.Matcher;
25
b2a6cbac 26import javax.xml.XMLConstants;
0df4af5f
JRJ
27import javax.xml.parsers.DocumentBuilder;
28import javax.xml.parsers.DocumentBuilderFactory;
29import javax.xml.parsers.ParserConfigurationException;
b2a6cbac 30import javax.xml.validation.SchemaFactory;
0df4af5f
JRJ
31
32import org.eclipse.core.commands.ExecutionException;
33import org.eclipse.core.runtime.IProgressMonitor;
d2e26145 34import org.eclipse.core.runtime.Platform;
364dcfaf
BH
35import org.eclipse.jdt.annotation.NonNull;
36import org.eclipse.jdt.annotation.Nullable;
67f8cadd 37import org.eclipse.osgi.util.NLS;
843f1eb2 38import org.eclipse.tracecompass.common.core.NonNullUtils;
9bc60be7
AM
39import org.eclipse.tracecompass.internal.lttng2.control.core.model.IBaseEventInfo;
40import org.eclipse.tracecompass.internal.lttng2.control.core.model.IChannelInfo;
41import org.eclipse.tracecompass.internal.lttng2.control.core.model.IDomainInfo;
42import org.eclipse.tracecompass.internal.lttng2.control.core.model.IEventInfo;
43import org.eclipse.tracecompass.internal.lttng2.control.core.model.IFieldInfo;
44import org.eclipse.tracecompass.internal.lttng2.control.core.model.IProbeEventInfo;
45import org.eclipse.tracecompass.internal.lttng2.control.core.model.ISessionInfo;
46import org.eclipse.tracecompass.internal.lttng2.control.core.model.ISnapshotInfo;
47import org.eclipse.tracecompass.internal.lttng2.control.core.model.IUstProviderInfo;
48import org.eclipse.tracecompass.internal.lttng2.control.core.model.LogLevelType;
49import org.eclipse.tracecompass.internal.lttng2.control.core.model.TraceDomainType;
50import org.eclipse.tracecompass.internal.lttng2.control.core.model.TraceEnablement;
51import org.eclipse.tracecompass.internal.lttng2.control.core.model.TraceEventType;
52import org.eclipse.tracecompass.internal.lttng2.control.core.model.TraceLogLevel;
53import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.BaseEventInfo;
54import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.BufferType;
55import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.ChannelInfo;
56import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.DomainInfo;
57import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.EventInfo;
58import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.FieldInfo;
59import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.ProbeEventInfo;
60import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.SessionInfo;
61import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.SnapshotInfo;
62import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.UstProviderInfo;
d2e26145 63import org.eclipse.tracecompass.internal.lttng2.control.ui.Activator;
9bc60be7
AM
64import org.eclipse.tracecompass.internal.lttng2.control.ui.views.handlers.XmlMiValidationErrorHandler;
65import org.eclipse.tracecompass.internal.lttng2.control.ui.views.messages.Messages;
364dcfaf 66import org.eclipse.tracecompass.tmf.remote.core.shell.ICommandInput;
ec619615
BH
67import org.eclipse.tracecompass.tmf.remote.core.shell.ICommandResult;
68import org.eclipse.tracecompass.tmf.remote.core.shell.ICommandShell;
0df4af5f
JRJ
69import org.w3c.dom.Document;
70import org.w3c.dom.Node;
71import org.w3c.dom.NodeList;
72import org.xml.sax.InputSource;
73import org.xml.sax.SAXException;
74
75/**
76 * Service for sending LTTng trace control commands to remote host via machine
77 * interface mode.
78 *
79 * @author Jonathan Rajotte
80 */
81public class LTTngControlServiceMI extends LTTngControlService {
82
d2e26145
MAL
83 /**
84 * The tracing key (.options) and System property to control whether or not schema validation should be used.
85 */
86 public static final String MI_SCHEMA_VALIDATION_KEY = Activator.PLUGIN_ID + "/mi/schema-validation"; //$NON-NLS-1$
87
0df4af5f
JRJ
88 // ------------------------------------------------------------------------
89 // Attributes
90 // ------------------------------------------------------------------------
91
92 private final DocumentBuilder fDocumentBuilder;
93
94 // ------------------------------------------------------------------------
95 // Constructors
96 // ------------------------------------------------------------------------
97
98 /**
99 * Constructor
100 *
101 * @param shell
102 * the command shell implementation to use
103 * @param xsdUrl
104 * the xsd schema file for validation
105 * @throws ExecutionException
106 * if the creation of the Schema and DocumentBuilder objects
107 * fails
108 */
364dcfaf 109 public LTTngControlServiceMI(@NonNull ICommandShell shell, @Nullable URL xsdUrl) throws ExecutionException {
0df4af5f
JRJ
110 super(shell);
111
112 DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
113 docBuilderFactory.setValidating(false);
114
d2e26145
MAL
115 if (isSchemaValidationEnabled()) {
116 // Validate XSD schema
117 if (xsdUrl != null) {
118 SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
119 try {
120 docBuilderFactory.setSchema(schemaFactory.newSchema(xsdUrl));
121 } catch (SAXException e) {
122 throw new ExecutionException(Messages.TraceControl_InvalidSchemaError, e);
123 }
b2a6cbac
AM
124 }
125 }
126
0df4af5f
JRJ
127 try {
128 fDocumentBuilder = docBuilderFactory.newDocumentBuilder();
129 } catch (ParserConfigurationException e) {
130 throw new ExecutionException(Messages.TraceControl_XmlDocumentBuilderError, e);
131 }
132
133 fDocumentBuilder.setErrorHandler(new XmlMiValidationErrorHandler());
134
135 }
136
d2e26145
MAL
137 private static boolean isSchemaValidationEnabled() {
138 String schemaValidationKey = Platform.getDebugOption(MI_SCHEMA_VALIDATION_KEY);
139 String systemProperty = System.getProperty(MI_SCHEMA_VALIDATION_KEY);
140 return schemaValidationKey != null && Boolean.parseBoolean(schemaValidationKey) || systemProperty != null && Boolean.parseBoolean(systemProperty);
141 }
142
0df4af5f 143 /**
cbc46cc9 144 * Generate a Document object from an list of Strings.
0df4af5f
JRJ
145 *
146 * @param xmlStrings
cbc46cc9 147 * list of strings representing an xml input
0df4af5f
JRJ
148 * @return Document generated from strings input
149 * @throws ExecutionException
150 * when parsing has failed
151 */
cbc46cc9 152 private Document getDocumentFromStrings(List<String> xmlStrings) throws ExecutionException {
0df4af5f
JRJ
153 StringBuilder concatenedString = new StringBuilder();
154 for (String string : xmlStrings) {
155 concatenedString.append(string);
156 }
157 InputSource stream = new InputSource(new StringReader(concatenedString.toString()));
158
159 Document document;
160 try {
161 document = fDocumentBuilder.parse(stream);
162 } catch (SAXException | IOException e) {
b2a6cbac 163 throw new ExecutionException(Messages.TraceControl_XmlParsingError + ':' + e.toString(), e);
0df4af5f
JRJ
164 }
165 return document;
166
167 }
168
169 /**
170 * Parse, populate and set the internal LTTngVersion variable
171 *
172 * @param xmlOutput
173 * the mi xml output of lttng version
174 * @throws ExecutionException
175 * when xml extraction fail
176 */
cbc46cc9 177 public void setVersion(List<String> xmlOutput) throws ExecutionException {
0df4af5f
JRJ
178 Document doc = getDocumentFromStrings(xmlOutput);
179 NodeList element = doc.getElementsByTagName(MIStrings.VERSION);
180 int major = 0;
181 int minor = 0;
182 int patchLevel = 0;
183 String license = ""; //$NON-NLS-1$
184 String commit = ""; //$NON-NLS-1$
185 String name = ""; //$NON-NLS-1$
186 String description = ""; //$NON-NLS-1$
187 String url = ""; //$NON-NLS-1$
188 String fullVersion = ""; //$NON-NLS-1$
189 if (element.getLength() == 1) {
190 NodeList child = element.item(0).getChildNodes();
191 // Get basic information
192 for (int i = 0; i < child.getLength(); i++) {
193 Node node = child.item(i);
194 switch (node.getNodeName()) {
195 case MIStrings.VERSION_MAJOR:
196 major = Integer.parseInt(node.getTextContent());
197 break;
198 case MIStrings.VERSION_MINOR:
199 minor = Integer.parseInt(node.getTextContent());
200 break;
201 case MIStrings.VERSION_PATCH_LEVEL:
202 patchLevel = Integer.parseInt(node.getTextContent());
203 break;
204 case MIStrings.VERSION_COMMIT:
205 commit = node.getTextContent();
206 break;
207 case MIStrings.VERSION_DESCRIPTION:
208 description = node.getTextContent();
209 break;
210 case MIStrings.VERSION_LICENSE:
211 license = node.getTextContent();
212 break;
213 case MIStrings.VERSION_NAME:
214 name = node.getTextContent();
215 break;
216 case MIStrings.VERSION_STR:
217 fullVersion = node.getTextContent();
218 break;
219 case MIStrings.VERSION_WEB:
220 url = node.getTextContent();
221 break;
222 default:
223 break;
224 }
225 }
226 setVersion(new LttngVersion(major, minor, patchLevel, license, commit, name, description, url, fullVersion));
227 } else {
228 throw new ExecutionException(Messages.TraceControl_UnsupportedVersionError);
229 }
230 }
231
232 @Override
cbc46cc9 233 public List<String> getSessionNames(IProgressMonitor monitor) throws ExecutionException {
364dcfaf 234 ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_LIST);
774a7993 235 ICommandResult result = executeCommand(command, monitor);
0df4af5f
JRJ
236
237 Document doc = getDocumentFromStrings(result.getOutput());
238
239 NodeList elements = doc.getElementsByTagName(MIStrings.NAME);
240
241 ArrayList<String> retArray = new ArrayList<>();
242 for (int i = 0; i < elements.getLength(); i++) {
243 Node node = elements.item(i);
244 if (node.getParentNode().getNodeName().equalsIgnoreCase(MIStrings.SESSION)) {
245 retArray.add(node.getTextContent());
246 }
247 }
cbc46cc9 248 return retArray;
0df4af5f
JRJ
249 }
250
251 @Override
252 public ISessionInfo getSession(String sessionName, IProgressMonitor monitor) throws ExecutionException {
364dcfaf 253 ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_LIST, sessionName);
774a7993 254 ICommandResult result = executeCommand(command, monitor);
0df4af5f
JRJ
255
256 ISessionInfo sessionInfo = new SessionInfo(sessionName);
257 Document document = getDocumentFromStrings(result.getOutput());
258
259 NodeList sessionsNode = document.getElementsByTagName(MIStrings.SESSION);
260 // There should be only one session
261 if (sessionsNode.getLength() != 1) {
517c0261 262 throw new ExecutionException(NLS.bind(Messages.TraceControl_MiInvalidNumberOfElementError, MIStrings.SESSION));
0df4af5f
JRJ
263 }
264
265 // Populate session information
67f8cadd
JRJ
266 Node rawSession = sessionsNode.item(0);
267 parseSession(sessionInfo, rawSession);
268
269 // Fetch the snapshot info
270 if (sessionInfo.isSnapshotSession()) {
271 ISnapshotInfo snapshot = getSnapshotInfo(sessionName, monitor);
272 sessionInfo.setSnapshotInfo(snapshot);
273 }
274
275 return sessionInfo;
276 }
277
278 /**
279 * @param sessionInfo
280 * @param rawSession
281 * @throws ExecutionException
282 */
283 private void parseSession(ISessionInfo sessionInfo, Node rawSession) throws ExecutionException {
284 if (!rawSession.getNodeName().equalsIgnoreCase(MIStrings.SESSION)) {
285 throw new ExecutionException(Messages.TraceControl_MiInvalidElementError);
286 }
287 NodeList rawSessionInfos = rawSession.getChildNodes();
0df4af5f
JRJ
288 for (int i = 0; i < rawSessionInfos.getLength(); i++) {
289 Node rawInfo = rawSessionInfos.item(i);
290 switch (rawInfo.getNodeName()) {
67f8cadd
JRJ
291 case MIStrings.NAME:
292 sessionInfo.setName(rawInfo.getTextContent());
293 break;
0df4af5f
JRJ
294 case MIStrings.PATH:
295 sessionInfo.setSessionPath(rawInfo.getTextContent());
296 break;
297 case MIStrings.ENABLED:
298 sessionInfo.setSessionState(rawInfo.getTextContent());
299 break;
300 case MIStrings.SNAPSHOT_MODE:
301 if (rawInfo.getTextContent().equals(LTTngControlServiceConstants.TRUE_NUMERICAL)) {
302 // real name will be set later
303 ISnapshotInfo snapshotInfo = new SnapshotInfo(""); //$NON-NLS-1$
304 sessionInfo.setSnapshotInfo(snapshotInfo);
305 }
306 break;
307 case MIStrings.LIVE_TIMER_INTERVAL:
ae02b8eb 308 long liveDelay = Long.parseLong(rawInfo.getTextContent());
e5237dc5 309 if ((liveDelay > 0 && (liveDelay <= LTTngControlServiceConstants.MAX_LIVE_TIMER_INTERVAL))) {
ae02b8eb
MAL
310 sessionInfo.setLive(true);
311 sessionInfo.setLiveUrl(SessionInfo.DEFAULT_LIVE_NETWORK_URL);
312 sessionInfo.setLivePort(SessionInfo.DEFAULT_LIVE_PORT);
313 sessionInfo.setLiveDelay(liveDelay);
314 }
0df4af5f
JRJ
315 break;
316 case MIStrings.DOMAINS:
317 // Extract the domains node
318 NodeList rawDomains = rawInfo.getChildNodes();
319 IDomainInfo domain = null;
320 for (int j = 0; j < rawDomains.getLength(); j++) {
321 if (rawDomains.item(j).getNodeName().equalsIgnoreCase(MIStrings.DOMAIN)) {
322 domain = parseDomain(rawDomains.item(j));
323 sessionInfo.addDomain(domain);
324 }
325 }
326 break;
327 default:
328 break;
329 }
330 }
331
332 if (!sessionInfo.isSnapshotSession()) {
333 Matcher matcher = LTTngControlServiceConstants.TRACE_NETWORK_PATTERN.matcher(sessionInfo.getSessionPath());
334 if (matcher.matches()) {
335 sessionInfo.setStreamedTrace(true);
336 }
337 }
0df4af5f
JRJ
338 }
339
340 /**
f4401569
JRJ
341 * Parse a raw domain XML node to a IDomainInfo object
342 *
343 * @param rawDomain
0df4af5f 344 * a domain xml node
f4401569
JRJ
345 * @return a populated {@link DomainInfo} object
346 * @throws ExecutionException
347 * when missing required xml element (type)
0df4af5f 348 */
f4401569
JRJ
349 protected IDomainInfo parseDomain(Node rawDomain) throws ExecutionException {
350 IDomainInfo domain = null;
351 // Get the type
352 Node rawType = getFirstOf(rawDomain.getChildNodes(), MIStrings.TYPE);
353 if (rawType == null) {
354 throw new ExecutionException(Messages.TraceControl_MiMissingRequiredError);
355 }
356 String rawTypeString = rawType.getTextContent().toLowerCase();
357 TraceDomainType domainType = TraceDomainType.valueOfString(rawTypeString);
358 switch (domainType) {
359 case KERNEL:
360 domain = new DomainInfo(Messages.TraceControl_KernelProviderDisplayName);
361 domain.setIsKernel(true);
362 break;
363 case UST:
364 domain = new DomainInfo(Messages.TraceControl_UstGlobalDomainDisplayName);
365 domain.setIsKernel(false);
366 break;
367 case JUL:
368 /**
369 * TODO: Support for JUL JUL substructure and semantic is not the
370 * same as a regular UST or Kernel Domain There is no channel under
371 * JUL domain only events. The channel is activated in UST Channel
372 */
373 domain = new DomainInfo(Messages.TraceControl_JULDomainDisplayName);
374 domain.setIsKernel(false);
375 break;
376 case UNKNOWN:
377 domain = new DomainInfo(Messages.TraceControl_UnknownDomainDisplayName);
378 domain.setIsKernel(false);
379 break;
380 default:
381 throw new ExecutionException(Messages.TraceControl_MiInvalidElementError);
382 }
383
384 NodeList rawInfos = rawDomain.getChildNodes();
385 for (int i = 0; i < rawInfos.getLength(); i++) {
386 Node rawInfo = rawInfos.item(i);
387 switch (rawInfo.getNodeName()) {
388 case MIStrings.BUFFER_TYPE:
389 BufferType bufferType = BufferType.valueOfString(rawInfo.getTextContent());
390 domain.setBufferType(bufferType);
391 break;
392 case MIStrings.CHANNELS:
393 ArrayList<IChannelInfo> channels = new ArrayList<>();
394 parseChannels(rawInfo.getChildNodes(), channels);
395 if (channels.size() > 0) {
396 domain.setChannels(channels);
397 }
398 break;
399 default:
400 break;
401 }
402 }
403
404 return domain;
405 }
406
407 /**
408 * Parse a list of raw channel XML node into an ArrayList of IChannelInfo
409 *
410 * @param rawChannes
411 * List of raw channel XML node
412 * @param channels
413 * the parsed channels list
414 * @throws ExecutionException
415 * when missing required xml element (type)
416 */
417 private static void parseChannels(NodeList rawChannels, ArrayList<IChannelInfo> channels) throws ExecutionException {
418 IChannelInfo channel = null;
419 for (int i = 0; i < rawChannels.getLength(); i++) {
420 Node rawChannel = rawChannels.item(i);
421 if (rawChannel.getNodeName().equalsIgnoreCase(MIStrings.CHANNEL)) {
422 channel = new ChannelInfo(""); //$NON-NLS-1$
423
424 // Populate the channel
425 NodeList rawInfos = rawChannel.getChildNodes();
426 Node rawInfo = null;
427 for (int j = 0; j < rawInfos.getLength(); j++) {
428 rawInfo = rawInfos.item(j);
429 switch (rawInfo.getNodeName()) {
430 case MIStrings.NAME:
431 channel.setName(rawInfo.getTextContent());
432 break;
433 case MIStrings.ENABLED:
434 channel.setState(TraceEnablement.valueOfString(rawInfo.getTextContent()));
435 break;
436 case MIStrings.EVENTS:
437 List<IEventInfo> events = new ArrayList<>();
438 getEventInfo(rawInfo.getChildNodes(), events);
439 channel.setEvents(events);
440 break;
441 case MIStrings.ATTRIBUTES:
442 NodeList rawAttributes = rawInfo.getChildNodes();
443 for (int k = 0; k < rawAttributes.getLength(); k++) {
444 Node attribute = rawAttributes.item(k);
445 switch (attribute.getNodeName()) {
446 case MIStrings.OVERWRITE_MODE:
447 channel.setOverwriteMode(!LTTngControlServiceConstants.OVERWRITE_MODE_ATTRIBUTE_FALSE_MI.equalsIgnoreCase(attribute.getTextContent()));
448 break;
449 case MIStrings.SUBBUF_SIZE:
450 channel.setSubBufferSize(Long.valueOf(attribute.getTextContent()));
451 break;
452 case MIStrings.NUM_SUBBUF:
453 channel.setNumberOfSubBuffers(Integer.valueOf(attribute.getTextContent()));
454 break;
455 case MIStrings.SWITCH_TIMER_INTERVAL:
456 channel.setSwitchTimer(Long.valueOf(attribute.getTextContent()));
457 break;
458 case MIStrings.READ_TIMER_INTERVAL:
459 channel.setReadTimer(Long.valueOf(attribute.getTextContent()));
460 break;
461 case MIStrings.OUTPUT_TYPE:
462 channel.setOutputType(attribute.getTextContent());
463 break;
464 case MIStrings.TRACEFILE_SIZE:
6f40b641 465 channel.setMaxSizeTraceFiles(Long.parseLong(attribute.getTextContent()));
f4401569
JRJ
466 break;
467 case MIStrings.TRACEFILE_COUNT:
468 channel.setMaxNumberTraceFiles(Integer.parseInt(attribute.getTextContent()));
469 break;
470 case MIStrings.LIVE_TIMER_INTERVAL:
471 // TODO: currently not supported by tmf
472 break;
473 default:
474 break;
475 }
476 }
477 break;
478 default:
479 break;
480 }
481 }
482 channels.add(channel);
483 }
484 }
485
0df4af5f
JRJ
486 }
487
488 @Override
489 public ISnapshotInfo getSnapshotInfo(String sessionName, IProgressMonitor monitor) throws ExecutionException {
4f9e6a03
JRJ
490 // TODO A session can have multiple snapshot output. This need to be
491 // supported in the future.
492 // Currently the SessionInfo object does not support multiple snashot
493 // output.
494 // For now only keep the last one.
364dcfaf 495 ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_SNAPSHOT, LTTngControlServiceConstants.COMMAND_LIST_SNAPSHOT_OUTPUT, LTTngControlServiceConstants.OPTION_SESSION, sessionName);
774a7993 496 ICommandResult result = executeCommand(command, monitor);
4f9e6a03
JRJ
497 Document doc = getDocumentFromStrings(result.getOutput());
498 NodeList rawSnapshotsOutputs = doc.getElementsByTagName(MIStrings.SNAPSHOT_OUTPUTS);
499
500 ISnapshotInfo snapshotInfo = new SnapshotInfo(""); //$NON-NLS-1$
501
502 // TODO: tmf does not have a notion of a ctrl url.
503 for (int i = 0; i < rawSnapshotsOutputs.getLength(); i++) {
504 NodeList rawSnapshotOutput = rawSnapshotsOutputs.item(i).getChildNodes();
505 for (int j = 0; j < rawSnapshotOutput.getLength(); j++) {
506 Node rawInfo = rawSnapshotOutput.item(j);
507 switch (rawInfo.getNodeName()) {
508 case MIStrings.ID:
509 snapshotInfo.setId(Integer.parseInt(rawInfo.getTextContent()));
510 break;
511 case MIStrings.NAME:
512 snapshotInfo.setName(rawInfo.getTextContent());
513 break;
514 case MIStrings.SNAPSHOT_CTRL_URL:
515 // The use of the ctrl_url for the snapshot path is to assure
516 // basic support. Refactoring is necessary in lttng and
517 // tmf side.
518 // See http://bugs.lttng.org/issues/828 (+comment)
519 snapshotInfo.setSnapshotPath(rawInfo.getTextContent());
520 break;
521 default:
522 break;
523 }
524 }
525 }
526
527 // Check if the snapshot output is Streamed
528 Matcher matcher2 = LTTngControlServiceConstants.TRACE_NETWORK_PATTERN.matcher(snapshotInfo.getSnapshotPath());
529 if (matcher2.matches()) {
530 snapshotInfo.setStreamedSnapshot(true);
531 }
532
533 return snapshotInfo;
0df4af5f
JRJ
534 }
535
536 @Override
537 public List<IBaseEventInfo> getKernelProvider(IProgressMonitor monitor) throws ExecutionException {
364dcfaf 538 ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_LIST, LTTngControlServiceConstants.OPTION_KERNEL);
774a7993 539 ICommandResult result = executeCommand(command, monitor, false);
0df4af5f
JRJ
540 List<IBaseEventInfo> events = new ArrayList<>();
541
13729cbc 542 if (isError(result)) {
517c0261
JRJ
543 // Ignore the following 2 cases:
544 // Spawning a session daemon
545 // Error: Unable to list kernel events
546 // or:
547 // Error: Unable to list kernel events
548 if (ignoredPattern(result.getErrorOutput(), LTTngControlServiceConstants.LIST_KERNEL_NO_KERNEL_PROVIDER_PATTERN)) {
549 return events;
550 }
364dcfaf 551 throw new ExecutionException(Messages.TraceControl_CommandError + command.toString());
0df4af5f
JRJ
552 }
553
554 Document document = getDocumentFromStrings(result.getOutput());
555 NodeList rawEvents = document.getElementsByTagName(MIStrings.EVENT);
f4401569 556 getBaseEventInfo(rawEvents, events);
0df4af5f
JRJ
557 return events;
558 }
559
560 @Override
561 public List<IUstProviderInfo> getUstProvider(IProgressMonitor monitor) throws ExecutionException {
364dcfaf 562 ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_LIST, LTTngControlServiceConstants.OPTION_UST);
0df4af5f 563 // Get the field to
774a7993 564 command.add(LTTngControlServiceConstants.OPTION_FIELDS);
0df4af5f
JRJ
565
566 // Execute
774a7993 567 ICommandResult result = executeCommand(command, monitor, false);
0df4af5f
JRJ
568 List<IUstProviderInfo> allProviders = new ArrayList<>();
569
13729cbc 570 if (isError(result)) {
517c0261
JRJ
571 // Ignore the following 2 cases:
572 // Spawning a session daemon
573 // Error: Unable to list UST events: Listing UST events failed
574 // or:
575 // Error: Unable to list UST events: Listing UST events failed
576 if (ignoredPattern(result.getErrorOutput(), LTTngControlServiceConstants.LIST_UST_NO_UST_PROVIDER_PATTERN)) {
577 return allProviders;
578 }
364dcfaf 579 throw new ExecutionException(Messages.TraceControl_CommandError + command.toString());
0df4af5f
JRJ
580 }
581
582 Document document = getDocumentFromStrings(result.getOutput());
583 NodeList rawProviders = document.getElementsByTagName(MIStrings.PID);
584
585 IUstProviderInfo providerInfo = null;
586
587 for (int i = 0; i < rawProviders.getLength(); i++) {
588 Node provider = rawProviders.item(i);
589 Node name = getFirstOf(provider.getChildNodes(), MIStrings.NAME);
590 if (name == null) {
591 throw new ExecutionException(Messages.TraceControl_MiInvalidProviderError);
592 }
593 providerInfo = new UstProviderInfo(name.getTextContent());
594
595 // Populate provider
596 NodeList infos = provider.getChildNodes();
597 for (int j = 0; j < infos.getLength(); j++) {
598 Node info = infos.item(j);
599 switch (info.getNodeName()) {
600 case MIStrings.PID_ID:
601 providerInfo.setPid(Integer.parseInt(info.getTextContent()));
602 break;
603 case MIStrings.EVENTS:
604 List<IBaseEventInfo> events = new ArrayList<>();
605 NodeList rawEvents = info.getChildNodes();
f4401569 606 getBaseEventInfo(rawEvents, events);
0df4af5f
JRJ
607 providerInfo.setEvents(events);
608 break;
609 default:
610 break;
611 }
612 }
613 allProviders.add(providerInfo);
614 }
615
616 return allProviders;
617 }
618
619 @Override
620 public ISessionInfo createSession(ISessionInfo sessionInfo, IProgressMonitor monitor) throws ExecutionException {
67f8cadd
JRJ
621 if (sessionInfo.isStreamedTrace()) {
622 return createStreamedSession(sessionInfo, monitor);
623 }
624
364dcfaf 625 ICommandInput command = prepareSessionCreationCommand(sessionInfo);
774a7993 626 ICommandResult result = executeCommand(command, monitor);
67f8cadd
JRJ
627
628 Document document = getDocumentFromStrings(result.getOutput());
629 NodeList sessions = document.getElementsByTagName(MIStrings.SESSION);
630
631 // Number of session should be equal to 1
632 if (sessions.getLength() != 1) {
633 throw new ExecutionException(Messages.TraceControl_CommandError + " " + command + "\n" //$NON-NLS-1$//$NON-NLS-2$
634 + NLS.bind(Messages.TraceControl_UnexpectedNumberOfElementError, MIStrings.SESSION) + " " + sessions.getLength()); //$NON-NLS-1$
635 }
636
637 // Fetch a session from output
638 ISessionInfo outputSession = new SessionInfo(""); //$NON-NLS-1$
639 parseSession(outputSession, sessions.item(0));
640
641 // Verify session name
642 if ((outputSession.getName().equals("")) || (!"".equals(sessionInfo.getName()) && !outputSession.getName().equals(sessionInfo.getName()))) { //$NON-NLS-1$ //$NON-NLS-2$
643 // Unexpected name returned
644 throw new ExecutionException(Messages.TraceControl_CommandError + " " + command + "\n" + //$NON-NLS-1$ //$NON-NLS-2$
645 Messages.TraceControl_UnexpectedNameError + ": " + outputSession.getName()); //$NON-NLS-1$
646 }
647
648 // Verify session path
649 if (!sessionInfo.isSnapshotSession() &&
650 ((outputSession.getSessionPath() == null) || ((sessionInfo.getSessionPath() != null) && (!outputSession.getSessionPath().contains(sessionInfo.getSessionPath()))))) {
651 // Unexpected path
652 throw new ExecutionException(Messages.TraceControl_CommandError + " " + command + "\n" + //$NON-NLS-1$ //$NON-NLS-2$
653 Messages.TraceControl_UnexpectedPathError + ": " + outputSession.getName()); //$NON-NLS-1$
654 }
655
656 if (sessionInfo.isSnapshotSession()) {
657 // Make it a snapshot session - content of snapshot info need to
658 // set afterwards using getSession() or getSnapshotInfo()
659 outputSession.setSnapshotInfo(new SnapshotInfo("")); //$NON-NLS-1$
660 }
661
662 return outputSession;
663 }
664
364dcfaf 665 private @NonNull ISessionInfo createStreamedSession(ISessionInfo sessionInfo, IProgressMonitor monitor) throws ExecutionException {
67f8cadd 666
364dcfaf 667 ICommandInput command = prepareStreamedSessionCreationCommand(sessionInfo);
67f8cadd 668
774a7993 669 ICommandResult result = executeCommand(command, monitor);
67f8cadd
JRJ
670
671 Document document = getDocumentFromStrings(result.getOutput());
672 NodeList sessions = document.getElementsByTagName(MIStrings.SESSION);
673
674 // Number of session should be equal to 1
675 if (sessions.getLength() != 1) {
676 throw new ExecutionException(Messages.TraceControl_CommandError + " " + command + "\n" //$NON-NLS-1$//$NON-NLS-2$
677 + NLS.bind(Messages.TraceControl_UnexpectedNumberOfElementError, MIStrings.SESSION) + " " + sessions.getLength()); //$NON-NLS-1$
678 }
679
680 // Fetch a session from output
681 ISessionInfo outputSession = new SessionInfo(""); //$NON-NLS-1$
682 parseSession(outputSession, sessions.item(0));
683
684 // Verify session name
685 if ((outputSession.getName().equals("")) || (!"".equals(sessionInfo.getName()) && !outputSession.getName().equals(sessionInfo.getName()))) { //$NON-NLS-1$ //$NON-NLS-2$
686 // Unexpected name returned
687 throw new ExecutionException(Messages.TraceControl_CommandError + " " + command + "\n" + //$NON-NLS-1$ //$NON-NLS-2$
688 Messages.TraceControl_UnexpectedNameError + ": " + outputSession.getName()); //$NON-NLS-1$
689 }
690
691 sessionInfo.setName(outputSession.getName());
692 sessionInfo.setStreamedTrace(true);
693
694 // Verify session path
695 if (sessionInfo.getNetworkUrl() != null) {
696 if (!sessionInfo.isSnapshotSession() && (outputSession.getSessionPath() == null)) {
697 // Unexpected path
698 throw new ExecutionException(Messages.TraceControl_CommandError + " " + command + "\n" + //$NON-NLS-1$ //$NON-NLS-2$
699 Messages.TraceControl_UnexpectedPathError + ": " + outputSession.getName()); //$NON-NLS-1$
700 }
701
702 if (sessionInfo.isSnapshotSession()) {
703 sessionInfo.setStreamedTrace(false);
704 } else {
705 sessionInfo.setSessionPath(outputSession.getSessionPath());
706 // Check file protocol
707 Matcher matcher = LTTngControlServiceConstants.TRACE_FILE_PROTOCOL_PATTERN.matcher(outputSession.getSessionPath());
708 if (matcher.matches()) {
709 sessionInfo.setStreamedTrace(false);
710 }
711 }
712 }
713
714 // When using controlUrl and dataUrl the full session path is not known
715 // yet
716 // and will be set later on when listing the session
717 return sessionInfo;
0df4af5f
JRJ
718 }
719
720 @Override
721 public void destroySession(String sessionName, IProgressMonitor monitor) throws ExecutionException {
364dcfaf 722 ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_DESTROY_SESSION, sessionName);
0df4af5f 723
774a7993 724 ICommandResult result = executeCommand(command, monitor, false);
cbc46cc9 725 List<String> errorOutput = result.getErrorOutput();
0df4af5f 726
13729cbc 727 if (isError(result)) {
517c0261
JRJ
728 // Don't treat this as an error
729 if (ignoredPattern(errorOutput, LTTngControlServiceConstants.SESSION_NOT_FOUND_ERROR_PATTERN)) {
730 return;
0df4af5f 731
517c0261 732 }
364dcfaf 733 throw new ExecutionException(Messages.TraceControl_CommandError + " " + command.toString() + "\n" + result.toString()); //$NON-NLS-1$ //$NON-NLS-2$
517c0261
JRJ
734 }
735
736 // Check for action effect
737 Document doc = getDocumentFromStrings(result.getOutput());
738 NodeList sessions = doc.getElementsByTagName(MIStrings.SESSION);
739 if (sessions.getLength() != 1) {
740 throw new ExecutionException(NLS.bind(Messages.TraceControl_MiInvalidNumberOfElementError, MIStrings.SESSION));
741 }
0df4af5f 742
517c0261
JRJ
743 Node rawSessionName = getFirstOf(sessions.item(0).getChildNodes(), MIStrings.NAME);
744 if (rawSessionName == null) {
745 throw new ExecutionException(Messages.TraceControl_MiMissingRequiredError);
746 }
747
748 // Validity check
749 if (!rawSessionName.getTextContent().equals(sessionName)) {
750 throw new ExecutionException(NLS.bind(Messages.TraceControl_UnexpectedValueError, rawSessionName.getTextContent(), sessionName));
751 }
0df4af5f
JRJ
752 }
753
0df4af5f 754 @Override
364dcfaf
BH
755 protected ICommandInput createCommand(String... strings) {
756 ICommandInput command = getCommandShell().createCommand();
774a7993 757 command.add(LTTngControlServiceConstants.CONTROL_COMMAND);
aa353506 758 List<@NonNull String> groupOption = getTracingGroupOption();
774a7993 759 if (!groupOption.isEmpty()) {
11b78e10 760 command.addAll(groupOption);
774a7993 761 }
11b78e10
BH
762 command.add(LTTngControlServiceConstants.CONTROL_COMMAND_MI_OPTION);
763 command.add(LTTngControlServiceConstants.CONTROL_COMMAND_MI_XML);
0df4af5f 764 for (String string : strings) {
364dcfaf 765 command.add(checkNotNull(string));
0df4af5f
JRJ
766 }
767 return command;
768 }
769
770 /**
f4401569
JRJ
771 * @param xmlBaseEvents
772 * a Node list of base xml event element
0df4af5f
JRJ
773 * @param events
774 * list of event generated by the parsing of the xml event
775 * element
776 * @throws ExecutionException
777 * when a raw event is not a complete/valid xml event
778 */
f4401569 779 private static void getBaseEventInfo(NodeList xmlBaseEvents, List<IBaseEventInfo> events) throws ExecutionException {
0df4af5f 780 IBaseEventInfo eventInfo = null;
f4401569
JRJ
781 for (int i = 0; i < xmlBaseEvents.getLength(); i++) {
782 NodeList rawInfos = xmlBaseEvents.item(i).getChildNodes();
0df4af5f 783 // Search for name
f4401569 784 if (xmlBaseEvents.item(i).getNodeName().equalsIgnoreCase(MIStrings.EVENT)) {
0df4af5f
JRJ
785 Node rawName = getFirstOf(rawInfos, MIStrings.NAME);
786 if (rawName == null) {
787 throw new ExecutionException(Messages.TraceControl_MiMissingRequiredError);
788 }
789 eventInfo = new BaseEventInfo(rawName.getTextContent());
790
791 // Populate the event
792 for (int j = 0; j < rawInfos.getLength(); j++) {
793 Node infoNode = rawInfos.item(j);
794 switch (infoNode.getNodeName()) {
795 case MIStrings.TYPE:
796 eventInfo.setEventType(infoNode.getTextContent());
797 break;
798 case MIStrings.LOGLEVEL:
799 eventInfo.setLogLevel(infoNode.getTextContent());
800 break;
801 case MIStrings.EVENT_FIELDS:
802 List<IFieldInfo> fields = new ArrayList<>();
803 getFieldInfo(infoNode.getChildNodes(), fields);
804 eventInfo.setFields(fields);
805 break;
806 default:
807 break;
808 }
809 }
810 events.add(eventInfo);
811 }
812 }
813 }
814
f4401569
JRJ
815 /**
816 * @param xmlBaseEvents
817 * a Node list of xml event element linked to a session
818 * @param events
819 * list of event generated by the parsing of the xml event
820 * element
821 * @throws ExecutionException
822 * when a raw event is not a complete/valid xml event
823 */
824 static void getEventInfo(NodeList xmlEvents, List<IEventInfo> events) throws ExecutionException {
825 IEventInfo eventInfo = null;
826 for (int i = 0; i < xmlEvents.getLength(); i++) {
827 NodeList rawInfos = xmlEvents.item(i).getChildNodes();
828 // Search for name
829 if (xmlEvents.item(i).getNodeName().equalsIgnoreCase(MIStrings.EVENT)) {
830 Node rawName = getFirstOf(rawInfos, MIStrings.NAME);
831 if (rawName == null) {
832 throw new ExecutionException(Messages.TraceControl_MiMissingRequiredError);
833 }
834
835 eventInfo = new EventInfo(rawName.getTextContent());
836
837 // Basic information
838 for (int j = 0; j < rawInfos.getLength(); j++) {
839 Node infoNode = rawInfos.item(j);
840 switch (infoNode.getNodeName()) {
841 case MIStrings.TYPE:
842 eventInfo.setEventType(infoNode.getTextContent());
843 break;
844 case MIStrings.LOGLEVEL_TYPE:
845 eventInfo.setLogLevelType(LogLevelType.valueOfString(infoNode.getTextContent()));
846 break;
847 case MIStrings.LOGLEVEL:
848 eventInfo.setLogLevel(TraceLogLevel.valueOfString(infoNode.getTextContent()));
849 break;
850 case MIStrings.ENABLED:
851 eventInfo.setState(TraceEnablement.valueOfString(infoNode.getTextContent()));
852 break;
853 case MIStrings.FILTER:
adecf0a7 854 // Before LTTng 2.8: We emulate the non-mi behavior and simply put
f4401569 855 // "with filter"
3b5e96d8
BH
856 if (Boolean.TRUE.toString().equals(infoNode.getTextContent())) {
857 eventInfo.setFilterExpression(Messages.TraceControl_DefaultEventFilterString);
858 }
f4401569 859 break;
adecf0a7
MAL
860 case MIStrings.FILTER_EXPRESSION:
861 eventInfo.setFilterExpression(infoNode.getTextContent());
862 break;
f4401569 863 case MIStrings.EXCLUSION:
1ed5ac2e 864 // TODO: Currently not supported by tmf
f4401569
JRJ
865 // ExclusionS element is ignored
866 break;
867 default:
868 break;
869 }
870 }
871
872 boolean isProbeFunction = (eventInfo.getEventType().equals(TraceEventType.PROBE)) || (eventInfo.getEventType().equals(TraceEventType.FUNCTION));
873 if (isProbeFunction) {
874 IProbeEventInfo probeEvent = new ProbeEventInfo(eventInfo);
875 eventInfo = probeEvent;
f4401569
JRJ
876
877 Node rawDataNode = null;
878 switch (probeEvent.getEventType()) {
f4401569 879 case FUNCTION:
6651c1b4
JRJ
880 case PROBE: {
881 // get attributes
882 Node rawAttributes = getFirstOf(rawInfos, MIStrings.ATTRIBUTES);
883 if (rawAttributes == null) {
884 throw new ExecutionException(Messages.TraceControl_MiMissingRequiredError);
885 }
886 rawDataNode = getFirstOf(rawAttributes.getChildNodes(), MIStrings.PROBE_ATTRIBUTES);
f4401569 887 break;
6651c1b4 888 }
f4401569
JRJ
889 case SYSCALL:
890 case TRACEPOINT:
891 case UNKNOWN:
892 default:
893 throw new ExecutionException(Messages.TraceControl_MiInvalidElementError);
894 }
895
896 if (rawDataNode == null) {
897 throw new ExecutionException(Messages.TraceControl_MiInvalidElementError);
898 }
899
900 // Extract info
901 NodeList rawDatas = rawDataNode.getChildNodes();
902 for (int j = 0; j < rawDatas.getLength(); j++) {
903 Node rawData = rawDatas.item(j);
904 switch (rawData.getNodeName()) {
905 case MIStrings.SYMBOL_NAME:
906 probeEvent.setSymbol(rawData.getTextContent());
907 break;
908 case MIStrings.ADDRESS:
6651c1b4 909 probeEvent.setAddress(String.format("%#016x", new BigInteger(rawData.getTextContent()))); //$NON-NLS-1$
f4401569
JRJ
910 break;
911 case MIStrings.OFFSET:
6651c1b4 912 probeEvent.setOffset(String.format("%#016x", new BigInteger(rawData.getTextContent()))); //$NON-NLS-1$
f4401569
JRJ
913 break;
914 default:
915 break;
916 }
917 }
918 }
919
f4401569
JRJ
920 // Add the event
921 events.add(eventInfo);
922 }
923 }
924 }
925
0df4af5f
JRJ
926 /**
927 * @param fieldsList
928 * a list of xml event_field element
929 * @param fields
930 * a list of field generated by xml parsing
931 * @throws ExecutionException
932 * when parsing fail or required elements are missing
933 */
934 private static void getFieldInfo(NodeList fieldsList, List<IFieldInfo> fields) throws ExecutionException {
935 IFieldInfo fieldInfo = null;
936 for (int i = 0; i < fieldsList.getLength(); i++) {
937 Node field = fieldsList.item(i);
938 if (field.getNodeName().equalsIgnoreCase(MIStrings.EVENT_FIELD)) {
939 // Get name
940 Node name = getFirstOf(field.getChildNodes(), MIStrings.NAME);
941 if (name == null) {
942 throw new ExecutionException(Messages.TraceControl_MiMissingRequiredError);
943 }
944 fieldInfo = new FieldInfo(name.getTextContent());
945
946 // Populate the field information
947 NodeList infos = field.getChildNodes();
948 for (int j = 0; j < infos.getLength(); j++) {
949 Node info = infos.item(j);
950 switch (info.getNodeName()) {
951 case MIStrings.TYPE:
952 fieldInfo.setFieldType(info.getTextContent());
953 break;
954 default:
955 break;
956 }
957 }
958 fields.add(fieldInfo);
959 }
960 }
961 }
962
963 /**
964 * Retrieve the fist instance of a given node with tag name equal to tagName
965 * parameter
966 *
967 * @param nodeList
968 * the list of Node to search against
969 * @param tagName
970 * the tag name of the desired node
971 * @return the first occurrence of a node with a tag name equals to tagName
972 */
364dcfaf 973 private static @Nullable Node getFirstOf(NodeList nodeList, String tagName) {
0df4af5f
JRJ
974 Node node = null;
975 for (int i = 0; i < nodeList.getLength(); i++) {
843f1eb2 976 if (NonNullUtils.equalsNullable(nodeList.item(i).getNodeName(), tagName)) {
0df4af5f
JRJ
977 node = nodeList.item(i);
978 break;
979 }
980 }
981 return node;
982 }
983
182e9b8f
MAL
984 @Override
985 public @NonNull List<String> getContextList(IProgressMonitor monitor) throws ExecutionException {
986 if (!isVersionSupported("2.8.0")) { //$NON-NLS-1$)
987 return super.getContextList(monitor);
988 }
989
990 ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_ADD_CONTEXT, LTTngControlServiceConstants.OPTION_LIST);
991 ICommandResult result = executeCommand(command, monitor);
992 return result.getOutput();
993 }
0df4af5f 994}
This page took 0.103952 seconds and 5 git commands to generate.