Commit | Line | Data |
---|---|---|
43e5396b DG |
1 | /* |
2 | * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com> | |
3 | * | |
4 | * | |
5 | * This library is free software; you can redistribute it and/or modify it | |
6 | * under the terms of the GNU Lesser General Public License, version 2.1 only, | |
7 | * as published by the Free Software Foundation. | |
8 | * | |
9 | * This library is distributed in the hope that it will be useful, but WITHOUT | |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License | |
12 | * for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU Lesser General Public License | |
15 | * along with this library; if not, write to the Free Software Foundation, | |
16 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
17 | */ | |
18 | ||
19 | package org.lttng.ust.jul; | |
20 | ||
21 | import java.nio.ByteBuffer; | |
22 | import java.nio.ByteOrder; | |
a15440fd | 23 | import java.lang.Object; |
43e5396b DG |
24 | import java.util.logging.Logger; |
25 | import java.util.ArrayList; | |
529e6def | 26 | import java.util.HashMap; |
96caa5ed | 27 | import java.util.Map; |
43e5396b | 28 | import java.util.List; |
96caa5ed | 29 | import java.util.Set; |
43e5396b DG |
30 | import java.util.Enumeration; |
31 | ||
32 | public interface LTTngSessiondCmd2_4 { | |
33 | /** | |
34 | * Maximum name length for a logger name to be send to sessiond. | |
35 | */ | |
36 | final static int NAME_MAX = 255; | |
37 | ||
a15440fd DG |
38 | /* |
39 | * Size of a primitive type int in byte. Because you know, Java can't | |
40 | * provide that since it does not makes sense... | |
41 | */ | |
42 | final static int INT_SIZE = 4; | |
43 | ||
43e5396b DG |
44 | public interface SessiondResponse { |
45 | /** | |
46 | * Gets a byte array of the command so that it may be streamed | |
47 | * | |
48 | * @return the byte array of the command | |
49 | */ | |
50 | public byte[] getBytes(); | |
51 | } | |
52 | ||
53 | public interface SessiondCommand { | |
54 | /** | |
55 | * Populate the class from a byte array | |
56 | * | |
57 | * @param data | |
58 | * the byte array containing the streamed command | |
59 | */ | |
60 | public void populate(byte[] data); | |
61 | } | |
62 | ||
63 | public enum lttng_jul_command { | |
64 | /** List logger(s). */ | |
65 | CMD_LIST(1), | |
66 | /** Enable logger by name. */ | |
67 | CMD_ENABLE(2), | |
68 | /** Disable logger by name. */ | |
f08bb871 DG |
69 | CMD_DISABLE(3), |
70 | /** Registration done */ | |
71 | CMD_REG_DONE(4); | |
72 | ||
43e5396b DG |
73 | private int code; |
74 | ||
75 | private lttng_jul_command(int c) { | |
76 | code = c; | |
77 | } | |
78 | ||
79 | public int getCommand() { | |
80 | return code; | |
81 | } | |
82 | } | |
83 | ||
84 | enum lttng_jul_ret_code { | |
85 | CODE_SUCCESS_CMD(1), | |
86 | CODE_INVALID_CMD(2), | |
87 | CODE_UNK_LOGGER_NAME(3); | |
88 | private int code; | |
89 | ||
90 | private lttng_jul_ret_code(int c) { | |
91 | code = c; | |
92 | } | |
93 | ||
94 | public int getCode() { | |
95 | return code; | |
96 | } | |
97 | } | |
98 | ||
99 | public class sessiond_hdr implements SessiondCommand { | |
100 | /** ABI size of command header. */ | |
101 | public final static int SIZE = 16; | |
102 | /** Payload size in bytes following this header. */ | |
103 | public long data_size; | |
104 | /** Command type. */ | |
105 | public lttng_jul_command cmd; | |
106 | /** Command version. */ | |
107 | public int cmd_version; | |
108 | ||
109 | public void populate(byte[] data) { | |
110 | ByteBuffer buf = ByteBuffer.wrap(data); | |
111 | buf.order(ByteOrder.BIG_ENDIAN); | |
112 | ||
113 | data_size = buf.getLong(); | |
114 | cmd = lttng_jul_command.values()[buf.getInt() - 1]; | |
115 | cmd_version = buf.getInt(); | |
116 | } | |
117 | } | |
118 | ||
119 | public class sessiond_enable_handler implements SessiondResponse, SessiondCommand { | |
120 | private final static int SIZE = 4; | |
121 | public String name; | |
a15440fd DG |
122 | public int lttngLogLevel; |
123 | public int lttngLogLevelType; | |
43e5396b DG |
124 | |
125 | /** Return status code to the session daemon. */ | |
126 | public lttng_jul_ret_code code; | |
127 | ||
128 | @Override | |
129 | public void populate(byte[] data) { | |
a15440fd DG |
130 | int data_offset = INT_SIZE * 2; |
131 | ||
43e5396b DG |
132 | ByteBuffer buf = ByteBuffer.wrap(data); |
133 | buf.order(ByteOrder.LITTLE_ENDIAN); | |
a15440fd DG |
134 | lttngLogLevel = buf.getInt(); |
135 | lttngLogLevelType = buf.getInt(); | |
136 | name = new String(data, data_offset, data.length - data_offset); | |
43e5396b DG |
137 | } |
138 | ||
139 | @Override | |
140 | public byte[] getBytes() { | |
141 | byte data[] = new byte[SIZE]; | |
142 | ByteBuffer buf = ByteBuffer.wrap(data); | |
143 | buf.order(ByteOrder.BIG_ENDIAN); | |
144 | buf.putInt(code.getCode()); | |
145 | return data; | |
146 | } | |
147 | ||
148 | /** | |
149 | * Execute enable handler action which is to enable the given handler | |
150 | * to the received name. | |
151 | * | |
152 | * @return Event name as a string if the event is NOT found thus was | |
153 | * not enabled. | |
154 | */ | |
96caa5ed DG |
155 | public void execute(LTTngLogHandler handler, |
156 | Map<String, ArrayList<LTTngEvent>> eventMap, Set wildCardSet) { | |
157 | ArrayList<LTTngEvent> bucket; | |
158 | LTTngEvent event; | |
43e5396b DG |
159 | |
160 | if (name == null) { | |
161 | this.code = lttng_jul_ret_code.CODE_INVALID_CMD; | |
96caa5ed | 162 | return; |
43e5396b DG |
163 | } |
164 | ||
165 | /* Wild card to enable ALL logger. */ | |
166 | if (name.trim().equals("*")) { | |
167 | String loggerName; | |
168 | Enumeration loggers = handler.logManager.getLoggerNames(); | |
5b5ffa03 | 169 | |
96caa5ed DG |
170 | /* Add event to the wildcard set. */ |
171 | wildCardSet.add(new LTTngEvent(name.trim(), lttngLogLevel, | |
172 | lttngLogLevelType)); | |
173 | ||
5b5ffa03 | 174 | /* |
96caa5ed DG |
175 | * Create an event for each logger found and attach it to the |
176 | * handler. | |
5b5ffa03 | 177 | */ |
43e5396b DG |
178 | while (loggers.hasMoreElements()) { |
179 | loggerName = loggers.nextElement().toString(); | |
180 | /* Somehow there is always an empty string at the end. */ | |
181 | if (loggerName == "") { | |
182 | continue; | |
183 | } | |
184 | ||
96caa5ed DG |
185 | event = new LTTngEvent(loggerName, lttngLogLevel, |
186 | lttngLogLevelType); | |
187 | /* Attach event to Log handler to it can be traced. */ | |
188 | handler.attachEvent(event); | |
189 | ||
5b5ffa03 | 190 | /* |
96caa5ed DG |
191 | * The agent timer call this function with eventMap set to |
192 | * null because it already has a reference to an existing | |
193 | * event so is should not try to add a new one here. | |
5b5ffa03 | 194 | */ |
96caa5ed DG |
195 | if (eventMap != null) { |
196 | bucket = eventMap.get(loggerName); | |
197 | if (bucket == null) { | |
198 | bucket = new ArrayList<LTTngEvent>(); | |
199 | eventMap.put(loggerName, bucket); | |
200 | } | |
201 | bucket.add(event); | |
202 | } | |
43e5396b | 203 | } |
96caa5ed DG |
204 | } else { |
205 | event = new LTTngEvent(name.trim(), lttngLogLevel, | |
206 | lttngLogLevelType); | |
207 | /* Attach event to Log handler to it can be traced. */ | |
208 | handler.attachEvent(event); | |
5b5ffa03 | 209 | |
3c3a0129 | 210 | /* |
96caa5ed DG |
211 | * The agent timer call this function with eventMap set to |
212 | * null because it already has a reference to an existing | |
213 | * event so is should not try to add a new one here. | |
3c3a0129 | 214 | */ |
96caa5ed DG |
215 | if (eventMap != null) { |
216 | bucket = eventMap.get(name.trim()); | |
217 | if (bucket == null) { | |
218 | bucket = new ArrayList<LTTngEvent>(); | |
219 | eventMap.put(name.trim(), bucket); | |
220 | } | |
221 | bucket.add(event); | |
3c3a0129 | 222 | } |
43e5396b DG |
223 | } |
224 | ||
225 | this.code = lttng_jul_ret_code.CODE_SUCCESS_CMD; | |
96caa5ed | 226 | return; |
43e5396b DG |
227 | } |
228 | } | |
229 | ||
230 | public class sessiond_disable_handler implements SessiondResponse, SessiondCommand { | |
231 | private final static int SIZE = 4; | |
232 | public String name; | |
96caa5ed DG |
233 | public int lttngLogLevel; |
234 | public int lttngLogLevelType; | |
43e5396b DG |
235 | |
236 | /** Return status code to the session daemon. */ | |
237 | public lttng_jul_ret_code code; | |
238 | ||
239 | @Override | |
240 | public void populate(byte[] data) { | |
96caa5ed DG |
241 | int data_offset = INT_SIZE * 2; |
242 | ||
43e5396b | 243 | ByteBuffer buf = ByteBuffer.wrap(data); |
96caa5ed DG |
244 | buf.order(ByteOrder.LITTLE_ENDIAN); |
245 | lttngLogLevel = buf.getInt(); | |
246 | lttngLogLevelType = buf.getInt(); | |
247 | name = new String(data, data_offset, data.length - data_offset); | |
43e5396b DG |
248 | } |
249 | ||
250 | @Override | |
251 | public byte[] getBytes() { | |
252 | byte data[] = new byte[SIZE]; | |
253 | ByteBuffer buf = ByteBuffer.wrap(data); | |
254 | buf.order(ByteOrder.BIG_ENDIAN); | |
255 | buf.putInt(code.getCode()); | |
256 | return data; | |
257 | } | |
258 | ||
259 | /** | |
260 | * Execute disable handler action which is to disable the given handler | |
261 | * to the received name. | |
262 | */ | |
96caa5ed DG |
263 | public void execute(LTTngLogHandler handler, |
264 | Map<String, ArrayList<LTTngEvent>> eventMap, Set wildCardSet) { | |
265 | ArrayList<LTTngEvent> bucket; | |
266 | LTTngEvent event; | |
43e5396b DG |
267 | |
268 | if (name == null) { | |
269 | this.code = lttng_jul_ret_code.CODE_INVALID_CMD; | |
270 | return; | |
271 | } | |
272 | ||
273 | /* Wild card to disable ALL logger. */ | |
274 | if (name.trim().equals("*")) { | |
275 | String loggerName; | |
276 | Enumeration loggers = handler.logManager.getLoggerNames(); | |
96caa5ed DG |
277 | |
278 | /* Remove event from the wildcard set. */ | |
279 | wildCardSet.remove(new LTTngEvent(name.trim(), lttngLogLevel, | |
280 | lttngLogLevelType)); | |
281 | ||
43e5396b DG |
282 | while (loggers.hasMoreElements()) { |
283 | loggerName = loggers.nextElement().toString(); | |
284 | /* Somehow there is always an empty string at the end. */ | |
285 | if (loggerName == "") { | |
286 | continue; | |
287 | } | |
288 | ||
96caa5ed DG |
289 | event = new LTTngEvent(loggerName, lttngLogLevel, |
290 | lttngLogLevelType); | |
291 | ||
292 | bucket = eventMap.get(loggerName); | |
293 | if (bucket != null) { | |
294 | handler.detachEvent(event); | |
295 | bucket.remove(event); | |
296 | if (bucket.isEmpty() == true) { | |
297 | eventMap.remove(bucket); | |
298 | } | |
299 | } | |
43e5396b DG |
300 | } |
301 | this.code = lttng_jul_ret_code.CODE_SUCCESS_CMD; | |
43e5396b | 302 | } else { |
96caa5ed DG |
303 | event = new LTTngEvent(this.name, lttngLogLevel, |
304 | lttngLogLevelType); | |
305 | ||
306 | bucket = eventMap.get(this.name); | |
307 | if (bucket != null) { | |
308 | handler.detachEvent(event); | |
309 | bucket.remove(event); | |
310 | if (bucket.isEmpty() == true) { | |
311 | eventMap.remove(bucket); | |
312 | } | |
313 | this.code = lttng_jul_ret_code.CODE_SUCCESS_CMD; | |
314 | } else { | |
315 | this.code = lttng_jul_ret_code.CODE_UNK_LOGGER_NAME; | |
316 | } | |
43e5396b | 317 | } |
96caa5ed DG |
318 | |
319 | return; | |
43e5396b DG |
320 | } |
321 | } | |
322 | ||
323 | public class sessiond_list_logger implements SessiondResponse { | |
324 | private final static int SIZE = 12; | |
325 | ||
326 | private int data_size = 0; | |
327 | private int nb_logger = 0; | |
328 | ||
329 | List<String> logger_list = new ArrayList<String>(); | |
330 | ||
331 | /** Return status code to the session daemon. */ | |
332 | public lttng_jul_ret_code code; | |
333 | ||
334 | @Override | |
335 | public byte[] getBytes() { | |
336 | byte data[] = new byte[SIZE + data_size]; | |
337 | ByteBuffer buf = ByteBuffer.wrap(data); | |
338 | buf.order(ByteOrder.BIG_ENDIAN); | |
339 | ||
340 | /* Returned code */ | |
341 | buf.putInt(code.getCode()); | |
342 | buf.putInt(data_size); | |
343 | buf.putInt(nb_logger); | |
344 | ||
345 | for (String logger: logger_list) { | |
346 | buf.put(logger.getBytes()); | |
347 | /* NULL terminated byte after the logger name. */ | |
348 | buf.put((byte) 0x0); | |
349 | } | |
350 | return data; | |
351 | } | |
352 | ||
353 | /** | |
354 | * Execute enable handler action which is to enable the given handler | |
355 | * to the received name. | |
356 | */ | |
357 | public void execute(LTTngLogHandler handler) { | |
358 | String loggerName; | |
359 | ||
360 | Enumeration loggers = handler.logManager.getLoggerNames(); | |
361 | while (loggers.hasMoreElements()) { | |
362 | loggerName = loggers.nextElement().toString(); | |
363 | /* Somehow there is always an empty string at the end. */ | |
364 | if (loggerName == "") { | |
365 | continue; | |
366 | } | |
367 | ||
368 | this.logger_list.add(loggerName); | |
369 | this.nb_logger++; | |
370 | this.data_size += loggerName.length() + 1; | |
371 | } | |
372 | ||
373 | this.code = lttng_jul_ret_code.CODE_SUCCESS_CMD; | |
374 | } | |
375 | } | |
376 | } |