Add liblttng-ust-jul for JUL support
[lttng-ust.git] / liblttng-ust-jul / org / lttng / ust / jul / LTTngTCPSessiondClient.java
CommitLineData
43e5396b
DG
1/*
2 * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
3 *
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.
7 *
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
11 * for more details.
12 *
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
16 */
17
18package org.lttng.ust.jul;
19
20import java.util.concurrent.Semaphore;
21import java.nio.ByteBuffer;
22import java.nio.ByteOrder;
23import java.lang.Integer;
24import java.io.IOException;
25import java.io.BufferedOutputStream;
26import java.io.ByteArrayOutputStream;
27import java.io.DataOutputStream;
28import java.io.DataInputStream;
29import java.net.*;
30import java.lang.management.ManagementFactory;
31import java.util.ArrayList;
32import java.util.List;
33import java.util.Timer;
34import java.util.TimerTask;
35
36class USTRegisterMsg {
37 public static int pid;
38}
39
40public class LTTngTCPSessiondClient {
41 /* Command header from the session deamon. */
42 private LTTngSessiondCmd2_4.sessiond_hdr headerCmd =
43 new LTTngSessiondCmd2_4.sessiond_hdr();
44
45 private final String sessiondHost;
46 private final int sessiondPort;
47 private Socket sessiondSock;
48 private boolean quit = false;
49
50 private DataInputStream inFromSessiond;
51 private DataOutputStream outToSessiond;
52
53 private LTTngLogHandler handler;
54
55 private Semaphore registerSem;
56
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;
62
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;
69 }
70
71 private void setupEventTimer() {
72 if (this.timerInitialized) {
73 return;
74 }
75
76 this.eventTimer.scheduleAtFixedRate(new TimerTask() {
77 @Override
78 public void run() {
79 /*
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.
82 */
83 List<String> tmpList = new ArrayList<String>(enabledEventList);
84
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);
91 }
92 }
93 }
94 }, this.timerDelay, this.timerDelay);
95
96 this.timerInitialized = true;
97 }
98
99 public void init(LTTngLogHandler handler) throws InterruptedException {
100 this.handler = handler;
101
102 for (;;) {
103 if (this.quit) {
104 break;
105 }
106
107 try {
108
109 /*
110 * Connect to the session daemon before anything else.
111 */
112 connectToSessiond();
113
114 /*
115 * Register to the session daemon as the Java component of the
116 * UST application.
117 */
118 registerToSessiond();
119 this.registerSem.release();
120
121 setupEventTimer();
122
123 /*
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.
127 */
128 handleSessiondCmd();
129 } catch (UnknownHostException uhe) {
130 this.registerSem.release();
131 System.out.println(uhe);
132 } catch (IOException ioe) {
133 this.registerSem.release();
134 Thread.sleep(3000);
135 } catch (Exception e) {
136 this.registerSem.release();
137 e.printStackTrace();
138 }
139 }
140 }
141
142 public void destroy() {
143 this.quit = true;
144 this.eventTimer.cancel();
145
146 try {
147 if (this.sessiondSock != null) {
148 this.sessiondSock.close();
149 }
150 } catch (Exception e) {
151 e.printStackTrace();
152 }
153 }
154
155 /*
156 * Receive header data from the session daemon using the LTTng command
157 * static buffer of the right size.
158 */
159 private void recvHeader() throws Exception {
160 int read_len;
161 byte data[] = new byte[this.headerCmd.SIZE];
162
163 read_len = this.inFromSessiond.read(data, 0, data.length);
164 if (read_len != data.length) {
165 throw new IOException();
166 }
167 this.headerCmd.populate(data);
168 }
169
170 /*
171 * Receive payload from the session daemon. This MUST be done after a
172 * recvHeader() so the header value of a command are known.
173 *
174 * The caller SHOULD use isPayload() before which returns true if a payload
175 * is expected after the header.
176 */
177 private byte[] recvPayload() throws Exception {
178 byte payload[] = new byte[(int) this.headerCmd.data_size];
179
180 /* Failsafe check so we don't waste our time reading 0 bytes. */
181 if (payload.length == 0) {
182 return null;
183 }
184
185 this.inFromSessiond.read(payload, 0, payload.length);
186 return payload;
187 }
188
189 /*
190 * Handle session command from the session daemon.
191 */
192 private void handleSessiondCmd() throws Exception {
193 int ret_code;
194 byte data[] = null;
195
196 while (true) {
197 /* Get header from session daemon. */
198 recvHeader();
199
200 if (headerCmd.data_size > 0) {
201 data = recvPayload();
202 }
203
204 switch (headerCmd.cmd) {
205 case CMD_LIST:
206 {
207 LTTngSessiondCmd2_4.sessiond_list_logger listLoggerCmd =
208 new LTTngSessiondCmd2_4.sessiond_list_logger();
209 listLoggerCmd.execute(this.handler);
210 data = listLoggerCmd.getBytes();
211 break;
212 }
213 case CMD_ENABLE:
214 {
215 String event_name;
216 LTTngSessiondCmd2_4.sessiond_enable_handler enableCmd =
217 new LTTngSessiondCmd2_4.sessiond_enable_handler();
218 if (data == null) {
219 enableCmd.code = LTTngSessiondCmd2_4.lttng_jul_ret_code.CODE_INVALID_CMD;
220 break;
221 }
222 enableCmd.populate(data);
223 event_name = enableCmd.execute(this.handler);
224 if (event_name != null) {
225 /*
226 * Add the event to the list so it can be enabled if
227 * the logger appears at some point in time.
228 */
229 enabledEventList.add(event_name);
230 }
231 data = enableCmd.getBytes();
232 break;
233 }
234 case CMD_DISABLE:
235 {
236 LTTngSessiondCmd2_4.sessiond_disable_handler disableCmd =
237 new LTTngSessiondCmd2_4.sessiond_disable_handler();
238 if (data == null) {
239 disableCmd.code = LTTngSessiondCmd2_4.lttng_jul_ret_code.CODE_INVALID_CMD;
240 break;
241 }
242 disableCmd.populate(data);
243 disableCmd.execute(this.handler);
244 data = disableCmd.getBytes();
245 break;
246 }
247 default:
248 {
249 data = new byte[4];
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());
255 break;
256 }
257 }
258
259 /* Send payload to session daemon. */
260 this.outToSessiond.write(data, 0, data.length);
261 this.outToSessiond.flush();
262 }
263 }
264
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());
271 }
272
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];
277
278 buf.putInt(Integer.parseInt(pid));
279 this.outToSessiond.write(data, 0, data.length);
280 this.outToSessiond.flush();
281 }
282}
This page took 0.033824 seconds and 4 git commands to generate.