| /********************************************************************** |
| * Copyright (c) 2012, 2016 Ericsson |
| * |
| * All rights reserved. This program and the accompanying materials are |
| * made available under the terms of the Eclipse Public License 2.0 which |
| * accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Bernd Hufmann - Initial API and implementation |
| * Bernd Hufmann - Updated for support of LTTng Tools 2.1 |
| * Simon Delisle - Updated for support of LTTng Tools 2.2 |
| * Marc-Andre Laperle - Support for creating a live session |
| * Markus Schorn - Bug 448058: Use org.eclipse.remote in favor of RSE |
| **********************************************************************/ |
| package org.eclipse.tracecompass.internal.lttng2.control.ui.views.service; |
| |
| import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; |
| import static org.eclipse.tracecompass.common.core.NonNullUtils.nullToEmptyString; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| import org.eclipse.core.commands.ExecutionException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.jdt.annotation.Nullable; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.IBaseEventInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.IChannelInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.IDomainInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.IEventInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.IFieldInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.IProbeEventInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.ISessionInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.ISnapshotInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.ITraceLogLevel; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.IUstProviderInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.LogLevelType; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.TraceDomainType; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.TraceEventType; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.TraceLogLevel; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.BaseEventInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.BufferType; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.ChannelInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.DomainInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.EventInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.FieldInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.ProbeEventInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.SessionInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.SnapshotInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.core.model.impl.UstProviderInfo; |
| import org.eclipse.tracecompass.internal.lttng2.control.ui.views.logging.ControlCommandLogger; |
| import org.eclipse.tracecompass.internal.lttng2.control.ui.views.messages.Messages; |
| import org.eclipse.tracecompass.internal.lttng2.control.ui.views.preferences.ControlPreferences; |
| import org.eclipse.tracecompass.tmf.remote.core.shell.ICommandInput; |
| import org.eclipse.tracecompass.tmf.remote.core.shell.ICommandResult; |
| import org.eclipse.tracecompass.tmf.remote.core.shell.ICommandShell; |
| |
| /** |
| * <p> |
| * Service for sending LTTng trace control commands to remote host. |
| * </p> |
| * |
| * @author Bernd Hufmann |
| */ |
| public class LTTngControlService implements ILttngControlService { |
| |
| // ------------------------------------------------------------------------ |
| // Attributes |
| // ------------------------------------------------------------------------ |
| /** |
| * The command shell implementation |
| */ |
| private final @NonNull ICommandShell fCommandShell; |
| |
| /** |
| * The version string. |
| */ |
| private @NonNull LttngVersion fVersion = LttngVersion.NULL_VERSION; |
| |
| // ------------------------------------------------------------------------ |
| // Constructors |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Constructor |
| * |
| * @param shell |
| * - the command shell implementation to use |
| */ |
| public LTTngControlService(@NonNull ICommandShell shell) { |
| fCommandShell = shell; |
| } |
| |
| // ------------------------------------------------------------------------ |
| // Accessors |
| // ------------------------------------------------------------------------ |
| |
| @Override |
| public String getVersionString() { |
| return nullToEmptyString(fVersion.toString()); |
| } |
| |
| @Override |
| public LttngVersion getVersion() { |
| return fVersion; |
| } |
| |
| /** |
| * Sets the version of the LTTng 2.0 control service. |
| * |
| * @param version |
| * - a version to set |
| */ |
| public void setVersion(@Nullable String version) { |
| if (version != null) { |
| fVersion = new LttngVersion(version); |
| } |
| } |
| |
| /** |
| * Sets the version of the LTTng 2.x control service. |
| * |
| * @param version |
| * - a version to set |
| */ |
| protected void setVersion(LttngVersion version) { |
| if (version != null) { |
| fVersion = version; |
| } |
| } |
| |
| @Override |
| public boolean isVersionSupported(String version) { |
| LttngVersion tmp = new LttngVersion(version); |
| return (fVersion.compareTo(tmp) >= 0) ? true : false; |
| } |
| |
| /** |
| * Returns the command shell implementation. |
| * |
| * @return the command shell implementation |
| */ |
| protected ICommandShell getCommandShell() { |
| return fCommandShell; |
| } |
| |
| // ------------------------------------------------------------------------ |
| // Operations |
| // ------------------------------------------------------------------------ |
| |
| @Override |
| public List<String> getSessionNames(IProgressMonitor monitor) throws ExecutionException { |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_LIST); |
| |
| ICommandResult result = executeCommand(command, monitor); |
| |
| // Output: |
| // Available tracing sessions: |
| // 1) mysession1 (/home/user/lttng-traces/mysession1-20120123-083928) |
| // [inactive] |
| // 2) mysession (/home/user/lttng-traces/mysession-20120123-083318) |
| // [inactive] |
| // |
| // Use lttng list <session_name> for more details |
| |
| ArrayList<String> retArray = new ArrayList<>(); |
| for (String line : result.getOutput()) { |
| Matcher matcher = LTTngControlServiceConstants.SESSION_PATTERN.matcher(line); |
| if (matcher.matches()) { |
| retArray.add(matcher.group(2).trim()); |
| } |
| } |
| return retArray; |
| } |
| |
| /** |
| * Check if there is a pattern to be ignored into a sequence of string |
| * |
| * @param input |
| * an input list of Strings |
| * @param pattern |
| * the pattern to search for |
| * @return if the pattern exist in the array of string |
| */ |
| protected boolean ignoredPattern(List<String> input, Pattern pattern) { |
| for (String line : input) { |
| Matcher matcher = pattern.matcher(line); |
| if (matcher.matches()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public ISessionInfo getSession(String sessionName, IProgressMonitor monitor) throws ExecutionException { |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_LIST, sessionName); |
| ICommandResult result = executeCommand(command, monitor); |
| |
| int index = 0; |
| |
| // Output: |
| // Tracing session mysession2: [inactive] |
| // Trace path: /home/eedbhu/lttng-traces/mysession2-20120123-110330 |
| ISessionInfo sessionInfo = new SessionInfo(sessionName); |
| |
| while (index < result.getOutput().size()) { |
| // Tracing session mysession2: [inactive] |
| // Trace path: /home/eedbhu/lttng-traces/mysession2-20120123-110330 |
| // |
| // === Domain: Kernel === |
| // |
| String line = result.getOutput().get(index); |
| Matcher matcher = LTTngControlServiceConstants.TRACE_SESSION_PATTERN.matcher(line); |
| if (matcher.matches()) { |
| sessionInfo.setSessionState(matcher.group(2)); |
| index++; |
| continue; |
| } |
| |
| matcher = LTTngControlServiceConstants.TRACE_SNAPSHOT_SESSION_PATTERN.matcher(line); |
| if (matcher.matches()) { |
| sessionInfo.setSessionState(matcher.group(2)); |
| // real name will be set later |
| ISnapshotInfo snapshotInfo = new SnapshotInfo(""); //$NON-NLS-1$ |
| sessionInfo.setSnapshotInfo(snapshotInfo); |
| index++; |
| continue; |
| } |
| |
| if (!sessionInfo.isSnapshotSession()) { |
| matcher = LTTngControlServiceConstants.TRACE_NETWORK_PATH_PATTERN.matcher(line); |
| if (matcher.matches()) { |
| sessionInfo.setStreamedTrace(true); |
| } |
| |
| matcher = LTTngControlServiceConstants.TRACE_SESSION_PATH_PATTERN.matcher(line); |
| if (matcher.matches()) { |
| sessionInfo.setSessionPath(matcher.group(1).trim()); |
| index++; |
| continue; |
| } |
| } |
| |
| matcher = LTTngControlServiceConstants.DOMAIN_KERNEL_PATTERN.matcher(line); |
| if (matcher.matches()) { |
| // Create Domain |
| IDomainInfo domainInfo = new DomainInfo(Messages.TraceControl_KernelDomainDisplayName); |
| |
| // set kernel domain |
| domainInfo.setDomain(TraceDomainType.KERNEL); |
| |
| // in domain kernel |
| ArrayList<IChannelInfo> channels = new ArrayList<>(); |
| index = parseDomain(result.getOutput(), index, channels, domainInfo); |
| |
| if (!channels.isEmpty()) { |
| // add domain |
| sessionInfo.addDomain(domainInfo); |
| |
| // set channels |
| domainInfo.setChannels(channels); |
| } |
| continue; |
| } |
| |
| matcher = LTTngControlServiceConstants.DOMAIN_UST_GLOBAL_PATTERN.matcher(line); |
| if (matcher.matches()) { |
| IDomainInfo domainInfo = new DomainInfo(Messages.TraceControl_UstGlobalDomainDisplayName); |
| |
| // set kernel domain |
| domainInfo.setDomain(TraceDomainType.UST); |
| |
| // in domain UST |
| ArrayList<IChannelInfo> channels = new ArrayList<>(); |
| index = parseDomain(result.getOutput(), index, channels, domainInfo); |
| |
| if (!channels.isEmpty()) { |
| // add domain |
| sessionInfo.addDomain(domainInfo); |
| |
| // set channels |
| domainInfo.setChannels(channels); |
| } |
| continue; |
| } |
| matcher = LTTngControlServiceConstants.LIST_LIVE_TIMER_INTERVAL_PATTERN.matcher(line); |
| if (matcher.matches()) { |
| long liveDelay = Long.parseLong(matcher.group(1)); |
| if ((liveDelay > 0) && (liveDelay <= LTTngControlServiceConstants.MAX_LIVE_TIMER_INTERVAL)) { |
| sessionInfo.setLive(true); |
| sessionInfo.setLiveUrl(SessionInfo.DEFAULT_LIVE_NETWORK_URL); |
| sessionInfo.setLivePort(SessionInfo.DEFAULT_LIVE_PORT); |
| sessionInfo.setLiveDelay(liveDelay); |
| } |
| index++; |
| continue; |
| } |
| |
| index++; |
| } |
| |
| if (sessionInfo.isSnapshotSession()) { |
| ISnapshotInfo snapshot = getSnapshotInfo(sessionName, monitor); |
| sessionInfo.setSnapshotInfo(snapshot); |
| } |
| |
| return sessionInfo; |
| } |
| |
| @Override |
| public ISnapshotInfo getSnapshotInfo(String sessionName, IProgressMonitor monitor) throws ExecutionException { |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_SNAPSHOT, LTTngControlServiceConstants.COMMAND_LIST_SNAPSHOT_OUTPUT, LTTngControlServiceConstants.OPTION_SESSION, sessionName); |
| ICommandResult result = executeCommand(command, monitor); |
| |
| int index = 0; |
| |
| // Output: |
| // [1] snapshot-1: /home/user/lttng-traces/my-20130909-114431 |
| // or |
| // [3] snapshot-3: net4://172.0.0.1/ |
| ISnapshotInfo snapshotInfo = new SnapshotInfo(""); //$NON-NLS-1$ |
| |
| while (index < result.getOutput().size()) { |
| String line = result.getOutput().get(index); |
| Matcher matcher = LTTngControlServiceConstants.LIST_SNAPSHOT_OUTPUT_PATTERN.matcher(line); |
| if (matcher.matches()) { |
| snapshotInfo.setId(Integer.valueOf(matcher.group(1))); |
| snapshotInfo.setName(matcher.group(2)); |
| snapshotInfo.setSnapshotPath(matcher.group(3)); |
| |
| Matcher matcher2 = LTTngControlServiceConstants.SNAPSHOT_NETWORK_PATH_PATTERN.matcher(snapshotInfo.getSnapshotPath()); |
| if (matcher2.matches()) { |
| snapshotInfo.setStreamedSnapshot(true); |
| } |
| |
| index++; |
| break; |
| } |
| index++; |
| } |
| |
| return snapshotInfo; |
| } |
| |
| @Override |
| public List<IBaseEventInfo> getKernelProvider(IProgressMonitor monitor) throws ExecutionException { |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_LIST, LTTngControlServiceConstants.OPTION_KERNEL); |
| ICommandResult result = executeCommand(command, monitor, false); |
| |
| List<IBaseEventInfo> events = new ArrayList<>(); |
| |
| // Ignore the following 2 cases: |
| // Spawning a session daemon |
| // Error: Unable to list kernel events |
| // or: |
| // Error: Unable to list kernel events |
| // |
| if (ignoredPattern(result.getErrorOutput(), LTTngControlServiceConstants.LIST_KERNEL_NO_KERNEL_PROVIDER_PATTERN)) { |
| return events; |
| } |
| |
| if (isError(result)) { |
| throw new ExecutionException(Messages.TraceControl_CommandError + " " + command.toString() + "\n" + result.toString()); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| // Kernel events: |
| // ------------- |
| // sched_kthread_stop (type: tracepoint) |
| getProviderEventInfo(result.getOutput(), 0, events); |
| return events; |
| } |
| |
| @Override |
| public List<IUstProviderInfo> getUstProvider() throws ExecutionException { |
| return getUstProvider(new NullProgressMonitor()); |
| } |
| |
| @Override |
| public List<IUstProviderInfo> getUstProvider(IProgressMonitor monitor) throws ExecutionException { |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_LIST, LTTngControlServiceConstants.OPTION_UST); |
| |
| if (isVersionSupported("2.1.0")) { //$NON-NLS-1$ |
| command.add(LTTngControlServiceConstants.OPTION_FIELDS); |
| } |
| |
| ICommandResult result = executeCommand(command, monitor, false); |
| List<IUstProviderInfo> allProviders = new ArrayList<>(); |
| |
| // Workaround for versions 2.0.x which causes a segmentation fault for |
| // this command |
| // if LTTng Tools is compiled without UST support. |
| if (!isVersionSupported("2.1.0") && (result.getResult() != 0)) { //$NON-NLS-1$ |
| return allProviders; |
| } |
| |
| // Ignore the following 2 cases: |
| // Spawning a session daemon |
| // Error: Unable to list UST events: Listing UST events failed |
| // or: |
| // Error: Unable to list UST events: Listing UST events failed |
| // |
| if (ignoredPattern(result.getErrorOutput(), LTTngControlServiceConstants.LIST_UST_NO_UST_PROVIDER_PATTERN)) { |
| return allProviders; |
| } |
| |
| if (isError(result)) { |
| throw new ExecutionException(Messages.TraceControl_CommandError + " " + command.toString() + "\n" + result.toString()); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| // Note that field print-outs exists for version >= 2.1.0 |
| // |
| // UST events: |
| // ------------- |
| // |
| // PID: 3635 - Name: |
| // /home/user/git/lttng-ust/tests/hello.cxx/.libs/lt-hello |
| // ust_tests_hello:tptest_sighandler (loglevel: TRACE_EMERG0) (type: |
| // tracepoint) |
| // ust_tests_hello:tptest (loglevel: TRACE_EMERG0) (type: tracepoint) |
| // field: doublefield (float) |
| // field: floatfield (float) |
| // field: stringfield (string) |
| // |
| // PID: 6459 - Name: |
| // /home/user/git/lttng-ust/tests/hello.cxx/.libs/lt-hello |
| // ust_tests_hello:tptest_sighandler (loglevel: TRACE_EMERG0) (type: |
| // tracepoint) |
| // ust_tests_hello:tptest (loglevel: TRACE_EMERG0) (type: tracepoint) |
| // field: doublefield (float) |
| // field: floatfield (float) |
| // field: stringfield (string) |
| |
| IUstProviderInfo provider = null; |
| |
| int index = 0; |
| while (index < result.getOutput().size()) { |
| String line = result.getOutput().get(index); |
| Matcher matcher = LTTngControlServiceConstants.UST_PROVIDER_PATTERN.matcher(line); |
| if (matcher.matches()) { |
| provider = new UstProviderInfo(matcher.group(2).trim()); |
| provider.setPid(Integer.valueOf(matcher.group(1).trim())); |
| List<IBaseEventInfo> events = new ArrayList<>(); |
| index = getProviderEventInfo(result.getOutput(), ++index, events); |
| provider.setEvents(events); |
| allProviders.add(provider); |
| } else { |
| index++; |
| } |
| } |
| return allProviders; |
| } |
| |
| @Override |
| public ISessionInfo createSession(ISessionInfo sessionInfo, IProgressMonitor monitor) throws ExecutionException { |
| if (sessionInfo.isStreamedTrace()) { |
| return createStreamedSession(sessionInfo, monitor); |
| } |
| |
| ICommandInput command = prepareSessionCreationCommand(sessionInfo); |
| |
| ICommandResult result = executeCommand(command, monitor); |
| |
| // Session myssession2 created. |
| // Traces will be written in |
| // /home/user/lttng-traces/myssession2-20120209-095418 |
| List<String> output = result.getOutput(); |
| |
| // Get and session name and path |
| String name = null; |
| String path = null; |
| |
| for (String line : output) { |
| Matcher nameMatcher = LTTngControlServiceConstants.CREATE_SESSION_NAME_PATTERN.matcher(line); |
| Matcher pathMatcher = LTTngControlServiceConstants.CREATE_SESSION_PATH_PATTERN.matcher(line); |
| if (nameMatcher.matches()) { |
| name = String.valueOf(nameMatcher.group(1).trim()); |
| } else if (pathMatcher.matches()) { |
| path = String.valueOf(pathMatcher.group(1).trim()); |
| } |
| } |
| |
| // Verify session name |
| if ((name == null) || (!"".equals(sessionInfo.getName()) && !name.equals(sessionInfo.getName()))) { //$NON-NLS-1$ |
| // Unexpected name returned |
| throw new ExecutionException(Messages.TraceControl_CommandError + " " + command.toString() + "\n" + //$NON-NLS-1$ //$NON-NLS-2$ |
| Messages.TraceControl_UnexpectedNameError + ": " + name); //$NON-NLS-1$ |
| } |
| |
| sessionInfo.setName(name); |
| // Verify session path |
| if (!sessionInfo.isSnapshotSession() && |
| ((path == null) || ((sessionInfo.getSessionPath() != null) && (!path.contains(sessionInfo.getSessionPath()))))) { |
| // Unexpected path |
| throw new ExecutionException(Messages.TraceControl_CommandError + " " + command.toString() + "\n" + //$NON-NLS-1$ //$NON-NLS-2$ |
| Messages.TraceControl_UnexpectedPathError + ": " + name); //$NON-NLS-1$ |
| } |
| |
| if (sessionInfo.isSnapshotSession()) { |
| // Make it a snapshot session - content of snapshot info need to |
| // set afterwards using getSession() or getSnapshotInfo() |
| sessionInfo.setSnapshotInfo(new SnapshotInfo("")); //$NON-NLS-1$ |
| } else { |
| sessionInfo.setSessionPath(path); |
| } |
| |
| return sessionInfo; |
| |
| } |
| |
| /** |
| * Basic generation of command for session creation |
| * |
| * @param sessionInfo |
| * the session to create |
| * @return the basic command for command creation |
| */ |
| protected @NonNull ICommandInput prepareSessionCreationCommand(ISessionInfo sessionInfo) { |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_CREATE_SESSION); |
| if (!sessionInfo.getName().isEmpty()) { |
| command.add(sessionInfo.getName()); |
| } |
| |
| String newPath = sessionInfo.getSessionPath(); |
| if (newPath != null && !"".equals(newPath)) { //$NON-NLS-1$ |
| command.add(LTTngControlServiceConstants.OPTION_OUTPUT_PATH); |
| command.add(newPath); |
| } |
| |
| if (sessionInfo.isSnapshotSession()) { |
| command.add(LTTngControlServiceConstants.OPTION_SNAPSHOT); |
| } |
| return command; |
| } |
| |
| private @NonNull ISessionInfo createStreamedSession(ISessionInfo sessionInfo, IProgressMonitor monitor) throws ExecutionException { |
| |
| ICommandInput command = prepareStreamedSessionCreationCommand(sessionInfo); |
| |
| ICommandResult result = executeCommand(command, monitor); |
| |
| // Verify output |
| List<String> output = result.getOutput(); |
| |
| // Get and session name and path |
| String name = null; |
| String path = null; |
| |
| for (String line : output) { |
| Matcher nameMatcher = LTTngControlServiceConstants.CREATE_SESSION_NAME_PATTERN.matcher(line); |
| Matcher pathMatcher = LTTngControlServiceConstants.CREATE_SESSION_PATH_PATTERN.matcher(line); |
| |
| if (nameMatcher.matches()) { |
| name = String.valueOf(nameMatcher.group(1).trim()); |
| } else if (pathMatcher.matches() && (sessionInfo.getNetworkUrl() != null)) { |
| path = String.valueOf(pathMatcher.group(1).trim()); |
| } |
| } |
| |
| // Verify session name |
| if ((name == null) || (!"".equals(sessionInfo.getName()) && !name.equals(sessionInfo.getName()))) { //$NON-NLS-1$ |
| // Unexpected name returned |
| throw new ExecutionException(Messages.TraceControl_CommandError + " " + command.toString() + "\n" + //$NON-NLS-1$ //$NON-NLS-2$ |
| Messages.TraceControl_UnexpectedNameError + ": " + name); //$NON-NLS-1$ |
| } |
| |
| sessionInfo.setName(name); |
| |
| sessionInfo.setStreamedTrace(true); |
| |
| // Verify session path |
| if (sessionInfo.getNetworkUrl() != null) { |
| if (!sessionInfo.isSnapshotSession() && (path == null)) { |
| // Unexpected path |
| throw new ExecutionException(Messages.TraceControl_CommandError + " " + command.toString() + "\n" + //$NON-NLS-1$ //$NON-NLS-2$ |
| Messages.TraceControl_UnexpectedPathError + ": " + name); //$NON-NLS-1$ |
| } |
| |
| if (sessionInfo.isSnapshotSession()) { |
| sessionInfo.setStreamedTrace(false); |
| } else { |
| sessionInfo.setSessionPath(path); |
| // Check file protocol |
| Matcher matcher = LTTngControlServiceConstants.TRACE_FILE_PROTOCOL_PATTERN.matcher(path); |
| if (matcher.matches()) { |
| sessionInfo.setStreamedTrace(false); |
| } |
| } |
| } |
| |
| // When using controlUrl and dataUrl the full session path is not known |
| // yet and will be set later on when listing the session |
| |
| return sessionInfo; |
| } |
| |
| /** |
| * Basic generation of command for streamed session creation |
| * |
| * @param sessionInfo |
| * the session to create |
| * @return the basic command for command creation |
| */ |
| protected @NonNull ICommandInput prepareStreamedSessionCreationCommand(ISessionInfo sessionInfo) { |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_CREATE_SESSION); |
| if (!sessionInfo.getName().isEmpty()) { |
| command.add(sessionInfo.getName()); |
| } |
| |
| if (sessionInfo.isSnapshotSession()) { |
| command.add(LTTngControlServiceConstants.OPTION_SNAPSHOT); |
| } else if (sessionInfo.isLive()) { |
| command.add(LTTngControlServiceConstants.OPTION_LIVE); |
| if (sessionInfo.getLiveDelay() != LTTngControlServiceConstants.UNUSED_VALUE) { |
| command.add(String.valueOf(sessionInfo.getLiveDelay())); |
| } |
| } |
| |
| if (sessionInfo.getNetworkUrl() != null) { |
| command.add(LTTngControlServiceConstants.OPTION_NETWORK_URL); |
| command.add(sessionInfo.getNetworkUrl()); |
| } else { |
| command.add(LTTngControlServiceConstants.OPTION_CONTROL_URL); |
| command.add(sessionInfo.getControlUrl()); |
| |
| command.add(LTTngControlServiceConstants.OPTION_DATA_URL); |
| command.add(sessionInfo.getDataUrl()); |
| } |
| return command; |
| } |
| |
| @Override |
| public void destroySession(String sessionName, IProgressMonitor monitor) throws ExecutionException { |
| |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_DESTROY_SESSION, sessionName); |
| |
| ICommandResult result = executeCommand(command, monitor, false); |
| boolean isError = isError(result); |
| if (isError && !ignoredPattern(result.getErrorOutput(), LTTngControlServiceConstants.SESSION_NOT_FOUND_ERROR_PATTERN)) { |
| throw new ExecutionException(Messages.TraceControl_CommandError + " " + command.toString() + "\n" + result.toString()); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| // Session <sessionName> destroyed |
| } |
| |
| @Override |
| public void startSession(String sessionName, IProgressMonitor monitor) throws ExecutionException { |
| |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_START_SESSION, sessionName); |
| |
| executeCommand(command, monitor); |
| |
| // Session <sessionName> started |
| } |
| |
| @Override |
| public void stopSession(String sessionName, IProgressMonitor monitor) throws ExecutionException { |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_STOP_SESSION, sessionName); |
| |
| executeCommand(command, monitor); |
| |
| // Session <sessionName> stopped |
| |
| } |
| |
| @Override |
| public void enableChannels(String sessionName, List<String> channelNames, TraceDomainType domain, IChannelInfo info, IProgressMonitor monitor) throws ExecutionException { |
| |
| // no channels to enable |
| if (channelNames.isEmpty()) { |
| return; |
| } |
| |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_ENABLE_CHANNEL); |
| |
| command.add(toCsv(channelNames)); |
| |
| command.add(getDomainOption(domain)); |
| |
| command.add(LTTngControlServiceConstants.OPTION_SESSION); |
| command.add(sessionName); |
| |
| if (info != null) { |
| // --discard Discard event when buffers are full (default) |
| |
| // --overwrite Flight recorder mode |
| if (info.isOverwriteMode()) { |
| command.add(LTTngControlServiceConstants.OPTION_OVERWRITE); |
| } |
| // --subbuf-size SIZE Subbuffer size in bytes |
| // (default: 4096, kernel default: 262144) |
| if (info.getSubBufferSize() != LTTngControlServiceConstants.UNUSED_VALUE) { |
| command.add(LTTngControlServiceConstants.OPTION_SUB_BUFFER_SIZE); |
| command.add(String.valueOf(info.getSubBufferSize())); |
| } |
| |
| // --num-subbuf NUM Number of subbufers |
| if (info.getNumberOfSubBuffers() != LTTngControlServiceConstants.UNUSED_VALUE) { |
| command.add(LTTngControlServiceConstants.OPTION_NUM_SUB_BUFFERS); |
| command.add(String.valueOf(info.getNumberOfSubBuffers())); |
| } |
| |
| // --switch-timer USEC Switch timer interval in usec |
| if (info.getSwitchTimer() != LTTngControlServiceConstants.UNUSED_VALUE) { |
| command.add(LTTngControlServiceConstants.OPTION_SWITCH_TIMER); |
| command.add(String.valueOf(info.getSwitchTimer())); |
| } |
| |
| // --read-timer USEC Read timer interval in usec |
| if (info.getReadTimer() != LTTngControlServiceConstants.UNUSED_VALUE) { |
| command.add(LTTngControlServiceConstants.OPTION_READ_TIMER); |
| command.add(String.valueOf(info.getReadTimer())); |
| } |
| |
| if (isVersionSupported("2.2.0")) { //$NON-NLS-1$ |
| // --buffers-uid Every application sharing the same UID use the |
| // same buffers --buffers-pid Buffers are allocated per PID |
| if (domain.equals(TraceDomainType.UST)) { |
| if (info.getBufferType() == BufferType.BUFFER_PER_PID) { |
| command.add(LTTngControlServiceConstants.OPTION_PER_PID_BUFFERS); |
| |
| } else if (info.getBufferType() == BufferType.BUFFER_PER_UID) { |
| command.add(LTTngControlServiceConstants.OPTION_PER_UID_BUFFERS); |
| } |
| } |
| |
| // -C SIZE Maximum size of trace files in bytes |
| if (info.getMaxSizeTraceFiles() != LTTngControlServiceConstants.UNUSED_VALUE) { |
| command.add(LTTngControlServiceConstants.OPTION_MAX_SIZE_TRACE_FILES); |
| command.add(String.valueOf(info.getMaxSizeTraceFiles())); |
| } |
| |
| // -W NUM Maximum number of trace files |
| if (info.getMaxNumberTraceFiles() != LTTngControlServiceConstants.UNUSED_VALUE) { |
| command.add(LTTngControlServiceConstants.OPTION_MAX_TRACE_FILES); |
| command.add(String.valueOf(info.getMaxNumberTraceFiles())); |
| } |
| } |
| } |
| |
| executeCommand(command, monitor); |
| |
| } |
| |
| @Override |
| public void disableChannels(String sessionName, List<String> channelNames, TraceDomainType domain, IProgressMonitor monitor) throws ExecutionException { |
| |
| // no channels to enable |
| if (channelNames.isEmpty()) { |
| return; |
| } |
| |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_DISABLE_CHANNEL); |
| |
| command.add(toCsv(channelNames)); |
| |
| command.add(getDomainOption(domain)); |
| |
| command.add(LTTngControlServiceConstants.OPTION_SESSION); |
| command.add(sessionName); |
| |
| executeCommand(command, monitor); |
| } |
| |
| @Override |
| public void enableEvents(String sessionName, String channelName, List<String> eventNames, TraceDomainType domain, String filterExpression, List<String> excludedEvents, IProgressMonitor monitor) throws ExecutionException { |
| |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_ENABLE_EVENT); |
| boolean isAllEvents = ALL_EVENTS.equals(eventNames); |
| |
| if (isAllEvents || (eventNames == null) || (eventNames.isEmpty())) { |
| command.add(LTTngControlServiceConstants.OPTION_ALL); |
| } else { |
| command.add(toCsv(eventNames)); |
| } |
| |
| command.add(getDomainOption(domain)); |
| |
| command.add(LTTngControlServiceConstants.OPTION_SESSION); |
| command.add(sessionName); |
| |
| if (channelName != null) { |
| command.add(LTTngControlServiceConstants.OPTION_CHANNEL); |
| command.add(channelName); |
| } |
| |
| if (!isAllEvents) { |
| command.add(LTTngControlServiceConstants.OPTION_TRACEPOINT); |
| } |
| |
| if (filterExpression != null) { |
| command.add(LTTngControlServiceConstants.OPTION_FILTER); |
| command.add(filterExpression); |
| } |
| |
| if (excludedEvents != null && !excludedEvents.isEmpty()) { |
| command.add(LTTngControlServiceConstants.OPTION_EXCLUDE); |
| command.add(toCsv(excludedEvents)); |
| } |
| |
| executeCommand(command, monitor); |
| } |
| |
| @Override |
| public void enableSyscalls(String sessionName, String channelName, List<String> syscallNames, IProgressMonitor monitor) throws ExecutionException { |
| |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_ENABLE_EVENT); |
| |
| boolean isAllSyscalls = ALL_EVENTS.equals(syscallNames); |
| |
| if (isAllSyscalls || (syscallNames == null) || (syscallNames.isEmpty())) { |
| command.add(LTTngControlServiceConstants.OPTION_ALL); |
| } else { |
| command.add(toCsv(syscallNames)); |
| } |
| |
| command.add(LTTngControlServiceConstants.OPTION_KERNEL); |
| |
| command.add(LTTngControlServiceConstants.OPTION_SESSION); |
| command.add(sessionName); |
| |
| if (channelName != null) { |
| command.add(LTTngControlServiceConstants.OPTION_CHANNEL); |
| command.add(channelName); |
| } |
| |
| command.add(LTTngControlServiceConstants.OPTION_SYSCALL); |
| |
| executeCommand(command, monitor); |
| } |
| |
| @Override |
| public void enableProbe(String sessionName, String channelName, String eventName, boolean isFunction, String probe, IProgressMonitor monitor) throws ExecutionException { |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_ENABLE_EVENT); |
| |
| command.add(eventName); |
| command.add(LTTngControlServiceConstants.OPTION_KERNEL); |
| |
| command.add(LTTngControlServiceConstants.OPTION_SESSION); |
| command.add(sessionName); |
| |
| if (channelName != null) { |
| command.add(LTTngControlServiceConstants.OPTION_CHANNEL); |
| command.add(channelName); |
| } |
| if (isFunction) { |
| command.add(LTTngControlServiceConstants.OPTION_FUNCTION_PROBE); |
| } else { |
| command.add(LTTngControlServiceConstants.OPTION_PROBE); |
| } |
| |
| command.add(probe); |
| |
| executeCommand(command, monitor); |
| } |
| |
| @Override |
| public void enableLogLevel(String sessionName, String channelName, List<String> eventNames, LogLevelType logLevelType, ITraceLogLevel level, String filterExpression, TraceDomainType domain, IProgressMonitor monitor) throws ExecutionException { |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_ENABLE_EVENT); |
| |
| // Checking if we should enable all events (with option '-a') |
| boolean isAllEvents = ALL_EVENTS.equals(eventNames); |
| |
| if (isAllEvents || (eventNames == null) || (eventNames.isEmpty())) { |
| command.add(LTTngControlServiceConstants.OPTION_ALL); |
| } else { |
| command.add(toCsv(eventNames)); |
| } |
| |
| command.add(getDomainOption(domain)); |
| |
| command.add(LTTngControlServiceConstants.OPTION_SESSION); |
| command.add(sessionName); |
| |
| if (channelName != null) { |
| command.add(LTTngControlServiceConstants.OPTION_CHANNEL); |
| command.add(channelName); |
| } |
| |
| if (logLevelType == LogLevelType.LOGLEVEL) { |
| command.add(LTTngControlServiceConstants.OPTION_LOGLEVEL); |
| } else if (logLevelType == LogLevelType.LOGLEVEL_ONLY) { |
| command.add(LTTngControlServiceConstants.OPTION_LOGLEVEL_ONLY); |
| } else { |
| return; |
| } |
| command.add(level.getInName()); |
| executeCommand(command, monitor); |
| } |
| |
| @Override |
| public void disableEvent(String sessionName, String channelName, List<String> eventNames, TraceDomainType domain, IProgressMonitor monitor) throws ExecutionException { |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_DISABLE_EVENT); |
| |
| if (eventNames == null) { |
| command.add(LTTngControlServiceConstants.OPTION_ALL); |
| } else { |
| // no events to disable |
| if (eventNames.isEmpty()) { |
| return; |
| } |
| |
| StringBuffer eventNameParameter = new StringBuffer(); |
| for (Iterator<String> iterator = eventNames.iterator(); iterator.hasNext();) { |
| String event = iterator.next(); |
| eventNameParameter.append(event); |
| if (iterator.hasNext()) { |
| eventNameParameter.append(','); |
| } |
| } |
| command.add(eventNameParameter.toString()); |
| } |
| |
| command.add(getDomainOption(domain)); |
| |
| command.add(LTTngControlServiceConstants.OPTION_SESSION); |
| command.add(sessionName); |
| |
| if (channelName != null) { |
| command.add(LTTngControlServiceConstants.OPTION_CHANNEL); |
| command.add(channelName); |
| } |
| |
| executeCommand(command, monitor); |
| } |
| |
| @Override |
| public List<String> getContextList(IProgressMonitor monitor) throws ExecutionException { |
| |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_ADD_CONTEXT, LTTngControlServiceConstants.OPTION_HELP); |
| |
| ICommandResult result = executeCommand(command, monitor); |
| |
| List<String> output = result.getOutput(); |
| |
| List<String> contexts = new ArrayList<>(0); |
| |
| int index = 0; |
| boolean inList = false; |
| while (index < output.size()) { |
| String line = output.get(index); |
| |
| Matcher startMatcher = LTTngControlServiceConstants.ADD_CONTEXT_HELP_CONTEXTS_INTRO.matcher(line); |
| Matcher endMatcher = LTTngControlServiceConstants.ADD_CONTEXT_HELP_CONTEXTS_END_LINE.matcher(line); |
| |
| if (startMatcher.matches()) { |
| inList = true; |
| } else if (endMatcher.matches()) { |
| break; |
| } else if (inList) { |
| String[] tmp = line.split(","); //$NON-NLS-1$ |
| for (int i = 0; i < tmp.length; i++) { |
| contexts.add(tmp[i].trim()); |
| } |
| } |
| index++; |
| } |
| return contexts; |
| } |
| |
| @Override |
| public void addContexts(String sessionName, String channelName, String eventName, TraceDomainType domain, List<String> contextNames, IProgressMonitor monitor) throws ExecutionException { |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_ADD_CONTEXT); |
| |
| command.add(LTTngControlServiceConstants.OPTION_SESSION); |
| command.add(sessionName); |
| |
| if (channelName != null) { |
| command.add(LTTngControlServiceConstants.OPTION_CHANNEL); |
| command.add(channelName); |
| } |
| |
| if (eventName != null) { |
| command.add(LTTngControlServiceConstants.OPTION_EVENT); |
| command.add(eventName); |
| } |
| |
| command.add(getDomainOption(domain)); |
| |
| for (Iterator<String> iterator = contextNames.iterator(); iterator.hasNext();) { |
| String context = iterator.next(); |
| command.add(LTTngControlServiceConstants.OPTION_CONTEXT_TYPE); |
| command.add(context); |
| } |
| |
| executeCommand(command, monitor); |
| |
| } |
| |
| @Override |
| public void recordSnapshot(String sessionName, IProgressMonitor monitor) |
| throws ExecutionException { |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_SNAPSHOT, LTTngControlServiceConstants.COMMAND_RECORD_SNAPSHOT); |
| |
| String newSessionName = sessionName; |
| command.add(LTTngControlServiceConstants.OPTION_SESSION); |
| command.add(newSessionName); |
| |
| executeCommand(command, monitor); |
| } |
| |
| @Override |
| public void loadSession(String inputPath, boolean isForce, IProgressMonitor monitor) |
| throws ExecutionException { |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_LOAD_SESSION); |
| |
| if (inputPath != null) { |
| command.add(LTTngControlServiceConstants.OPTION_INPUT_PATH); |
| command.add(inputPath); |
| } |
| |
| if (isForce) { |
| command.add(LTTngControlServiceConstants.OPTION_FORCE); |
| } |
| executeCommand(command, monitor); |
| } |
| |
| @Override |
| public void saveSession(String session, String outputPath, boolean isForce, IProgressMonitor monitor) throws ExecutionException { |
| ICommandInput command = createCommand(LTTngControlServiceConstants.COMMAND_SAVE_SESSION); |
| |
| if (outputPath != null) { |
| command.add(LTTngControlServiceConstants.OPTION_OUTPUT_PATH); |
| command.add(outputPath); |
| } |
| |
| if (isForce) { |
| command.add(LTTngControlServiceConstants.OPTION_FORCE); |
| } |
| |
| if (session != null) { |
| command.add(session); |
| } |
| executeCommand(command, monitor); |
| } |
| |
| @Override |
| public void runCommands(IProgressMonitor monitor, List<String> commandLines) throws ExecutionException { |
| for (String commandLine : commandLines) { |
| if (monitor.isCanceled()) { |
| return; |
| } |
| |
| if (commandLine.isEmpty() || commandLine.startsWith("#")) { //$NON-NLS-1$ |
| continue; |
| } |
| String[] args = commandLine.split("\\s+"); //$NON-NLS-1$ |
| ICommandInput command = fCommandShell.createCommand(); |
| command.addAll(Arrays.asList(args)); |
| ICommandResult result = executeCommand(command, monitor); |
| |
| if (isError(result)) { |
| throw new ExecutionException(Messages.TraceControl_CommandError + " " + command.toString() + "\n" + result.toString()); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| // Helper methods |
| // ------------------------------------------------------------------------ |
| |
| private static @NonNull String getDomainOption(TraceDomainType domain) { |
| switch (domain) { |
| case KERNEL: |
| return LTTngControlServiceConstants.OPTION_KERNEL; |
| case UST: |
| return LTTngControlServiceConstants.OPTION_UST; |
| case JUL: |
| return LTTngControlServiceConstants.OPTION_JUL; |
| case LOG4J: |
| return LTTngControlServiceConstants.OPTION_LOG4J; |
| case PYTHON: |
| return LTTngControlServiceConstants.OPTION_PYTHON; |
| case UNKNOWN: |
| default: |
| return TraceDomainType.UNKNOWN.name(); |
| } |
| } |
| |
| /** |
| * Checks if command result is an error result. |
| * |
| * @param result |
| * - the command result to check |
| * @return true if error else false |
| */ |
| protected boolean isError(ICommandResult result) { |
| // Check return code and length of returned strings |
| |
| if ((result.getResult()) != 0) { |
| return true; |
| } |
| |
| // Look for error pattern |
| for (String line : result.getErrorOutput()) { |
| Matcher matcher = LTTngControlServiceConstants.ERROR_PATTERN.matcher(line); |
| if (matcher.matches()) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Creates a comma separated string from list of names |
| * |
| * @param names |
| * List of name to convert |
| * @return comma separated string |
| */ |
| protected String toCsv(List<String> names) { |
| StringBuilder csvString = new StringBuilder(); |
| for (Iterator<String> iterator = names.iterator(); iterator.hasNext();) { |
| String name = iterator.next(); |
| csvString.append(name); |
| if (iterator.hasNext()) { |
| csvString.append(','); |
| } |
| } |
| return csvString.toString(); |
| } |
| |
| /** |
| * Parses the domain information. |
| * |
| * @param output |
| * a command output list |
| * @param currentIndex |
| * current index in command output list |
| * @param channels |
| * list for returning channel information |
| * @param domainInfo |
| * The domain information |
| * @return the new current index in command output list |
| */ |
| protected int parseDomain(List<String> output, int currentIndex, List<IChannelInfo> channels, IDomainInfo domainInfo) { |
| int index = currentIndex; |
| |
| // if kernel set the buffer type to shared |
| if (domainInfo.getDomain().equals(TraceDomainType.KERNEL)) { |
| domainInfo.setBufferType(BufferType.BUFFER_SHARED); |
| } |
| |
| // Channels: |
| // ------------- |
| // - channnel1: [enabled] |
| // |
| // Attributes: |
| // overwrite mode: 0 |
| // subbufers size: 262144 |
| // number of subbufers: 4 |
| // switch timer interval: 0 |
| // read timer interval: 200 |
| // output: splice() |
| |
| while (index < output.size()) { |
| String line = output.get(index); |
| |
| if (isVersionSupported("2.2.0")) { //$NON-NLS-1$ |
| Matcher bufferTypeMatcher = LTTngControlServiceConstants.BUFFER_TYPE_PATTERN.matcher(line); |
| if (bufferTypeMatcher.matches()) { |
| String bufferTypeString = getAttributeValue(line); |
| if (BufferType.BUFFER_PER_PID.getInName().equals(bufferTypeString)) { |
| domainInfo.setBufferType(BufferType.BUFFER_PER_PID); |
| } else if (BufferType.BUFFER_PER_UID.getInName().equals(bufferTypeString)) { |
| domainInfo.setBufferType(BufferType.BUFFER_PER_UID); |
| } else { |
| domainInfo.setBufferType(BufferType.BUFFER_TYPE_UNKNOWN); |
| } |
| } |
| } else { |
| domainInfo.setBufferType(BufferType.BUFFER_TYPE_UNKNOWN); |
| } |
| Matcher outerMatcher = LTTngControlServiceConstants.CHANNELS_SECTION_PATTERN.matcher(line); |
| Matcher noKernelChannelMatcher = LTTngControlServiceConstants.DOMAIN_NO_KERNEL_CHANNEL_PATTERN.matcher(line); |
| Matcher noUstChannelMatcher = LTTngControlServiceConstants.DOMAIN_NO_UST_CHANNEL_PATTERN.matcher(line); |
| if (outerMatcher.matches()) { |
| IChannelInfo channelInfo = null; |
| while (index < output.size()) { |
| String subLine = output.get(index); |
| |
| Matcher innerMatcher = LTTngControlServiceConstants.CHANNEL_PATTERN.matcher(subLine); |
| if (innerMatcher.matches()) { |
| channelInfo = new ChannelInfo(""); //$NON-NLS-1$ |
| // get channel name |
| channelInfo.setName(innerMatcher.group(1)); |
| |
| // get channel enablement |
| channelInfo.setState(innerMatcher.group(2)); |
| |
| // set BufferType |
| channelInfo.setBufferType(domainInfo.getBufferType()); |
| |
| // add channel |
| channels.add(channelInfo); |
| |
| } else if (LTTngControlServiceConstants.OVERWRITE_MODE_ATTRIBUTE.matcher(subLine).matches()) { |
| String value = getAttributeValue(subLine); |
| if (channelInfo != null) { |
| channelInfo.setOverwriteMode(!LTTngControlServiceConstants.OVERWRITE_MODE_ATTRIBUTE_FALSE.equals(value)); |
| } |
| } else if (LTTngControlServiceConstants.SUBBUFFER_SIZE_ATTRIBUTE.matcher(subLine).matches()) { |
| if (channelInfo != null) { |
| channelInfo.setSubBufferSize(Long.valueOf(getAttributeValue(subLine))); |
| } |
| |
| } else if (LTTngControlServiceConstants.NUM_SUBBUFFERS_ATTRIBUTE.matcher(subLine).matches()) { |
| if (channelInfo != null) { |
| channelInfo.setNumberOfSubBuffers(Integer.valueOf(getAttributeValue(subLine))); |
| } |
| |
| } else if (LTTngControlServiceConstants.SWITCH_TIMER_ATTRIBUTE.matcher(subLine).matches()) { |
| if (channelInfo != null) { |
| channelInfo.setSwitchTimer(Long.valueOf(getAttributeValue(subLine))); |
| } |
| |
| } else if (LTTngControlServiceConstants.READ_TIMER_ATTRIBUTE.matcher(subLine).matches()) { |
| if (channelInfo != null) { |
| channelInfo.setReadTimer(Long.valueOf(getAttributeValue(subLine))); |
| } |
| |
| } else if (LTTngControlServiceConstants.OUTPUT_ATTRIBUTE.matcher(subLine).matches()) { |
| if (channelInfo != null) { |
| channelInfo.setOutputType(getAttributeValue(subLine)); |
| } |
| |
| } else if (LTTngControlServiceConstants.TRACE_FILE_COUNT_ATTRIBUTE.matcher(subLine).matches()) { |
| if (channelInfo != null) { |
| channelInfo.setMaxNumberTraceFiles(Integer.valueOf(getAttributeValue(subLine))); |
| } |
| |
| } else if (LTTngControlServiceConstants.TRACE_FILE_SIZE_ATTRIBUTE.matcher(subLine).matches()) { |
| if (channelInfo != null) { |
| channelInfo.setMaxSizeTraceFiles(Long.valueOf(getAttributeValue(subLine))); |
| } |
| } else if (LTTngControlServiceConstants.EVENT_SECTION_PATTERN.matcher(subLine).matches()) { |
| List<IEventInfo> events = new ArrayList<>(); |
| index = parseEvents(output, index, events); |
| if (channelInfo != null) { |
| channelInfo.setEvents(events); |
| } |
| // we want to stay at the current index to be able to |
| // exit the domain |
| continue; |
| } else if (LTTngControlServiceConstants.DOMAIN_KERNEL_PATTERN.matcher(subLine).matches()) { |
| return index; |
| |
| } else if (LTTngControlServiceConstants.DOMAIN_UST_GLOBAL_PATTERN.matcher(subLine).matches()) { |
| return index; |
| } |
| index++; |
| } |
| } else if (noKernelChannelMatcher.matches() || noUstChannelMatcher.matches()) { |
| // domain indicates that no channels were found -> return |
| index++; |
| return index; |
| } |
| index++; |
| } |
| return index; |
| } |
| |
| /** |
| * Parses the event information within a domain. |
| * |
| * @param output |
| * a command output list |
| * @param currentIndex |
| * current index in command output list |
| * @param events |
| * list for returning event information |
| * @return the new current index in command output list |
| */ |
| protected int parseEvents(List<String> output, int currentIndex, List<IEventInfo> events) { |
| int index = currentIndex; |
| |
| while (index < output.size()) { |
| String line = output.get(index); |
| if (LTTngControlServiceConstants.CHANNEL_PATTERN.matcher(line).matches()) { |
| // end of channel |
| return index; |
| } else if (LTTngControlServiceConstants.DOMAIN_KERNEL_PATTERN.matcher(line).matches()) { |
| // end of domain |
| return index; |
| } else if (LTTngControlServiceConstants.DOMAIN_UST_GLOBAL_PATTERN.matcher(line).matches()) { |
| // end of domain |
| return index; |
| } |
| |
| Matcher matcher = LTTngControlServiceConstants.EVENT_PATTERN.matcher(line); |
| Matcher matcher2 = LTTngControlServiceConstants.WILDCARD_EVENT_PATTERN.matcher(line); |
| |
| if (matcher.matches()) { |
| IEventInfo eventInfo = new EventInfo(matcher.group(1).trim()); |
| eventInfo.setLogLevelType(matcher.group(2).trim()); |
| eventInfo.setLogLevel(matcher.group(3).trim()); |
| eventInfo.setEventType(matcher.group(4).trim()); |
| eventInfo.setState(matcher.group(5)); |
| if (("[" + LTTngControlServiceConstants.HAS_EXCLUSIONS + "]").equals(matcher.group(6))) { //$NON-NLS-1$ //$NON-NLS-2$ |
| eventInfo.setExcludedEvents(LTTngControlServiceConstants.HAS_EXCLUSIONS); |
| } |
| if (("[" + LTTngControlServiceConstants.WITH_FILTER + "]").equals(matcher.group(7))) { //$NON-NLS-1$ //$NON-NLS-2$ |
| eventInfo.setFilterExpression(LTTngControlServiceConstants.WITH_FILTER); |
| } |
| events.add(eventInfo); |
| index++; |
| } else if (matcher2.matches()) { |
| IEventInfo eventInfo = new EventInfo(matcher2.group(1).trim()); |
| eventInfo.setLogLevel(TraceLogLevel.LEVEL_UNKNOWN); |
| eventInfo.setEventType(matcher2.group(2).trim()); |
| eventInfo.setState(matcher2.group(3)); |
| if (("[" + LTTngControlServiceConstants.HAS_EXCLUSIONS + "]").equals(matcher2.group(4))) { //$NON-NLS-1$ //$NON-NLS-2$ |
| eventInfo.setExcludedEvents(LTTngControlServiceConstants.HAS_EXCLUSIONS); |
| } |
| if (("[" + LTTngControlServiceConstants.WITH_FILTER + "]").equals(matcher2.group(5))) { //$NON-NLS-1$ //$NON-NLS-2$ |
| eventInfo.setFilterExpression(LTTngControlServiceConstants.WITH_FILTER); |
| } |
| |
| if ((eventInfo.getEventType() == TraceEventType.PROBE) || |
| (eventInfo.getEventType() == TraceEventType.FUNCTION)) { |
| IProbeEventInfo probeEvent = new ProbeEventInfo(eventInfo.getName()); |
| probeEvent.setLogLevel(eventInfo.getLogLevel()); |
| probeEvent.setEventType(eventInfo.getEventType()); |
| probeEvent.setState(eventInfo.getState()); |
| |
| // Overwrite eventinfo |
| eventInfo = probeEvent; |
| |
| // myevent2 (type: probe) [enabled] |
| // addr: 0xc0101340 |
| // myevent0 (type: function) [enabled] |
| // offset: 0x0 |
| // symbol: init_post |
| index++; |
| while (index < output.size()) { |
| String probeLine = output.get(index); |
| // parse probe |
| Matcher addrMatcher = LTTngControlServiceConstants.PROBE_ADDRESS_PATTERN.matcher(probeLine); |
| Matcher offsetMatcher = LTTngControlServiceConstants.PROBE_OFFSET_PATTERN.matcher(probeLine); |
| Matcher symbolMatcher = LTTngControlServiceConstants.PROBE_SYMBOL_PATTERN.matcher(probeLine); |
| if (addrMatcher.matches()) { |
| String addr = addrMatcher.group(2).trim(); |
| probeEvent.setAddress(addr); |
| } else if (offsetMatcher.matches()) { |
| String offset = offsetMatcher.group(2).trim(); |
| probeEvent.setOffset(offset); |
| } else if (symbolMatcher.matches()) { |
| String symbol = symbolMatcher.group(2).trim(); |
| probeEvent.setSymbol(symbol); |
| } else if ((LTTngControlServiceConstants.EVENT_PATTERN.matcher(probeLine).matches()) || (LTTngControlServiceConstants.WILDCARD_EVENT_PATTERN.matcher(probeLine).matches())) { |
| break; |
| } else if (LTTngControlServiceConstants.CHANNEL_PATTERN.matcher(probeLine).matches()) { |
| break; |
| } else if (LTTngControlServiceConstants.DOMAIN_KERNEL_PATTERN.matcher(probeLine).matches()) { |
| // end of domain |
| break; |
| } else if (LTTngControlServiceConstants.DOMAIN_UST_GLOBAL_PATTERN.matcher(probeLine).matches()) { |
| // end of domain |
| break; |
| } |
| index++; |
| } |
| events.add(eventInfo); |
| } else { |
| events.add(eventInfo); |
| index++; |
| continue; |
| } |
| } else { |
| index++; |
| } |
| } |
| |
| return index; |
| } |
| |
| /** |
| * Parses a line with attributes: <attribute Name>: <attribute value> |
| * |
| * @param line |
| * - attribute line to parse |
| * @return the attribute value as string |
| */ |
| protected String getAttributeValue(String line) { |
| String[] temp = line.split("\\: "); //$NON-NLS-1$ |
| return temp[1]; |
| } |
| |
| /** |
| * Parses the event information within a provider. |
| * |
| * @param output |
| * a command output list |
| * @param currentIndex |
| * current index in command output list |
| * @param events |
| * list for returning event information |
| * @return the new current index in command output list |
| */ |
| protected int getProviderEventInfo(List<String> output, int currentIndex, List<IBaseEventInfo> events) { |
| int index = currentIndex; |
| IBaseEventInfo eventInfo = null; |
| while (index < output.size()) { |
| String line = output.get(index); |
| Matcher matcher = LTTngControlServiceConstants.PROVIDER_EVENT_PATTERN.matcher(line); |
| if (matcher.matches()) { |
| // sched_kthread_stop (loglevel: TRACE_EMERG0) (type: |
| // tracepoint) |
| eventInfo = new BaseEventInfo(matcher.group(1).trim()); |
| eventInfo.setLogLevel(matcher.group(2).trim()); |
| eventInfo.setEventType(matcher.group(3).trim()); |
| events.add(eventInfo); |
| index++; |
| } else if (LTTngControlServiceConstants.EVENT_FIELD_PATTERN.matcher(line).matches()) { |
| if (eventInfo != null) { |
| List<IFieldInfo> fields = new ArrayList<>(); |
| index = getFieldInfo(output, index, fields); |
| eventInfo.setFields(fields); |
| } else { |
| index++; |
| } |
| } else if (LTTngControlServiceConstants.UST_PROVIDER_PATTERN.matcher(line).matches()) { |
| return index; |
| } else { |
| index++; |
| } |
| } |
| return index; |
| } |
| |
| /** |
| * Parse a field's information. |
| * |
| * @param output |
| * A command output list |
| * @param currentIndex |
| * The current index in the command output list |
| * @param fields |
| * List for returning the field information |
| * @return The new current index in the command output list |
| */ |
| protected int getFieldInfo(List<String> output, int currentIndex, List<IFieldInfo> fields) { |
| int index = currentIndex; |
| IFieldInfo fieldInfo = null; |
| while (index < output.size()) { |
| String line = output.get(index); |
| Matcher matcher = LTTngControlServiceConstants.EVENT_FIELD_PATTERN.matcher(line); |
| if (matcher.matches()) { |
| // field: content (string) |
| fieldInfo = new FieldInfo(matcher.group(2).trim()); |
| fieldInfo.setFieldType(matcher.group(3).trim()); |
| fields.add(fieldInfo); |
| } else if (LTTngControlServiceConstants.PROVIDER_EVENT_PATTERN.matcher(line).matches()) { |
| return index; |
| } else if (LTTngControlServiceConstants.UST_PROVIDER_PATTERN.matcher(line).matches()) { |
| return index; |
| } |
| index++; |
| } |
| return index; |
| } |
| |
| /** |
| * Creates a command input instance |
| * |
| * @param segments |
| * array of string that makes up a command line |
| * @return {@link ICommandInput} instance |
| */ |
| protected @NonNull ICommandInput createCommand(String... segments) { |
| ICommandInput command = fCommandShell.createCommand(); |
| command.add(LTTngControlServiceConstants.CONTROL_COMMAND); |
| List<@NonNull String> groupOption = getTracingGroupOption(); |
| if (!groupOption.isEmpty()) { |
| command.addAll(groupOption); |
| } |
| String verboseOption = getVerboseOption(); |
| if (!verboseOption.isEmpty()) { |
| command.add(verboseOption); |
| } |
| for (String string : segments) { |
| command.add(checkNotNull(string)); |
| } |
| return command; |
| } |
| |
| /** |
| * @return the tracing group option if configured in the preferences |
| */ |
| protected @NonNull List<@NonNull String> getTracingGroupOption() { |
| List<@NonNull String> groupOption = new ArrayList<>(); |
| if (!ControlPreferences.getInstance().isDefaultTracingGroup() && !ControlPreferences.getInstance().getTracingGroup().equals("")) { //$NON-NLS-1$ |
| groupOption.add(LTTngControlServiceConstants.OPTION_TRACING_GROUP); |
| groupOption.add(ControlPreferences.getInstance().getTracingGroup()); |
| } |
| return groupOption; |
| } |
| |
| /** |
| * @return the verbose option as configured in the preferences |
| */ |
| protected String getVerboseOption() { |
| if (ControlPreferences.getInstance().isLoggingEnabled()) { |
| String level = ControlPreferences.getInstance().getVerboseLevel(); |
| if (ControlPreferences.TRACE_CONTROL_VERBOSE_LEVEL_VERBOSE.equals(level)) { |
| return LTTngControlServiceConstants.OPTION_VERBOSE; |
| } |
| if (ControlPreferences.TRACE_CONTROL_VERBOSE_LEVEL_V_VERBOSE.equals(level)) { |
| return LTTngControlServiceConstants.OPTION_VERY_VERBOSE; |
| } |
| if (ControlPreferences.TRACE_CONTROL_VERBOSE_LEVEL_V_V_VERBOSE.equals(level)) { |
| return LTTngControlServiceConstants.OPTION_VERY_VERY_VERBOSE; |
| } |
| } |
| return ""; //$NON-NLS-1$ |
| } |
| |
| /** |
| * Method that logs the command and command result if logging is enabled as |
| * well as forwards the command execution to the shell. |
| * |
| * @param command |
| * - the command to execute |
| * @param monitor |
| * - a progress monitor |
| * @return the command result |
| * @throws ExecutionException |
| * If the command fails |
| */ |
| protected ICommandResult executeCommand(@NonNull ICommandInput command, |
| @Nullable IProgressMonitor monitor) throws ExecutionException { |
| return executeCommand(command, monitor, true); |
| } |
| |
| /** |
| * Method that logs the command and command result if logging is enabled as |
| * well as forwards the command execution to the shell. |
| * |
| * @param command |
| * - the command to execute |
| * @param monitor |
| * - a progress monitor |
| * @param checkForError |
| * - true to verify command result, else false |
| * @return the command result |
| * @throws ExecutionException |
| * in case of error result |
| */ |
| protected ICommandResult executeCommand(@NonNull ICommandInput command, |
| @Nullable IProgressMonitor monitor, boolean checkForError) |
| throws ExecutionException { |
| if (ControlPreferences.getInstance().isLoggingEnabled()) { |
| ControlCommandLogger.log(command.toString()); |
| } |
| |
| ICommandResult result = fCommandShell.executeCommand(command, monitor); |
| |
| if (ControlPreferences.getInstance().isLoggingEnabled()) { |
| ControlCommandLogger.log(result.toString()); |
| } |
| |
| if (checkForError && isError(result)) { |
| throw new ExecutionException(Messages.TraceControl_CommandError |
| + " " + command.toString() + "\n" + result.toString()); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| return result; |
| } |
| } |