blob: 48bfa713ff70dc1557985277b011ce54e2528a00 [file] [log] [blame]
/**********************************************************************
* 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 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
**********************************************************************/
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;
}
}
}