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