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