2 * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 package org
.lttng
.ust
.jul
;
20 import java
.io
.IOException
;
21 import java
.io
.FileNotFoundException
;
22 import java
.io
.InputStream
;
23 import java
.io
.BufferedReader
;
24 import java
.io
.FileReader
;
25 import java
.util
.concurrent
.Semaphore
;
26 import java
.util
.logging
.FileHandler
;
27 import java
.util
.logging
.Handler
;
28 import java
.util
.logging
.Level
;
29 import java
.util
.logging
.Logger
;
30 import java
.util
.logging
.LogManager
;
31 import java
.util
.Enumeration
;
33 public class LTTngAgent
{
34 private static LogManager logManager
;
36 /* Possible that we have to threads handling two sessiond. */
37 private static LTTngLogHandler lttngHandlerRoot
;
38 private static LTTngLogHandler lttngHandlerUser
;
39 private static LTTngThread lttngThreadRoot
;
40 private static LTTngThread lttngThreadUser
;
41 private static Thread sessiondThRoot
;
42 private static Thread sessiondThUser
;
44 /* Singleton agent object. */
45 private static LTTngAgent curAgent
= null;
47 /* Indicate if this object has been initialized. */
48 private static boolean initialized
= false;
50 private static Semaphore registerSem
;
52 private static final String sessiondAddr
= "127.0.0.1";
53 private static final int sessiondPort
= 5345;
55 private static final String rootPortFile
= "/var/run/lttng/jul.port";
56 private static final String userPortFile
= "/.lttng/jul.port";
59 * Constructor is private. This is a singleton and a reference should be
60 * acquired using getLTTngAgent().
62 private LTTngAgent() throws IOException
{
63 this.logManager
= LogManager
.getLogManager();
64 this.lttngHandlerUser
= new LTTngLogHandler(this.logManager
);
65 this.lttngHandlerRoot
= new LTTngLogHandler(this.logManager
);
66 this.lttngHandlerRoot
.is_root
= 1;
67 this.registerSem
= new Semaphore(0, true);
70 private void removeHandlers() throws SecurityException
, IOException
{
74 Enumeration list
= this.logManager
.getLoggerNames();
75 while (list
.hasMoreElements()) {
76 loggerName
= list
.nextElement().toString();
77 /* Somehow there is always an empty string at the end. */
78 if (loggerName
== "") {
82 logger
= this.logManager
.getLogger(loggerName
);
83 logger
.removeHandler(this.lttngHandlerUser
);
84 logger
.removeHandler(this.lttngHandlerRoot
);
88 private int getUID() throws IOException
{
90 byte b
[] = new byte[4];
91 String userName
= System
.getProperty("user.name");
92 String command
= "id -u " + userName
;
93 Process child
= Runtime
.getRuntime().exec(command
);
94 InputStream in
= child
.getInputStream();
97 uid
= Integer
.parseInt(new String(b
).trim(), 10);
103 private String
getHomePath() {
104 return System
.getProperty("user.home");
107 private int getPortFromFile(String path
) throws IOException
{
112 br
= new BufferedReader(new FileReader(path
));
113 String line
= br
.readLine();
114 port
= Integer
.parseInt(line
, 10);
115 if (port
< 0 || port
> 65535) {
119 } catch (FileNotFoundException e
) {
127 * Public getter to acquire a reference to this singleton object.
129 public static synchronized LTTngAgent
getLTTngAgent() throws IOException
{
130 if (curAgent
== null) {
131 curAgent
= new LTTngAgent();
139 * Initialize LTTngAgent. This will attach the log handler to all Logger
140 * returned by the logManager.
142 private synchronized void init() throws SecurityException
, IOException
{
143 int user_port
, root_port
;
146 if (this.initialized
) {
150 root_port
= getPortFromFile(rootPortFile
);
152 user_port
= root_port
;
154 user_port
= getPortFromFile(getHomePath() + userPortFile
);
157 /* Handle user session daemon if any. */
158 this.lttngThreadUser
= new LTTngThread(this.sessiondAddr
, user_port
,
159 this.lttngHandlerUser
, this.registerSem
);
160 this.sessiondThUser
= new Thread(lttngThreadUser
);
161 this.sessiondThUser
.start();
162 /* Wait for registration done of per-user sessiond */
165 /* Having two different ports, we have to try both. */
166 if (root_port
!= user_port
) {
167 /* Handle root session daemon. */
168 this.lttngThreadRoot
= new LTTngThread(this.sessiondAddr
,
169 root_port
, this.lttngHandlerRoot
, this.registerSem
);
170 this.sessiondThRoot
= new Thread(lttngThreadRoot
);
171 this.sessiondThRoot
.start();
172 /* Wait for registration done of system-wide sessiond */
176 /* Wait for each registration to end. */
178 this.registerSem
.acquire(nr_acquires
);
179 } catch (InterruptedException e
) {
183 this.initialized
= true;
186 public void dispose() throws IOException
{
187 this.lttngThreadUser
.dispose();
188 if (this.lttngThreadRoot
!= null) {
189 this.lttngThreadRoot
.dispose();
192 /* Make sure there is no more LTTng handler attach to logger(s). */
193 this.removeHandlers();
196 this.sessiondThUser
.join();
197 if (this.sessiondThRoot
!= null) {
198 this.sessiondThRoot
.join();
200 } catch (InterruptedException e
) {