Decouple the TCP client from the implementation of the LTTng Java agent.
Instead of using AbstractLttngAgent directly, the TCP client (and the
command subclasses) can deal with the new ILttngTcpClientListener
interface. The agent will implement this interface.
This will also allow easier testing of the TCP client and its protocol,
since test classess can now implement their own listener and verify the
contents of each command.
Signed-off-by: Alexandre Montplaisir <alexmonthy@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
$(pkgpath)/ILttngAgent.java \
$(pkgpath)/ILttngHandler.java \
$(pkgpath)/LTTngAgent.java \
- $(pkgpath)/client/LttngAgentResponse.java \
+ $(pkgpath)/client/ILttngTcpClientListener.java \
$(pkgpath)/client/ISessiondCommand.java \
+ $(pkgpath)/client/LttngAgentResponse.java \
$(pkgpath)/client/LttngTcpSessiondClient.java \
$(pkgpath)/client/SessiondCommandHeader.java \
$(pkgpath)/client/SessiondDisableEventCommand.java \
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.atomic.AtomicInteger;
+import org.lttng.ust.agent.client.ILttngTcpClientListener;
import org.lttng.ust.agent.client.LttngTcpSessiondClient;
/**
* @param <T>
* The type of logging handler that should register to this agent
*/
-public abstract class AbstractLttngAgent<T extends ILttngHandler> implements ILttngAgent<T> {
+public abstract class AbstractLttngAgent<T extends ILttngHandler>
+ implements ILttngAgent<T>, ILttngTcpClientListener {
private static final String WILDCARD = "*";
private static final int INIT_TIMEOUT = 3; /* Seconds */
}
String rootClientThreadName = "Root sessiond client started by agent: " + this.getClass().getSimpleName();
- rootSessiondClient = new LttngTcpSessiondClient(this, true);
+ rootSessiondClient = new LttngTcpSessiondClient(this, getDomain().value(), true);
rootSessiondClientThread = new Thread(rootSessiondClient, rootClientThreadName);
rootSessiondClientThread.setDaemon(true);
rootSessiondClientThread.start();
String userClientThreadName = "User sessiond client started by agent: " + this.getClass().getSimpleName();
- userSessiondClient = new LttngTcpSessiondClient(this, false);
+ userSessiondClient = new LttngTcpSessiondClient(this, getDomain().value(), false);
userSessiondClientThread = new Thread(userSessiondClient, userClientThreadName);
userSessiondClientThread.setDaemon(true);
userSessiondClientThread.start();
}
- /**
- * Callback for the TCP clients to notify the agent that a request for
- * enabling an event was sent from the session daemon.
- *
- * @param eventName
- * The name of the event that was requested to be enabled.
- * @return Since we do not track individual sessions, right now this command
- * cannot fail. It will always return true.
- */
+ @Override
public boolean eventEnabled(String eventName) {
if (eventName.equals(WILDCARD)) {
enabledWildcards.incrementAndGet();
return incrementEventCount(eventName, enabledEvents);
}
- /**
- * Callback for the TCP clients to notify the agent that a request for
- * disabling an event was sent from the session daemon.
- *
- * @param eventName
- * The name of the event that was requested to be disabled.
- * @return True if the command completed successfully, false if we should
- * report an error (event was not enabled, etc.)
- */
+ @Override
public boolean eventDisabled(String eventName) {
if (eventName.equals(WILDCARD)) {
int newCount = enabledWildcards.decrementAndGet();
return decrementEventCount(eventName, enabledEvents);
}
+ @Override
+ public Iterable<String> listEnabledEvents() {
+ List<String> events = new LinkedList<String>();
+
+ if (enabledWildcards.get() > 0) {
+ events.add(WILDCARD);
+ }
+ for (String prefix : enabledEventPrefixes.keySet()) {
+ events.add(new String(prefix + WILDCARD));
+ }
+ events.addAll(enabledEvents.keySet());
+ return events;
+ }
+
@Override
public boolean isEventEnabled(String eventName) {
/* If at least one session enabled the "*" wildcard, send the event */
return false;
}
- @Override
- public Iterable<String> listEnabledEvents() {
- List<String> events = new LinkedList<String>();
-
- if (enabledWildcards.get() > 0) {
- events.add(WILDCARD);
- }
- for (String prefix : enabledEventPrefixes.keySet()) {
- events.add(new String(prefix + WILDCARD));
- }
- events.addAll(enabledEvents.keySet());
- return events;
- }
-
private static boolean incrementEventCount(String eventName, Map<String, Integer> eventMap) {
synchronized (eventMap) {
Integer count = eventMap.get(eventName);
/**
* Query if a given event is currently enabled in a current tracing session,
- * meaning it should be sent to UST. May be quicker than listing all events
- * via {@link #listEnabledEvents()}.
+ * meaning it should be sent to UST.
*
* @param eventName
* The name of the event to check.
* @return True if the event is currently enabled, false if it is not.
*/
boolean isEventEnabled(String eventName);
-
- /**
- * List the all events currently enabled in the current tracing sessions.
- *
- * @return The list of enabled events
- */
- Iterable<String> listEnabledEvents();
}
--- /dev/null
+/*
+ * Copyright (C) 2015 - EfficiOS Inc., Alexandre Montplaisir <alexmonthy@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.lttng.ust.agent.client;
+
+/**
+ * TCP client listener interface.
+ *
+ * This interface contains callbacks that are called when the TCP client
+ * receives commands from the session daemon. These callbacks will define what
+ * do to with each command.
+ *
+ * @author Alexandre Montplaisir
+ */
+public interface ILttngTcpClientListener {
+
+ /**
+ * Callback for the TCP client to notify the listener agent that a request
+ * for enabling an event was sent from the session daemon.
+ *
+ * @param eventName
+ * The name of the event that was requested to be enabled.
+ * @return Since we do not track individual sessions, right now this command
+ * cannot fail. It will always return true.
+ */
+ boolean eventEnabled(String eventName);
+
+ /**
+ * Callback for the TCP client to notify the listener agent that a request
+ * for disabling an event was sent from the session daemon.
+ *
+ * @param eventName
+ * The name of the event that was requested to be disabled.
+ * @return True if the command completed successfully, false if we should
+ * report an error (event was not enabled, etc.)
+ */
+ boolean eventDisabled(String eventName);
+
+ /**
+ * List the all events currently enabled in the current tracing sessions.
+ *
+ * @return The list of enabled events
+ */
+ Iterable<String> listEnabledEvents();
+}
package org.lttng.ust.agent.client;
-import org.lttng.ust.agent.AbstractLttngAgent;
-
/**
* Interface to represent all commands sent from the session daemon to the Java
* agent. The agent is then expected to execute the command and provide a
* The agent on which to execute the command
* @return If the command completed successfully or not
*/
- public LttngAgentResponse execute(AbstractLttngAgent<?> agent);
+ public LttngAgentResponse execute(ILttngTcpClientListener agent);
}
\ No newline at end of file
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import org.lttng.ust.agent.AbstractLttngAgent;
-
/**
* Client for agents to connect to a local session daemon, using a TCP socket.
*
private DataInputStream inFromSessiond;
private DataOutputStream outToSessiond;
- private final AbstractLttngAgent<?> logAgent;
+ private final ILttngTcpClientListener logAgent;
+ private final int domainValue;
private final boolean isRoot;
-
/**
* Constructor
*
* @param logAgent
- * The logging agent this client will operate on.
+ * The listener this client will operate on, typically an LTTng
+ * agent.
+ * @param domainValue
+ * The integer to send to the session daemon representing the
+ * tracing domain to handle.
* @param isRoot
* True if this client should connect to the root session daemon,
* false if it should connect to the user one.
*/
- public LttngTcpSessiondClient(AbstractLttngAgent<?> logAgent, boolean isRoot) {
+ public LttngTcpSessiondClient(ILttngTcpClientListener logAgent, int domainValue, boolean isRoot) {
this.logAgent = logAgent;
+ this.domainValue = domainValue;
this.isRoot = isRoot;
}
ByteBuffer buf = ByteBuffer.wrap(data);
String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
- buf.putInt(logAgent.getDomain().value());
+ buf.putInt(domainValue);
buf.putInt(Integer.parseInt(pid));
buf.putInt(protocolMajorVersion);
buf.putInt(protocolMinorVersion);
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-import org.lttng.ust.agent.AbstractLttngAgent;
-
/**
* Session daemon command indicating to the Java agent that some events were
* disabled in the tracing session.
}
@Override
- public LttngAgentResponse execute(AbstractLttngAgent<?> agent) {
+ public LttngAgentResponse execute(ILttngTcpClientListener agent) {
boolean success = agent.eventDisabled(this.eventName);
return (success ? LttngAgentResponse.SUCESS_RESPONSE : DISABLE_EVENT_FAILURE_RESPONSE);
}
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-import org.lttng.ust.agent.AbstractLttngAgent;
-
/**
* Session daemon command indicating to the Java agent that some events were
* enabled in the tracing session.
}
@Override
- public LttngAgentResponse execute(AbstractLttngAgent<?> agent) {
+ public LttngAgentResponse execute(ILttngTcpClientListener agent) {
boolean success = agent.eventEnabled(this.eventName);
return (success ? LttngAgentResponse.SUCESS_RESPONSE : LttngAgentResponse.FAILURE_RESPONSE);
}
import java.util.ArrayList;
import java.util.List;
-import org.lttng.ust.agent.AbstractLttngAgent;
-
/**
* Session daemon command asking the Java agent to list its registered loggers,
* which corresponds to event names in the tracing session.
class SessiondListLoggersCommand implements ISessiondCommand {
@Override
- public LttngAgentResponse execute(AbstractLttngAgent<?> agent) {
+ public LttngAgentResponse execute(ILttngTcpClientListener agent) {
final List<String> loggerList = new ArrayList<String>();
int dataSize = 0;