X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=liblttng-ust-jul%2Forg%2Flttng%2Fust%2Fjul%2FLTTngTCPSessiondClient.java;h=cf3074b0728f21d7d66ef4d046827a913e86feac;hb=8d17995998aa11ffeecbe2cf7701106283544253;hp=aab1d05418b2f0d576248aa39950003b399aed58;hpb=f08bb871203e921da1b0cdce6f9ff88d32a2fb4e;p=lttng-ust.git diff --git a/liblttng-ust-jul/org/lttng/ust/jul/LTTngTCPSessiondClient.java b/liblttng-ust-jul/org/lttng/ust/jul/LTTngTCPSessiondClient.java index aab1d054..cf3074b0 100644 --- a/liblttng-ust-jul/org/lttng/ust/jul/LTTngTCPSessiondClient.java +++ b/liblttng-ust-jul/org/lttng/ust/jul/LTTngTCPSessiondClient.java @@ -23,21 +23,15 @@ import java.nio.ByteOrder; import java.lang.Integer; import java.io.IOException; import java.io.BufferedOutputStream; +import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.DataInputStream; +import java.io.FileReader; +import java.io.FileNotFoundException; import java.net.*; import java.lang.management.ManagementFactory; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.Timer; -import java.util.TimerTask; import java.util.logging.Logger; -import java.util.Collections; class USTRegisterMsg { public static int pid; @@ -49,7 +43,6 @@ public class LTTngTCPSessiondClient { new LTTngSessiondCmd2_4.sessiond_hdr(); private final String sessiondHost; - private final int sessiondPort; private Socket sessiondSock; private boolean quit = false; @@ -60,112 +53,41 @@ public class LTTngTCPSessiondClient { private Semaphore registerSem; - private Timer eventTimer; - private Set enabledEventSet = - Collections.synchronizedSet(new HashSet()); + private static final String rootPortFile = "/var/run/lttng/agent.port"; + private static final String userPortFile = "/.lttng/agent.port"; /* - * Map of Logger objects that have been enabled. They are indexed by name. + * This is taken from the lttng/domain.h file which is mapped to + * LTTNG_DOMAIN_JUL value for this agent. */ - private HashMap enabledLoggers = new HashMap(); - /* Timer delay at each 5 seconds. */ - private final static long timerDelay = 5 * 1000; - private static boolean timerInitialized; + private static final int agent_domain = 3; - public LTTngTCPSessiondClient(String host, int port, Semaphore sem) { + /* Indicate if we've already release the semaphore. */ + private boolean sem_posted = false; + + public LTTngTCPSessiondClient(String host, Semaphore sem) { this.sessiondHost = host; - this.sessiondPort = port; this.registerSem = sem; - this.eventTimer = new Timer(); - this.timerInitialized = false; } - private void setupEventTimer() { - if (this.timerInitialized) { - return; + /* + * Try to release the registerSem if it's not already done. + */ + private void tryReleaseSem() + { + /* Release semaphore so we unblock the agent. */ + if (!this.sem_posted) { + this.registerSem.release(); + this.sem_posted = true; } + } - this.eventTimer.scheduleAtFixedRate(new TimerTask() { - @Override - public void run() { - synchronized (enabledEventSet) { - LTTngSessiondCmd2_4.sessiond_enable_handler enableCmd = new - LTTngSessiondCmd2_4.sessiond_enable_handler(); - /* - * Modifying events in a Set will raise a - * ConcurrentModificationException. Thus, we remove an event - * and add its modified version to modifiedEvents when a - * modification is necessary. - */ - Set modifiedEvents = new HashSet(); - Iterator it = enabledEventSet.iterator(); - - while (it.hasNext()) { - int ret; - Logger logger; - LTTngEvent event = it.next(); - - /* - * Check if this Logger name has been enabled already. Note - * that in the case of "*", it's never added in that hash - * table thus the enable command does a lookup for each - * logger name in that hash table for the * case in order - * to make sure we don't enable twice the same logger - * because JUL apparently accepts that the *same* - * LogHandler can be added twice on a Logger object... - * don't ask... - */ - logger = enabledLoggers.get(event.name); - if (logger != null) { - continue; - } - - /* - * Set to one means that the enable all event has been seen - * thus event from that point on must use loglevel for all - * events. Else the object has its own loglevel. - */ - if (handler.logLevelUseAll == 1) { - it.remove(); - event.logLevel.level = handler.logLevelAll; - event.logLevel.type = handler.logLevelTypeAll; - modifiedEvents.add(event); - } - - /* - * The all event is a special case since we have to iterate - * over every Logger to see which one was not enabled. - */ - if (event.name.equals("*")) { - enableCmd.name = event.name; - enableCmd.lttngLogLevel = event.logLevel.level; - enableCmd.lttngLogLevelType = event.logLevel.type; - /* - * The return value is irrelevant since the * event is - * always kept in the set. - */ - enableCmd.execute(handler, enabledLoggers); - continue; - } - - ret = enableCmd.enableLogger(handler, event, enabledLoggers); - if (ret == 1) { - /* Enabled so remove the event from the set. */ - if (!modifiedEvents.remove(event)) { - /* - * event can only be present in one of - * the sets. - */ - it.remove(); - } - } - } - enabledEventSet.addAll(modifiedEvents); - } - - } - }, this.timerDelay, this.timerDelay); - - this.timerInitialized = true; + /* + * Cleanup Agent state. + */ + private void cleanupState() { + if (this.handler != null) { + this.handler.clear(); + } } public void init(LTTngLogHandler handler) throws InterruptedException { @@ -176,6 +98,9 @@ public class LTTngTCPSessiondClient { break; } + /* Cleanup Agent state before trying to connect or reconnect. */ + cleanupState(); + try { /* @@ -189,8 +114,6 @@ public class LTTngTCPSessiondClient { */ registerToSessiond(); - setupEventTimer(); - /* * Block on socket receive and wait for command from the * session daemon. This will return if and only if there is a @@ -198,13 +121,13 @@ public class LTTngTCPSessiondClient { */ handleSessiondCmd(); } catch (UnknownHostException uhe) { - this.registerSem.release(); + tryReleaseSem(); System.out.println(uhe); } catch (IOException ioe) { - this.registerSem.release(); + tryReleaseSem(); Thread.sleep(3000); } catch (Exception e) { - this.registerSem.release(); + tryReleaseSem(); e.printStackTrace(); } } @@ -212,7 +135,6 @@ public class LTTngTCPSessiondClient { public void destroy() { this.quit = true; - this.eventTimer.cancel(); try { if (this.sessiondSock != null) { @@ -279,8 +201,12 @@ public class LTTngTCPSessiondClient { * Release semaphore so meaning registration is done and we * can proceed to continue tracing. */ - this.registerSem.release(); - break; + tryReleaseSem(); + /* + * We don't send any reply to the registration done command. + * This just marks the end of the initial session setup. + */ + continue; } case CMD_LIST: { @@ -300,14 +226,7 @@ public class LTTngTCPSessiondClient { break; } enableCmd.populate(data); - event = enableCmd.execute(this.handler, this.enabledLoggers); - if (event != null) { - /* - * Add the event to the set so it can be enabled if - * the logger appears at some point in time. - */ - enabledEventSet.add(event); - } + enableCmd.execute(this.handler); data = enableCmd.getBytes(); break; } @@ -342,8 +261,54 @@ public class LTTngTCPSessiondClient { } } + private String getHomePath() { + return System.getProperty("user.home"); + } + + /** + * Read port number from file created by the session daemon. + * + * @return port value if found else 0. + */ + private int getPortFromFile(String path) throws IOException { + int port; + BufferedReader br; + + try { + br = new BufferedReader(new FileReader(path)); + String line = br.readLine(); + port = Integer.parseInt(line, 10); + if (port < 0 || port > 65535) { + /* Invalid value. Ignore. */ + port = 0; + } + br.close(); + } catch (FileNotFoundException e) { + /* No port available. */ + port = 0; + } + + return port; + } + private void connectToSessiond() throws Exception { - this.sessiondSock = new Socket(this.sessiondHost, this.sessiondPort); + int port; + + if (this.handler.is_root == 1) { + port = getPortFromFile(rootPortFile); + if (port == 0) { + /* No session daemon available. Stop and retry later. */ + throw new IOException(); + } + } else { + port = getPortFromFile(getHomePath() + userPortFile); + if (port == 0) { + /* No session daemon available. Stop and retry later. */ + throw new IOException(); + } + } + + this.sessiondSock = new Socket(this.sessiondHost, port); this.inFromSessiond = new DataInputStream( sessiondSock.getInputStream()); this.outToSessiond = new DataOutputStream( @@ -351,10 +316,11 @@ public class LTTngTCPSessiondClient { } private void registerToSessiond() throws Exception { - byte data[] = new byte[4]; + byte data[] = new byte[8]; ByteBuffer buf = ByteBuffer.wrap(data); String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0]; + buf.putInt(this.agent_domain); buf.putInt(Integer.parseInt(pid)); this.outToSessiond.write(data, 0, data.length); this.outToSessiond.flush();