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
.util
.concurrent
.Semaphore
;
21 import java
.nio
.ByteBuffer
;
22 import java
.nio
.ByteOrder
;
23 import java
.lang
.Integer
;
24 import java
.io
.IOException
;
25 import java
.io
.BufferedOutputStream
;
26 import java
.io
.ByteArrayOutputStream
;
27 import java
.io
.DataOutputStream
;
28 import java
.io
.DataInputStream
;
30 import java
.lang
.management
.ManagementFactory
;
31 import java
.util
.ArrayList
;
32 import java
.util
.List
;
33 import java
.util
.Timer
;
34 import java
.util
.TimerTask
;
36 class USTRegisterMsg
{
37 public static int pid
;
40 public class LTTngTCPSessiondClient
{
41 /* Command header from the session deamon. */
42 private LTTngSessiondCmd2_4
.sessiond_hdr headerCmd
=
43 new LTTngSessiondCmd2_4
.sessiond_hdr();
45 private final String sessiondHost
;
46 private final int sessiondPort
;
47 private Socket sessiondSock
;
48 private boolean quit
= false;
50 private DataInputStream inFromSessiond
;
51 private DataOutputStream outToSessiond
;
53 private LTTngLogHandler handler
;
55 private Semaphore registerSem
;
57 private Timer eventTimer
;
58 private List
<String
> enabledEventList
= new ArrayList
<String
>();
59 /* Timer delay at each 5 seconds. */
60 private final static long timerDelay
= 5 * 1000;
61 private static boolean timerInitialized
;
63 public LTTngTCPSessiondClient(String host
, int port
, Semaphore sem
) {
64 this.sessiondHost
= host
;
65 this.sessiondPort
= port
;
66 this.registerSem
= sem
;
67 this.eventTimer
= new Timer();
68 this.timerInitialized
= false;
71 private void setupEventTimer() {
72 if (this.timerInitialized
) {
76 this.eventTimer
.scheduleAtFixedRate(new TimerTask() {
80 * We have to make a copy here since it is possible that the
81 * enabled event list is changed during an iteration on it.
83 List
<String
> tmpList
= new ArrayList
<String
>(enabledEventList
);
85 LTTngSessiondCmd2_4
.sessiond_enable_handler enableCmd
= new
86 LTTngSessiondCmd2_4
.sessiond_enable_handler();
87 for (String strEventName
: tmpList
) {
88 enableCmd
.name
= strEventName
;
89 if (enableCmd
.execute(handler
) == null) {
90 enabledEventList
.remove(strEventName
);
94 }, this.timerDelay
, this.timerDelay
);
96 this.timerInitialized
= true;
99 public void init(LTTngLogHandler handler
) throws InterruptedException
{
100 this.handler
= handler
;
110 * Connect to the session daemon before anything else.
115 * Register to the session daemon as the Java component of the
118 registerToSessiond();
119 this.registerSem
.release();
124 * Block on socket receive and wait for command from the
125 * session daemon. This will return if and only if there is a
126 * fatal error or the socket closes.
129 } catch (UnknownHostException uhe
) {
130 this.registerSem
.release();
131 System
.out
.println(uhe
);
132 } catch (IOException ioe
) {
133 this.registerSem
.release();
135 } catch (Exception e
) {
136 this.registerSem
.release();
142 public void destroy() {
144 this.eventTimer
.cancel();
147 if (this.sessiondSock
!= null) {
148 this.sessiondSock
.close();
150 } catch (Exception e
) {
156 * Receive header data from the session daemon using the LTTng command
157 * static buffer of the right size.
159 private void recvHeader() throws Exception
{
161 byte data
[] = new byte[this.headerCmd
.SIZE
];
163 read_len
= this.inFromSessiond
.read(data
, 0, data
.length
);
164 if (read_len
!= data
.length
) {
165 throw new IOException();
167 this.headerCmd
.populate(data
);
171 * Receive payload from the session daemon. This MUST be done after a
172 * recvHeader() so the header value of a command are known.
174 * The caller SHOULD use isPayload() before which returns true if a payload
175 * is expected after the header.
177 private byte[] recvPayload() throws Exception
{
178 byte payload
[] = new byte[(int) this.headerCmd
.data_size
];
180 /* Failsafe check so we don't waste our time reading 0 bytes. */
181 if (payload
.length
== 0) {
185 this.inFromSessiond
.read(payload
, 0, payload
.length
);
190 * Handle session command from the session daemon.
192 private void handleSessiondCmd() throws Exception
{
197 /* Get header from session daemon. */
200 if (headerCmd
.data_size
> 0) {
201 data
= recvPayload();
204 switch (headerCmd
.cmd
) {
207 LTTngSessiondCmd2_4
.sessiond_list_logger listLoggerCmd
=
208 new LTTngSessiondCmd2_4
.sessiond_list_logger();
209 listLoggerCmd
.execute(this.handler
);
210 data
= listLoggerCmd
.getBytes();
216 LTTngSessiondCmd2_4
.sessiond_enable_handler enableCmd
=
217 new LTTngSessiondCmd2_4
.sessiond_enable_handler();
219 enableCmd
.code
= LTTngSessiondCmd2_4
.lttng_jul_ret_code
.CODE_INVALID_CMD
;
222 enableCmd
.populate(data
);
223 event_name
= enableCmd
.execute(this.handler
);
224 if (event_name
!= null) {
226 * Add the event to the list so it can be enabled if
227 * the logger appears at some point in time.
229 enabledEventList
.add(event_name
);
231 data
= enableCmd
.getBytes();
236 LTTngSessiondCmd2_4
.sessiond_disable_handler disableCmd
=
237 new LTTngSessiondCmd2_4
.sessiond_disable_handler();
239 disableCmd
.code
= LTTngSessiondCmd2_4
.lttng_jul_ret_code
.CODE_INVALID_CMD
;
242 disableCmd
.populate(data
);
243 disableCmd
.execute(this.handler
);
244 data
= disableCmd
.getBytes();
250 ByteBuffer buf
= ByteBuffer
.wrap(data
);
251 buf
.order(ByteOrder
.BIG_ENDIAN
);
252 LTTngSessiondCmd2_4
.lttng_jul_ret_code code
=
253 LTTngSessiondCmd2_4
.lttng_jul_ret_code
.CODE_INVALID_CMD
;
254 buf
.putInt(code
.getCode());
259 /* Send payload to session daemon. */
260 this.outToSessiond
.write(data
, 0, data
.length
);
261 this.outToSessiond
.flush();
265 private void connectToSessiond() throws Exception
{
266 this.sessiondSock
= new Socket(this.sessiondHost
, this.sessiondPort
);
267 this.inFromSessiond
= new DataInputStream(
268 sessiondSock
.getInputStream());
269 this.outToSessiond
= new DataOutputStream(
270 sessiondSock
.getOutputStream());
273 private void registerToSessiond() throws Exception
{
274 byte data
[] = new byte[4];
275 ByteBuffer buf
= ByteBuffer
.wrap(data
);
276 String pid
= ManagementFactory
.getRuntimeMXBean().getName().split("@")[0];
278 buf
.putInt(Integer
.parseInt(pid
));
279 this.outToSessiond
.write(data
, 0, data
.length
);
280 this.outToSessiond
.flush();