/********************************************************************** * Copyright (c) 2012, 2015 Ericsson * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which * accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bernd Hufmann - Initial API and implementation * Bernd Hufmann - Updated for support of LTTng Tools 2.1 **********************************************************************/ package org.eclipse.tracecompass.internal.lttng2.control.ui.views.handlers; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.tracecompass.common.core.NonNullUtils; 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.ui.Activator; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.ControlView; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.dialogs.IGetEventInfoDialog; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.dialogs.TraceControlDialogFactory; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.messages.Messages; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.model.ITraceControlComponent; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.model.impl.BaseEventComponent; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.model.impl.KernelProviderComponent; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.model.impl.TargetNodeComponent; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.model.impl.TraceChannelComponent; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.model.impl.TraceSessionComponent; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.model.impl.UstProviderComponent; import org.eclipse.ui.IWorkbenchPage; /** * <p> * Command handler implementation to assign events to a session and channel and enable/configure them. * This is done on the trace provider level. * </p> * * @author Bernd Hufmann */ public class AssignEventHandler extends BaseControlViewHandler { // ------------------------------------------------------------------------ // Attributes // ------------------------------------------------------------------------ /** * The command execution parameter. */ private Parameter fParam; // ------------------------------------------------------------------------ // Operations // ------------------------------------------------------------------------ @Override public Object execute(ExecutionEvent event) throws ExecutionException { // Make a copy for thread safety Parameter tmpParam = null; fLock.lock(); try { tmpParam = fParam; if (tmpParam == null) { return null; } tmpParam = new Parameter(tmpParam); } finally { fLock.unlock(); } final Parameter param = tmpParam; // Open dialog box to retrieve the session and channel where the events should be enabled in. final IGetEventInfoDialog dialog = TraceControlDialogFactory.getInstance().getGetEventInfoDialog(); dialog.setDomain(param.getDomain()); dialog.setSessions(param.getSessions()); if (dialog.open() != Window.OK) { return null; } Job job = new Job(Messages.TraceControl_EnableEventsJob) { @Override protected IStatus run(IProgressMonitor monitor) { Exception error = null; TraceSessionComponent session = dialog.getSession(); try { List<String> eventNames = new ArrayList<>(); List<BaseEventComponent> events = param.getEvents(); // Find the type of the events (all the events in the list are the same type) TraceEventType eventType = !events.isEmpty() ? events.get(0).getEventType() : null; // Create list of event names for (Iterator<BaseEventComponent> iterator = events.iterator(); iterator.hasNext();) { BaseEventComponent baseEvent = iterator.next(); eventNames.add(baseEvent.getName()); } TraceChannelComponent channel = dialog.getChannel(); if (TraceEventType.TRACEPOINT.equals(eventType)) { if (channel == null) { // enable events on default channel (which will be created by lttng-tools) session.enableEvents(eventNames, param.getDomain(), dialog.getFilterExpression(), null, monitor); } else { channel.enableEvents(eventNames, dialog.getFilterExpression(), null, monitor); } } else if (TraceEventType.SYSCALL.equals(eventType)) { if (channel == null) { session.enableSyscalls(eventNames, monitor); } else { channel.enableSyscalls(eventNames, monitor); } } } catch (ExecutionException e) { error = e; } // refresh in all cases if (session != null) { refresh(new CommandParameter(session)); } if (error != null) { return new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.TraceControl_EnableEventsFailure, error); } return Status.OK_STATUS; } }; job.setUser(true); job.schedule(); return null; } @Override public boolean isEnabled() { @NonNull ArrayList<@NonNull BaseEventComponent> events = new ArrayList<>(); @NonNull TraceSessionComponent[] sessions = null; TraceDomainType domain = null; TraceEventType eventType = null; // Get workbench page for the Control View IWorkbenchPage page = getWorkbenchPage(); if (page == null) { return false; } // Check if one or more session are selected ISelection selection = page.getSelection(ControlView.ID); if (selection instanceof StructuredSelection) { StructuredSelection structered = ((StructuredSelection) selection); for (Iterator<?> iterator = structered.iterator(); iterator.hasNext();) { Object element = iterator.next(); if (element instanceof BaseEventComponent) { BaseEventComponent event = (BaseEventComponent) element; ITraceControlComponent provider = event.getParent(); // check for the domain provider TraceDomainType temp = null; if (provider instanceof KernelProviderComponent) { temp = TraceDomainType.KERNEL; } else if (provider instanceof UstProviderComponent) { temp = TraceDomainType.UST; // Loggers are under the UST domain } else { return false; } if (domain == null) { domain = temp; } else { // don't mix events from Kernel and UST provider if (!domain.equals(temp)) { return false; } } // The events have to be the same type if (eventType == null) { eventType = event.getEventType(); } else if (!eventType.equals(event.getEventType())) { events.clear(); break; } // Add BaseEventComponents events.add(event); if (sessions == null) { TargetNodeComponent root = (TargetNodeComponent)event.getParent().getParent().getParent(); sessions = root.getSessions(); } } } } boolean isEnabled = ((!events.isEmpty()) && (sessions != null) && (sessions.length > 0)); // To avoid compiler warnings check for null even if isKernel is always not null when used below if (domain == null) { return false; } fLock.lock(); try { fParam = null; if(isEnabled) { fParam = new Parameter(NonNullUtils.checkNotNull(sessions), events, domain); } } finally { fLock.unlock(); } return isEnabled; } /** * Class containing parameter for the command execution. */ @NonNullByDefault private static final class Parameter { /** * The list of event components the command is to be executed on. */ private final List<BaseEventComponent> fEvents; /** * The list of available sessions. */ private final @NonNull TraceSessionComponent[] fSessions; /** * The domain type ({@link TraceDomainType}) */ private final TraceDomainType fDomain; /** * Constructor * * @param sessions - a array of trace sessions * @param events - a lists of events to enable * @param domain - domain type ({@link TraceDomainType}) */ public Parameter(@NonNull TraceSessionComponent[] sessions, List<BaseEventComponent> events, TraceDomainType domain) { fSessions = NonNullUtils.checkNotNull(Arrays.copyOf(sessions, sessions.length)); fEvents = new ArrayList<>(); fEvents.addAll(events); fDomain = domain; } /** * Copy constructor * @param other - a parameter to copy */ public Parameter(Parameter other) { this(other.fSessions, other.fEvents, other.fDomain); } public TraceSessionComponent[] getSessions() { return fSessions; } public List<BaseEventComponent> getEvents() { return fEvents; } public TraceDomainType getDomain() { return fDomain; } } }