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