1583b1c36ce9456297a3e2255b898b9122a18150
[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 JRJ - STUB
451 return null;
452 }
453
454 @Override
455 public List<IBaseEventInfo> getKernelProvider(IProgressMonitor monitor) throws ExecutionException {
456 StringBuffer command = createCommand(LTTngControlServiceConstants.COMMAND_LIST_KERNEL);
457 ICommandResult result = executeCommand(command.toString(), monitor, false);
458 List<IBaseEventInfo> events = new ArrayList<>();
459
460 if (isError(result) && result.getErrorOutput() != null) {
461 // Ignore the following 2 cases:
462 // Spawning a session daemon
463 // Error: Unable to list kernel events
464 // or:
465 // Error: Unable to list kernel events
466 if (ignoredPattern(result.getErrorOutput(), LTTngControlServiceConstants.LIST_KERNEL_NO_KERNEL_PROVIDER_PATTERN)) {
467 return events;
468 }
469 throw new ExecutionException(Messages.TraceControl_CommandError + LTTngControlServiceConstants.COMMAND_LIST_KERNEL);
470 }
471
472 Document document = getDocumentFromStrings(result.getOutput());
473 NodeList rawEvents = document.getElementsByTagName(MIStrings.EVENT);
474 getBaseEventInfo(rawEvents, events);
475 return events;
476 }
477
478 @Override
479 public List<IUstProviderInfo> getUstProvider(IProgressMonitor monitor) throws ExecutionException {
480 StringBuffer command = createCommand(LTTngControlServiceConstants.COMMAND_LIST_UST);
481 // Get the field to
482 command.append(LTTngControlServiceConstants.OPTION_FIELDS);
483
484 // Execute
485 ICommandResult result = executeCommand(command.toString(), monitor, false);
486 List<IUstProviderInfo> allProviders = new ArrayList<>();
487
488 if (isError(result) && result.getErrorOutput() != null) {
489 // Ignore the following 2 cases:
490 // Spawning a session daemon
491 // Error: Unable to list UST events: Listing UST events failed
492 // or:
493 // Error: Unable to list UST events: Listing UST events failed
494 if (ignoredPattern(result.getErrorOutput(), LTTngControlServiceConstants.LIST_UST_NO_UST_PROVIDER_PATTERN)) {
495 return allProviders;
496 }
497 throw new ExecutionException(Messages.TraceControl_CommandError + LTTngControlServiceConstants.COMMAND_LIST_UST);
498 }
499
500 Document document = getDocumentFromStrings(result.getOutput());
501 NodeList rawProviders = document.getElementsByTagName(MIStrings.PID);
502
503 IUstProviderInfo providerInfo = null;
504
505 for (int i = 0; i < rawProviders.getLength(); i++) {
506 Node provider = rawProviders.item(i);
507 Node name = getFirstOf(provider.getChildNodes(), MIStrings.NAME);
508 if (name == null) {
509 throw new ExecutionException(Messages.TraceControl_MiInvalidProviderError);
510 }
511 providerInfo = new UstProviderInfo(name.getTextContent());
512
513 // Populate provider
514 NodeList infos = provider.getChildNodes();
515 for (int j = 0; j < infos.getLength(); j++) {
516 Node info = infos.item(j);
517 switch (info.getNodeName()) {
518 case MIStrings.PID_ID:
519 providerInfo.setPid(Integer.parseInt(info.getTextContent()));
520 break;
521 case MIStrings.EVENTS:
522 List<IBaseEventInfo> events = new ArrayList<>();
523 NodeList rawEvents = info.getChildNodes();
524 getBaseEventInfo(rawEvents, events);
525 providerInfo.setEvents(events);
526 break;
527 default:
528 break;
529 }
530 }
531 allProviders.add(providerInfo);
532 }
533
534 return allProviders;
535 }
536
537 @Override
538 public ISessionInfo createSession(ISessionInfo sessionInfo, IProgressMonitor monitor) throws ExecutionException {
539 if (sessionInfo.isStreamedTrace()) {
540 return createStreamedSession(sessionInfo, monitor);
541 }
542
543 StringBuffer command = prepareSessionCreationCommand(sessionInfo);
544
545 ICommandResult result = executeCommand(command.toString(), monitor);
546
547 Document document = getDocumentFromStrings(result.getOutput());
548 NodeList sessions = document.getElementsByTagName(MIStrings.SESSION);
549
550 // Number of session should be equal to 1
551 if (sessions.getLength() != 1) {
552 throw new ExecutionException(Messages.TraceControl_CommandError + " " + command + "\n" //$NON-NLS-1$//$NON-NLS-2$
553 + NLS.bind(Messages.TraceControl_UnexpectedNumberOfElementError, MIStrings.SESSION) + " " + sessions.getLength()); //$NON-NLS-1$
554 }
555
556 // Fetch a session from output
557 ISessionInfo outputSession = new SessionInfo(""); //$NON-NLS-1$
558 parseSession(outputSession, sessions.item(0));
559
560 // Verify session name
561 if ((outputSession.getName().equals("")) || (!"".equals(sessionInfo.getName()) && !outputSession.getName().equals(sessionInfo.getName()))) { //$NON-NLS-1$ //$NON-NLS-2$
562 // Unexpected name returned
563 throw new ExecutionException(Messages.TraceControl_CommandError + " " + command + "\n" + //$NON-NLS-1$ //$NON-NLS-2$
564 Messages.TraceControl_UnexpectedNameError + ": " + outputSession.getName()); //$NON-NLS-1$
565 }
566
567 // Verify session path
568 if (!sessionInfo.isSnapshotSession() &&
569 ((outputSession.getSessionPath() == null) || ((sessionInfo.getSessionPath() != null) && (!outputSession.getSessionPath().contains(sessionInfo.getSessionPath()))))) {
570 // Unexpected path
571 throw new ExecutionException(Messages.TraceControl_CommandError + " " + command + "\n" + //$NON-NLS-1$ //$NON-NLS-2$
572 Messages.TraceControl_UnexpectedPathError + ": " + outputSession.getName()); //$NON-NLS-1$
573 }
574
575 if (sessionInfo.isSnapshotSession()) {
576 // Make it a snapshot session - content of snapshot info need to
577 // set afterwards using getSession() or getSnapshotInfo()
578 outputSession.setSnapshotInfo(new SnapshotInfo("")); //$NON-NLS-1$
579 }
580
581 return outputSession;
582 }
583
584 private ISessionInfo createStreamedSession(ISessionInfo sessionInfo, IProgressMonitor monitor) throws ExecutionException {
585
586 StringBuffer command = prepareStreamedSessionCreationCommand(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 sessionInfo.setName(outputSession.getName());
611 sessionInfo.setStreamedTrace(true);
612
613 // Verify session path
614 if (sessionInfo.getNetworkUrl() != null) {
615 if (!sessionInfo.isSnapshotSession() && (outputSession.getSessionPath() == null)) {
616 // Unexpected path
617 throw new ExecutionException(Messages.TraceControl_CommandError + " " + command + "\n" + //$NON-NLS-1$ //$NON-NLS-2$
618 Messages.TraceControl_UnexpectedPathError + ": " + outputSession.getName()); //$NON-NLS-1$
619 }
620
621 if (sessionInfo.isSnapshotSession()) {
622 sessionInfo.setStreamedTrace(false);
623 } else {
624 sessionInfo.setSessionPath(outputSession.getSessionPath());
625 // Check file protocol
626 Matcher matcher = LTTngControlServiceConstants.TRACE_FILE_PROTOCOL_PATTERN.matcher(outputSession.getSessionPath());
627 if (matcher.matches()) {
628 sessionInfo.setStreamedTrace(false);
629 }
630 }
631 }
632
633 // When using controlUrl and dataUrl the full session path is not known
634 // yet
635 // and will be set later on when listing the session
636 return sessionInfo;
637
638 }
639
640 @Override
641 public void destroySession(String sessionName, IProgressMonitor monitor) throws ExecutionException {
642 String newName = formatParameter(sessionName);
643
644 StringBuffer command = createCommand(LTTngControlServiceConstants.COMMAND_DESTROY_SESSION, newName);
645
646 ICommandResult result = executeCommand(command.toString(), monitor, false);
647 String[] errorOutput = result.getErrorOutput();
648
649 if (isError(result) && (errorOutput != null)) {
650 // Don't treat this as an error
651 if (ignoredPattern(errorOutput, LTTngControlServiceConstants.SESSION_NOT_FOUND_ERROR_PATTERN)) {
652 return;
653
654 }
655 throw new ExecutionException(Messages.TraceControl_CommandError + " " + command.toString() + "\n" + formatOutput(result)); //$NON-NLS-1$ //$NON-NLS-2$
656 }
657
658 // Check for action effect
659 Document doc = getDocumentFromStrings(result.getOutput());
660 NodeList sessions = doc.getElementsByTagName(MIStrings.SESSION);
661 if (sessions.getLength() != 1) {
662 throw new ExecutionException(NLS.bind(Messages.TraceControl_MiInvalidNumberOfElementError, MIStrings.SESSION));
663 }
664
665 Node rawSessionName = getFirstOf(sessions.item(0).getChildNodes(), MIStrings.NAME);
666 if (rawSessionName == null) {
667 throw new ExecutionException(Messages.TraceControl_MiMissingRequiredError);
668 }
669
670 // Validity check
671 if (!rawSessionName.getTextContent().equals(sessionName)) {
672 throw new ExecutionException(NLS.bind(Messages.TraceControl_UnexpectedValueError, rawSessionName.getTextContent(), sessionName));
673 }
674 }
675
676 @Override
677 public void enableChannels(String sessionName, List<String> channelNames, boolean isKernel, IChannelInfo info, IProgressMonitor monitor) throws ExecutionException {
678 // TODO Auto-generated method stub
679
680 }
681
682 @Override
683 public void disableChannels(String sessionName, List<String> channelNames, boolean isKernel, IProgressMonitor monitor) throws ExecutionException {
684 // TODO Auto-generated method stub
685
686 }
687
688 @Override
689 public void enableEvents(String sessionName, String channelName, List<String> eventNames, boolean isKernel, String filterExpression, IProgressMonitor monitor) throws ExecutionException {
690 // TODO Auto-generated method stub
691
692 }
693
694 @Override
695 public void enableSyscalls(String sessionName, String channelName, IProgressMonitor monitor) throws ExecutionException {
696 // TODO Auto-generated method stub
697
698 }
699
700 @Override
701 public void enableProbe(String sessionName, String channelName, String eventName, boolean isFunction, String probe, IProgressMonitor monitor) throws ExecutionException {
702 // TODO Auto-generated method stub
703
704 }
705
706 @Override
707 public void enableLogLevel(String sessionName, String channelName, String eventName, LogLevelType logLevelType, TraceLogLevel level, String filterExpression, IProgressMonitor monitor) throws ExecutionException {
708 // TODO Auto-generated method stub
709
710 }
711
712 @Override
713 public void disableEvent(String sessionName, String channelName, List<String> eventNames, boolean isKernel, IProgressMonitor monitor) throws ExecutionException {
714 // TODO Auto-generated method stub
715
716 }
717
718 @Override
719 public List<String> getContextList(IProgressMonitor monitor) throws ExecutionException {
720 // TODO Auto-generated method stub
721 return null;
722 }
723
724 @Override
725 public void addContexts(String sessionName, String channelName, String eventName, boolean isKernel, List<String> contexts, IProgressMonitor monitor) throws ExecutionException {
726 // TODO Auto-generated method stub
727
728 }
729
730 @Override
731 public void calibrate(boolean isKernel, IProgressMonitor monitor) throws ExecutionException {
732 // TODO Auto-generated method stub
733
734 }
735
736 @Override
737 public void recordSnapshot(String sessionName, IProgressMonitor monitor) throws ExecutionException {
738 // TODO Auto-generated method stub
739
740 }
741
742 @Override
743 public void runCommands(IProgressMonitor monitor, List<String> commands) throws ExecutionException {
744 // TODO Auto-generated method stub
745
746 }
747
748 /**
749 * @param strings
750 * array of string that make up a command line
751 * @return string buffer with created command line
752 */
753 @Override
754 protected StringBuffer createCommand(String... strings) {
755 StringBuffer command = new StringBuffer();
756 command.append(LTTngControlServiceConstants.CONTROL_COMMAND_MI_XML);
757 command.append(getTracingGroupOption());
758 for (String string : strings) {
759 command.append(string);
760 }
761 return command;
762 }
763
764 /**
765 * @param xmlBaseEvents
766 * a Node list of base xml event element
767 * @param events
768 * list of event generated by the parsing of the xml event
769 * element
770 * @throws ExecutionException
771 * when a raw event is not a complete/valid xml event
772 */
773 private static void getBaseEventInfo(NodeList xmlBaseEvents, List<IBaseEventInfo> events) throws ExecutionException {
774 IBaseEventInfo eventInfo = null;
775 for (int i = 0; i < xmlBaseEvents.getLength(); i++) {
776 NodeList rawInfos = xmlBaseEvents.item(i).getChildNodes();
777 // Search for name
778 if (xmlBaseEvents.item(i).getNodeName().equalsIgnoreCase(MIStrings.EVENT)) {
779 Node rawName = getFirstOf(rawInfos, MIStrings.NAME);
780 if (rawName == null) {
781 throw new ExecutionException(Messages.TraceControl_MiMissingRequiredError);
782 }
783 eventInfo = new BaseEventInfo(rawName.getTextContent());
784
785 // Populate the event
786 for (int j = 0; j < rawInfos.getLength(); j++) {
787 Node infoNode = rawInfos.item(j);
788 switch (infoNode.getNodeName()) {
789 case MIStrings.TYPE:
790 eventInfo.setEventType(infoNode.getTextContent());
791 break;
792 case MIStrings.LOGLEVEL:
793 eventInfo.setLogLevel(infoNode.getTextContent());
794 break;
795 case MIStrings.EVENT_FIELDS:
796 List<IFieldInfo> fields = new ArrayList<>();
797 getFieldInfo(infoNode.getChildNodes(), fields);
798 eventInfo.setFields(fields);
799 break;
800 default:
801 break;
802 }
803 }
804 events.add(eventInfo);
805 }
806 }
807 }
808
809 /**
810 * @param xmlBaseEvents
811 * a Node list of xml event element linked to a session
812 * @param events
813 * list of event generated by the parsing of the xml event
814 * element
815 * @throws ExecutionException
816 * when a raw event is not a complete/valid xml event
817 */
818 static void getEventInfo(NodeList xmlEvents, List<IEventInfo> events) throws ExecutionException {
819 IEventInfo eventInfo = null;
820 for (int i = 0; i < xmlEvents.getLength(); i++) {
821 NodeList rawInfos = xmlEvents.item(i).getChildNodes();
822 // Search for name
823 if (xmlEvents.item(i).getNodeName().equalsIgnoreCase(MIStrings.EVENT)) {
824 Node rawName = getFirstOf(rawInfos, MIStrings.NAME);
825 if (rawName == null) {
826 throw new ExecutionException(Messages.TraceControl_MiMissingRequiredError);
827 }
828
829 eventInfo = new EventInfo(rawName.getTextContent());
830
831 // Basic information
832 for (int j = 0; j < rawInfos.getLength(); j++) {
833 Node infoNode = rawInfos.item(j);
834 switch (infoNode.getNodeName()) {
835 case MIStrings.TYPE:
836 eventInfo.setEventType(infoNode.getTextContent());
837 break;
838 case MIStrings.LOGLEVEL_TYPE:
839 eventInfo.setLogLevelType(LogLevelType.valueOfString(infoNode.getTextContent()));
840 break;
841 case MIStrings.LOGLEVEL:
842 eventInfo.setLogLevel(TraceLogLevel.valueOfString(infoNode.getTextContent()));
843 break;
844 case MIStrings.ENABLED:
845 eventInfo.setState(TraceEnablement.valueOfString(infoNode.getTextContent()));
846 break;
847 case MIStrings.FILTER:
848 // TODO
849 // See bug 334 http://bugs.lttng.org/issues/334 from
850 // LTTng
851 // For now we emulate the a behavior, and simply put
852 // "with filter"
853 eventInfo.setFilterExpression("with filter"); //$NON-NLS-1$
854 break;
855 case MIStrings.EXCLUSION:
856 // TODO:Currently not supported by tmf
857 // ExclusionS element is ignored
858 break;
859 default:
860 break;
861 }
862 }
863
864 boolean isProbeFunction = (eventInfo.getEventType().equals(TraceEventType.PROBE)) || (eventInfo.getEventType().equals(TraceEventType.FUNCTION));
865 if (isProbeFunction) {
866 IProbeEventInfo probeEvent = new ProbeEventInfo(eventInfo);
867 eventInfo = probeEvent;
868 // get attributes
869 Node rawAttributes = getFirstOf(rawInfos, MIStrings.ATTRIBUTES);
870 if (rawAttributes == null) {
871 throw new ExecutionException(Messages.TraceControl_MiMissingRequiredError);
872 }
873
874 Node rawDataNode = null;
875 switch (probeEvent.getEventType()) {
876 case PROBE:
877 rawDataNode = getFirstOf(rawAttributes.getChildNodes(), MIStrings.PROBE_ATTRIBUTES);
878 break;
879 case FUNCTION:
880 rawDataNode = getFirstOf(rawAttributes.getChildNodes(), MIStrings.FUNCTION_ATTRIBUTES);
881 break;
882 case SYSCALL:
883 case TRACEPOINT:
884 case UNKNOWN:
885 default:
886 throw new ExecutionException(Messages.TraceControl_MiInvalidElementError);
887 }
888
889 if (rawDataNode == null) {
890 throw new ExecutionException(Messages.TraceControl_MiInvalidElementError);
891 }
892
893 // Extract info
894 NodeList rawDatas = rawDataNode.getChildNodes();
895 for (int j = 0; j < rawDatas.getLength(); j++) {
896 Node rawData = rawDatas.item(j);
897 switch (rawData.getNodeName()) {
898 case MIStrings.SYMBOL_NAME:
899 probeEvent.setSymbol(rawData.getTextContent());
900 break;
901 case MIStrings.ADDRESS:
902 probeEvent.setAddress(rawData.getTextContent());
903 break;
904 case MIStrings.OFFSET:
905 probeEvent.setOffset(rawData.getTextContent());
906 break;
907 default:
908 break;
909 }
910 }
911 }
912
913 // Syscalls does not have name.
914 // Let put one to make sure this is user friendly via UI
915 if (eventInfo.getEventType().equals(TraceEventType.SYSCALL)) {
916 eventInfo.setName(TraceEventType.SYSCALL.getInName());
917 }
918
919 // Add the event
920 events.add(eventInfo);
921 }
922 }
923 }
924
925 /**
926 * @param fieldsList
927 * a list of xml event_field element
928 * @param fields
929 * a list of field generated by xml parsing
930 * @throws ExecutionException
931 * when parsing fail or required elements are missing
932 */
933 private static void getFieldInfo(NodeList fieldsList, List<IFieldInfo> fields) throws ExecutionException {
934 IFieldInfo fieldInfo = null;
935 for (int i = 0; i < fieldsList.getLength(); i++) {
936 Node field = fieldsList.item(i);
937 if (field.getNodeName().equalsIgnoreCase(MIStrings.EVENT_FIELD)) {
938 // Get name
939 Node name = getFirstOf(field.getChildNodes(), MIStrings.NAME);
940 if (name == null) {
941 throw new ExecutionException(Messages.TraceControl_MiMissingRequiredError);
942 }
943 fieldInfo = new FieldInfo(name.getTextContent());
944
945 // Populate the field information
946 NodeList infos = field.getChildNodes();
947 for (int j = 0; j < infos.getLength(); j++) {
948 Node info = infos.item(j);
949 switch (info.getNodeName()) {
950 case MIStrings.TYPE:
951 fieldInfo.setFieldType(info.getTextContent());
952 break;
953 default:
954 break;
955 }
956 }
957 fields.add(fieldInfo);
958 }
959 }
960 }
961
962 /**
963 * Retrieve the fist instance of a given node with tag name equal to tagName
964 * parameter
965 *
966 * @param nodeList
967 * the list of Node to search against
968 * @param tagName
969 * the tag name of the desired node
970 * @return the first occurrence of a node with a tag name equals to tagName
971 */
972 private static Node getFirstOf(NodeList nodeList, String tagName) {
973 Node node = null;
974 for (int i = 0; i < nodeList.getLength(); i++) {
975 if (nodeList.item(i).getNodeName() == tagName) {
976 node = nodeList.item(i);
977 break;
978 }
979 }
980 return node;
981 }
982
983 }
This page took 0.056159 seconds and 4 git commands to generate.