Commit | Line | Data |
---|---|---|
f3ed775e DG |
1 | /* |
2 | * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca> | |
3 | * | |
d14d33bf AM |
4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License, version 2 only, | |
6 | * as published by the Free Software Foundation. | |
f3ed775e DG |
7 | * |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
12 | * | |
d14d33bf AM |
13 | * You should have received a copy of the GNU General Public License along |
14 | * with this program; if not, write to the Free Software Foundation, Inc., | |
15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
f3ed775e DG |
16 | */ |
17 | ||
6c1c0768 | 18 | #define _LGPL_SOURCE |
b2064f54 | 19 | #include <assert.h> |
f3ed775e DG |
20 | #include <popt.h> |
21 | #include <stdio.h> | |
22 | #include <stdlib.h> | |
f3ed775e DG |
23 | #include <sys/stat.h> |
24 | #include <sys/types.h> | |
25 | #include <unistd.h> | |
5a0de755 | 26 | #include <inttypes.h> |
8f0d098b | 27 | #include <ctype.h> |
f3ed775e | 28 | |
42224349 | 29 | #include <src/common/sessiond-comm/sessiond-comm.h> |
f5436bfc | 30 | #include <common/compat/string.h> |
f3ed775e | 31 | |
89476427 JRJ |
32 | /* Mi dependancy */ |
33 | #include <common/mi-lttng.h> | |
34 | ||
35 | #include "../command.h" | |
36 | ||
8ab7c0d9 MD |
37 | #if (LTTNG_SYMBOL_NAME_LEN == 256) |
38 | #define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "255" | |
39 | #endif | |
40 | ||
f3ed775e DG |
41 | static char *opt_event_list; |
42 | static int opt_event_type; | |
c7dfbc0e | 43 | static char *opt_loglevel; |
0cda4f28 | 44 | static int opt_loglevel_type; |
6181537c | 45 | static int opt_kernel; |
5440dc42 | 46 | static char *opt_session_name; |
721b94fe | 47 | static int opt_domain; |
f3ed775e | 48 | static int opt_enable_all; |
cf0e5467 | 49 | static char *opt_probe; |
8f0d098b | 50 | static char *opt_function; |
f3ed775e | 51 | static char *opt_channel_name; |
53a80697 | 52 | static char *opt_filter; |
fac3366c | 53 | static char *opt_exclude; |
7b0e3fab | 54 | static char *opt_template_path; |
f3ed775e DG |
55 | |
56 | enum { | |
57 | OPT_HELP = 1, | |
f3ed775e | 58 | OPT_TRACEPOINT, |
cf0e5467 | 59 | OPT_PROBE, |
f3ed775e | 60 | OPT_FUNCTION, |
a54bd42d | 61 | OPT_SYSCALL, |
0cda4f28 MD |
62 | OPT_LOGLEVEL, |
63 | OPT_LOGLEVEL_ONLY, | |
679b4943 | 64 | OPT_LIST_OPTIONS, |
53a80697 | 65 | OPT_FILTER, |
fac3366c | 66 | OPT_EXCLUDE, |
f3ed775e DG |
67 | }; |
68 | ||
cd80958d | 69 | static struct lttng_handle *handle; |
89476427 | 70 | static struct mi_writer *writer; |
cd80958d | 71 | |
f3ed775e DG |
72 | static struct poptOption long_options[] = { |
73 | /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */ | |
e14f64a8 | 74 | {"all", 'a', POPT_ARG_VAL, &opt_enable_all, 1, 0, 0}, |
f3ed775e | 75 | {"channel", 'c', POPT_ARG_STRING, &opt_channel_name, 0, 0, 0}, |
721b94fe JR |
76 | {"kernel", 'k', POPT_ARG_VAL, &opt_domain, LTTNG_DOMAIN_KERNEL, 0, 0}, |
77 | {"userspace", 'u', POPT_ARG_VAL, &opt_domain, LTTNG_DOMAIN_UST, 0, 0}, | |
78 | {"jul", 'j', POPT_ARG_VAL, &opt_domain, LTTNG_DOMAIN_JUL, 0, 0}, | |
79 | {"log4j", 'l', POPT_ARG_VAL, &opt_domain, LTTNG_DOMAIN_LOG4J, 0, 0}, | |
80 | {"python", 'p', POPT_ARG_VAL, &opt_domain, LTTNG_DOMAIN_PYTHON, 0, 0}, | |
f3ed775e | 81 | {"tracepoint", 0, POPT_ARG_NONE, 0, OPT_TRACEPOINT, 0, 0}, |
7ebae521 | 82 | {"probe", 0, POPT_ARG_STRING, &opt_probe, OPT_PROBE, 0, 0}, |
40e9d5d3 | 83 | {"function", 0, POPT_ARG_STRING, &opt_function, OPT_FUNCTION, 0, 0}, |
7ebae521 | 84 | {"syscall", 0, POPT_ARG_NONE, 0, OPT_SYSCALL, 0, 0}, |
0cda4f28 MD |
85 | {"loglevel", 0, POPT_ARG_STRING, 0, OPT_LOGLEVEL, 0, 0}, |
86 | {"loglevel-only", 0, POPT_ARG_STRING, 0, OPT_LOGLEVEL_ONLY, 0, 0}, | |
53a80697 | 87 | {"filter", 'f', POPT_ARG_STRING, &opt_filter, OPT_FILTER, 0, 0}, |
fac3366c | 88 | {"exclude", 'x', POPT_ARG_STRING, &opt_exclude, OPT_EXCLUDE, 0, 0}, |
7b0e3fab | 89 | /* No op */ |
721b94fe | 90 | {"session", 's', POPT_ARG_NONE, 0, 0, 0, 0}, |
7b0e3fab | 91 | {"template-path", 't', POPT_ARG_NONE, 0, 0, 0, 0}, |
f3ed775e DG |
92 | {0, 0, 0, 0, 0, 0, 0} |
93 | }; | |
94 | ||
721b94fe JR |
95 | static struct poptOption global_long_options[] = { |
96 | /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */ | |
97 | {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0}, | |
98 | {"session", 's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0}, | |
7b0e3fab | 99 | {"template-path", 't', POPT_ARG_STRING, &opt_template_path, 0, 0, 0}, |
721b94fe JR |
100 | {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL}, |
101 | {0, 0, 0, 0, 0, 0, 0} | |
102 | }; | |
0d63dd19 | 103 | /* |
6181537c | 104 | * Parse probe options. |
0d63dd19 | 105 | */ |
cf0e5467 | 106 | static int parse_probe_opts(struct lttng_event *ev, char *opt) |
0d63dd19 | 107 | { |
49d4e302 JRJ |
108 | int ret = CMD_SUCCESS; |
109 | int match; | |
8ff0bbd0 | 110 | char s_hex[19]; |
8ab7c0d9 | 111 | #define S_HEX_LEN_SCANF_IS_A_BROKEN_API "18" /* 18 is (19 - 1) (\0 is extra) */ |
0d63dd19 DG |
112 | char name[LTTNG_SYMBOL_NAME_LEN]; |
113 | ||
114 | if (opt == NULL) { | |
49d4e302 | 115 | ret = CMD_ERROR; |
8f0d098b | 116 | goto end; |
0d63dd19 DG |
117 | } |
118 | ||
119 | /* Check for symbol+offset */ | |
49d4e302 | 120 | match = sscanf(opt, "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API |
8ab7c0d9 | 121 | "[^'+']+%" S_HEX_LEN_SCANF_IS_A_BROKEN_API "s", name, s_hex); |
49d4e302 | 122 | if (match == 2) { |
7d29a247 | 123 | strncpy(ev->attr.probe.symbol_name, name, LTTNG_SYMBOL_NAME_LEN); |
99497cd0 | 124 | ev->attr.probe.symbol_name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; |
cf0e5467 | 125 | DBG("probe symbol %s", ev->attr.probe.symbol_name); |
9d035200 | 126 | if (*s_hex == '\0') { |
8ff0bbd0 | 127 | ERR("Invalid probe offset %s", s_hex); |
49d4e302 | 128 | ret = CMD_ERROR; |
8f0d098b | 129 | goto end; |
0d63dd19 | 130 | } |
8ff0bbd0 | 131 | ev->attr.probe.offset = strtoul(s_hex, NULL, 0); |
cf0e5467 | 132 | DBG("probe offset %" PRIu64, ev->attr.probe.offset); |
3000dc78 | 133 | ev->attr.probe.addr = 0; |
8f0d098b MD |
134 | goto end; |
135 | } | |
136 | ||
137 | /* Check for symbol */ | |
138 | if (isalpha(name[0])) { | |
49d4e302 | 139 | match = sscanf(opt, "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "s", |
8ab7c0d9 | 140 | name); |
49d4e302 | 141 | if (match == 1) { |
8f0d098b | 142 | strncpy(ev->attr.probe.symbol_name, name, LTTNG_SYMBOL_NAME_LEN); |
99497cd0 | 143 | ev->attr.probe.symbol_name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; |
8f0d098b MD |
144 | DBG("probe symbol %s", ev->attr.probe.symbol_name); |
145 | ev->attr.probe.offset = 0; | |
146 | DBG("probe offset %" PRIu64, ev->attr.probe.offset); | |
147 | ev->attr.probe.addr = 0; | |
148 | goto end; | |
149 | } | |
0d63dd19 DG |
150 | } |
151 | ||
152 | /* Check for address */ | |
49d4e302 JRJ |
153 | match = sscanf(opt, "%" S_HEX_LEN_SCANF_IS_A_BROKEN_API "s", s_hex); |
154 | if (match > 0) { | |
9d035200 | 155 | if (*s_hex == '\0') { |
8ff0bbd0 | 156 | ERR("Invalid probe address %s", s_hex); |
49d4e302 | 157 | ret = CMD_ERROR; |
8f0d098b | 158 | goto end; |
0d63dd19 | 159 | } |
8ff0bbd0 | 160 | ev->attr.probe.addr = strtoul(s_hex, NULL, 0); |
cf0e5467 | 161 | DBG("probe addr %" PRIu64, ev->attr.probe.addr); |
3000dc78 DG |
162 | ev->attr.probe.offset = 0; |
163 | memset(ev->attr.probe.symbol_name, 0, LTTNG_SYMBOL_NAME_LEN); | |
8f0d098b | 164 | goto end; |
0d63dd19 DG |
165 | } |
166 | ||
167 | /* No match */ | |
49d4e302 | 168 | ret = CMD_ERROR; |
0d63dd19 | 169 | |
8f0d098b | 170 | end: |
0d63dd19 DG |
171 | return ret; |
172 | } | |
173 | ||
5cdb6027 DG |
174 | /* |
175 | * Maps LOG4j loglevel from string to value | |
176 | */ | |
177 | static int loglevel_log4j_str_to_value(const char *inputstr) | |
178 | { | |
179 | int i = 0; | |
180 | char str[LTTNG_SYMBOL_NAME_LEN]; | |
181 | ||
3712b110 JG |
182 | if (!inputstr || strlen(inputstr) == 0) { |
183 | return -1; | |
184 | } | |
185 | ||
5cdb6027 DG |
186 | /* |
187 | * Loop up to LTTNG_SYMBOL_NAME_LEN minus one because the NULL bytes is | |
188 | * added at the end of the loop so a the upper bound we avoid the overflow. | |
189 | */ | |
190 | while (i < (LTTNG_SYMBOL_NAME_LEN - 1) && inputstr[i] != '\0') { | |
191 | str[i] = toupper(inputstr[i]); | |
192 | i++; | |
193 | } | |
194 | str[i] = '\0'; | |
195 | ||
196 | if (!strcmp(str, "LOG4J_OFF") || !strcmp(str, "OFF")) { | |
197 | return LTTNG_LOGLEVEL_LOG4J_OFF; | |
198 | } else if (!strcmp(str, "LOG4J_FATAL") || !strcmp(str, "FATAL")) { | |
199 | return LTTNG_LOGLEVEL_LOG4J_FATAL; | |
200 | } else if (!strcmp(str, "LOG4J_ERROR") || !strcmp(str, "ERROR")) { | |
201 | return LTTNG_LOGLEVEL_LOG4J_ERROR; | |
202 | } else if (!strcmp(str, "LOG4J_WARN") || !strcmp(str, "WARN")) { | |
203 | return LTTNG_LOGLEVEL_LOG4J_WARN; | |
204 | } else if (!strcmp(str, "LOG4J_INFO") || !strcmp(str, "INFO")) { | |
205 | return LTTNG_LOGLEVEL_LOG4J_INFO; | |
206 | } else if (!strcmp(str, "LOG4J_DEBUG") || !strcmp(str, "DEBUG")) { | |
207 | return LTTNG_LOGLEVEL_LOG4J_DEBUG; | |
208 | } else if (!strcmp(str, "LOG4J_TRACE") || !strcmp(str, "TRACE")) { | |
209 | return LTTNG_LOGLEVEL_LOG4J_TRACE; | |
210 | } else if (!strcmp(str, "LOG4J_ALL") || !strcmp(str, "ALL")) { | |
211 | return LTTNG_LOGLEVEL_LOG4J_ALL; | |
212 | } else { | |
213 | return -1; | |
214 | } | |
215 | } | |
216 | ||
b2064f54 DG |
217 | /* |
218 | * Maps JUL loglevel from string to value | |
219 | */ | |
220 | static int loglevel_jul_str_to_value(const char *inputstr) | |
221 | { | |
222 | int i = 0; | |
223 | char str[LTTNG_SYMBOL_NAME_LEN]; | |
224 | ||
3712b110 JG |
225 | if (!inputstr || strlen(inputstr) == 0) { |
226 | return -1; | |
227 | } | |
228 | ||
b2064f54 DG |
229 | /* |
230 | * Loop up to LTTNG_SYMBOL_NAME_LEN minus one because the NULL bytes is | |
231 | * added at the end of the loop so a the upper bound we avoid the overflow. | |
232 | */ | |
233 | while (i < (LTTNG_SYMBOL_NAME_LEN - 1) && inputstr[i] != '\0') { | |
234 | str[i] = toupper(inputstr[i]); | |
235 | i++; | |
236 | } | |
237 | str[i] = '\0'; | |
238 | ||
239 | if (!strcmp(str, "JUL_OFF") || !strcmp(str, "OFF")) { | |
240 | return LTTNG_LOGLEVEL_JUL_OFF; | |
241 | } else if (!strcmp(str, "JUL_SEVERE") || !strcmp(str, "SEVERE")) { | |
242 | return LTTNG_LOGLEVEL_JUL_SEVERE; | |
243 | } else if (!strcmp(str, "JUL_WARNING") || !strcmp(str, "WARNING")) { | |
244 | return LTTNG_LOGLEVEL_JUL_WARNING; | |
245 | } else if (!strcmp(str, "JUL_INFO") || !strcmp(str, "INFO")) { | |
246 | return LTTNG_LOGLEVEL_JUL_INFO; | |
247 | } else if (!strcmp(str, "JUL_CONFIG") || !strcmp(str, "CONFIG")) { | |
248 | return LTTNG_LOGLEVEL_JUL_CONFIG; | |
249 | } else if (!strcmp(str, "JUL_FINE") || !strcmp(str, "FINE")) { | |
250 | return LTTNG_LOGLEVEL_JUL_FINE; | |
251 | } else if (!strcmp(str, "JUL_FINER") || !strcmp(str, "FINER")) { | |
252 | return LTTNG_LOGLEVEL_JUL_FINER; | |
253 | } else if (!strcmp(str, "JUL_FINEST") || !strcmp(str, "FINEST")) { | |
254 | return LTTNG_LOGLEVEL_JUL_FINEST; | |
255 | } else if (!strcmp(str, "JUL_ALL") || !strcmp(str, "ALL")) { | |
256 | return LTTNG_LOGLEVEL_JUL_ALL; | |
257 | } else { | |
258 | return -1; | |
259 | } | |
260 | } | |
261 | ||
0e115563 DG |
262 | /* |
263 | * Maps Python loglevel from string to value | |
264 | */ | |
265 | static int loglevel_python_str_to_value(const char *inputstr) | |
266 | { | |
267 | int i = 0; | |
268 | char str[LTTNG_SYMBOL_NAME_LEN]; | |
269 | ||
3712b110 JG |
270 | if (!inputstr || strlen(inputstr) == 0) { |
271 | return -1; | |
272 | } | |
273 | ||
0e115563 DG |
274 | /* |
275 | * Loop up to LTTNG_SYMBOL_NAME_LEN minus one because the NULL bytes is | |
276 | * added at the end of the loop so a the upper bound we avoid the overflow. | |
277 | */ | |
278 | while (i < (LTTNG_SYMBOL_NAME_LEN - 1) && inputstr[i] != '\0') { | |
279 | str[i] = toupper(inputstr[i]); | |
280 | i++; | |
281 | } | |
282 | str[i] = '\0'; | |
283 | ||
284 | if (!strcmp(str, "PYTHON_CRITICAL") || !strcmp(str, "CRITICAL")) { | |
285 | return LTTNG_LOGLEVEL_PYTHON_CRITICAL; | |
286 | } else if (!strcmp(str, "PYTHON_ERROR") || !strcmp(str, "ERROR")) { | |
287 | return LTTNG_LOGLEVEL_PYTHON_ERROR; | |
288 | } else if (!strcmp(str, "PYTHON_WARNING") || !strcmp(str, "WARNING")) { | |
289 | return LTTNG_LOGLEVEL_PYTHON_WARNING; | |
290 | } else if (!strcmp(str, "PYTHON_INFO") || !strcmp(str, "INFO")) { | |
291 | return LTTNG_LOGLEVEL_PYTHON_INFO; | |
292 | } else if (!strcmp(str, "PYTNON_DEBUG") || !strcmp(str, "DEBUG")) { | |
293 | return LTTNG_LOGLEVEL_PYTHON_DEBUG; | |
294 | } else if (!strcmp(str, "PYTHON_NOTSET") || !strcmp(str, "NOTSET")) { | |
295 | return LTTNG_LOGLEVEL_PYTHON_NOTSET; | |
296 | } else { | |
297 | return -1; | |
298 | } | |
299 | } | |
300 | ||
8005f29a | 301 | /* |
0c8477c8 | 302 | * Maps loglevel from string to value |
8005f29a MD |
303 | */ |
304 | static | |
1036985c | 305 | int loglevel_ust_str_to_value(const char *inputstr) |
8005f29a | 306 | { |
46839cc2 MD |
307 | int i = 0; |
308 | char str[LTTNG_SYMBOL_NAME_LEN]; | |
309 | ||
3712b110 JG |
310 | if (!inputstr || strlen(inputstr) == 0) { |
311 | return -1; | |
312 | } | |
313 | ||
e051e07c DG |
314 | /* |
315 | * Loop up to LTTNG_SYMBOL_NAME_LEN minus one because the NULL bytes is | |
316 | * added at the end of the loop so a the upper bound we avoid the overflow. | |
317 | */ | |
318 | while (i < (LTTNG_SYMBOL_NAME_LEN - 1) && inputstr[i] != '\0') { | |
46839cc2 MD |
319 | str[i] = toupper(inputstr[i]); |
320 | i++; | |
321 | } | |
322 | str[i] = '\0'; | |
323 | if (!strcmp(str, "TRACE_EMERG") || !strcmp(str, "EMERG")) { | |
324 | return LTTNG_LOGLEVEL_EMERG; | |
325 | } else if (!strcmp(str, "TRACE_ALERT") || !strcmp(str, "ALERT")) { | |
326 | return LTTNG_LOGLEVEL_ALERT; | |
327 | } else if (!strcmp(str, "TRACE_CRIT") || !strcmp(str, "CRIT")) { | |
328 | return LTTNG_LOGLEVEL_CRIT; | |
329 | } else if (!strcmp(str, "TRACE_ERR") || !strcmp(str, "ERR")) { | |
330 | return LTTNG_LOGLEVEL_ERR; | |
331 | } else if (!strcmp(str, "TRACE_WARNING") || !strcmp(str, "WARNING")) { | |
332 | return LTTNG_LOGLEVEL_WARNING; | |
333 | } else if (!strcmp(str, "TRACE_NOTICE") || !strcmp(str, "NOTICE")) { | |
334 | return LTTNG_LOGLEVEL_NOTICE; | |
335 | } else if (!strcmp(str, "TRACE_INFO") || !strcmp(str, "INFO")) { | |
336 | return LTTNG_LOGLEVEL_INFO; | |
337 | } else if (!strcmp(str, "TRACE_DEBUG_SYSTEM") || !strcmp(str, "DEBUG_SYSTEM") || !strcmp(str, "SYSTEM")) { | |
338 | return LTTNG_LOGLEVEL_DEBUG_SYSTEM; | |
339 | } else if (!strcmp(str, "TRACE_DEBUG_PROGRAM") || !strcmp(str, "DEBUG_PROGRAM") || !strcmp(str, "PROGRAM")) { | |
340 | return LTTNG_LOGLEVEL_DEBUG_PROGRAM; | |
341 | } else if (!strcmp(str, "TRACE_DEBUG_PROCESS") || !strcmp(str, "DEBUG_PROCESS") || !strcmp(str, "PROCESS")) { | |
342 | return LTTNG_LOGLEVEL_DEBUG_PROCESS; | |
343 | } else if (!strcmp(str, "TRACE_DEBUG_MODULE") || !strcmp(str, "DEBUG_MODULE") || !strcmp(str, "MODULE")) { | |
344 | return LTTNG_LOGLEVEL_DEBUG_MODULE; | |
345 | } else if (!strcmp(str, "TRACE_DEBUG_UNIT") || !strcmp(str, "DEBUG_UNIT") || !strcmp(str, "UNIT")) { | |
346 | return LTTNG_LOGLEVEL_DEBUG_UNIT; | |
347 | } else if (!strcmp(str, "TRACE_DEBUG_FUNCTION") || !strcmp(str, "DEBUG_FUNCTION") || !strcmp(str, "FUNCTION")) { | |
348 | return LTTNG_LOGLEVEL_DEBUG_FUNCTION; | |
349 | } else if (!strcmp(str, "TRACE_DEBUG_LINE") || !strcmp(str, "DEBUG_LINE") || !strcmp(str, "LINE")) { | |
350 | return LTTNG_LOGLEVEL_DEBUG_LINE; | |
351 | } else if (!strcmp(str, "TRACE_DEBUG") || !strcmp(str, "DEBUG")) { | |
352 | return LTTNG_LOGLEVEL_DEBUG; | |
8005f29a MD |
353 | } else { |
354 | return -1; | |
355 | } | |
356 | } | |
357 | ||
1036985c JR |
358 | /* |
359 | * Map a userspace agent loglevel to it's value based on the domain type. | |
360 | * | |
361 | * Assert when loglevel is NULL and domain type is LTTNG_DOMAIN_NONE || | |
362 | * LTTNG_DOMAIN_KERNEL. | |
363 | * | |
364 | * return -1 on invalid loglevel. | |
365 | */ | |
366 | static int loglevel_str_to_value(const char* loglevel, enum lttng_domain_type type) | |
367 | { | |
368 | int ret = -1; | |
369 | switch (type) { | |
370 | case LTTNG_DOMAIN_UST: | |
371 | ret = loglevel_ust_str_to_value(loglevel); | |
372 | break; | |
373 | case LTTNG_DOMAIN_JUL: | |
374 | ret = loglevel_jul_str_to_value(loglevel); | |
375 | break; | |
376 | case LTTNG_DOMAIN_LOG4J: | |
377 | ret = loglevel_log4j_str_to_value(loglevel); | |
378 | break; | |
379 | case LTTNG_DOMAIN_PYTHON: | |
380 | ret = loglevel_python_str_to_value(loglevel); | |
381 | break; | |
382 | default: | |
383 | assert(0); | |
384 | } | |
385 | ||
386 | return ret; | |
387 | } | |
388 | ||
85076754 MD |
389 | static |
390 | const char *print_channel_name(const char *name) | |
391 | { | |
392 | return name ? : DEFAULT_CHANNEL_NAME; | |
393 | } | |
394 | ||
395 | static | |
396 | const char *print_raw_channel_name(const char *name) | |
397 | { | |
398 | return name ? : "<default>"; | |
399 | } | |
400 | ||
89476427 JRJ |
401 | /* |
402 | * Mi print exlcusion list | |
403 | */ | |
404 | static | |
405 | int mi_print_exclusion(int count, char **names) | |
406 | { | |
407 | int i, ret; | |
408 | ||
409 | assert(writer); | |
410 | ||
411 | if (count == 0) { | |
412 | ret = 0; | |
413 | goto end; | |
414 | } | |
415 | ret = mi_lttng_writer_open_element(writer, config_element_exclusions); | |
416 | if (ret) { | |
417 | goto end; | |
418 | } | |
419 | ||
420 | for (i = 0; i < count; i++) { | |
421 | ret = mi_lttng_writer_write_element_string(writer, | |
422 | config_element_exclusion, names[i]); | |
423 | if (ret) { | |
424 | goto end; | |
425 | } | |
426 | } | |
427 | ||
428 | /* Close exclusions element */ | |
429 | ret = mi_lttng_writer_close_element(writer); | |
430 | ||
431 | end: | |
432 | return ret; | |
433 | } | |
434 | ||
9c48cab3 JI |
435 | /* |
436 | * Return allocated string for pretty-printing exclusion names. | |
437 | */ | |
438 | static | |
439 | char *print_exclusions(int count, char **names) | |
440 | { | |
441 | int length = 0; | |
442 | int i; | |
443 | const char *preamble = " excluding "; | |
444 | char *ret; | |
445 | ||
446 | if (count == 0) { | |
447 | return strdup(""); | |
448 | } | |
449 | ||
450 | /* calculate total required length */ | |
451 | for (i = 0; i < count; i++) { | |
452 | length += strlen(names[i]) + 1; | |
453 | } | |
454 | ||
455 | /* add length of preamble + one for NUL - one for last (missing) comma */ | |
456 | length += strlen(preamble); | |
fd591b18 MD |
457 | ret = zmalloc(length); |
458 | if (!ret) { | |
459 | return NULL; | |
460 | } | |
9c48cab3 JI |
461 | strncpy(ret, preamble, length); |
462 | for (i = 0; i < count; i++) { | |
463 | strcat(ret, names[i]); | |
464 | if (i != count - 1) { | |
465 | strcat(ret, ","); | |
466 | } | |
467 | } | |
89476427 | 468 | |
9c48cab3 JI |
469 | return ret; |
470 | } | |
471 | ||
7b0e3fab JR |
472 | /* |
473 | * Return an allocated string for pretty printing of exclusion of an event from | |
474 | * a config_element. | |
475 | * | |
476 | * e.g: test,test1,test2 | |
477 | */ | |
478 | static | |
479 | char *print_exclusions_config(const struct config_element *event) | |
480 | { | |
481 | const char *path = "/event/exclusions/exclusion"; | |
482 | struct config_element **element_array = NULL; | |
483 | int element_array_size = 0; | |
484 | char **exclusion_str_array = NULL; | |
485 | char *return_string = NULL; | |
486 | int length = 0; | |
487 | ||
488 | config_element_get_element_array(event, path, &element_array, &element_array_size); | |
489 | if (element_array_size == 0) { | |
490 | return_string = strdup(""); | |
491 | goto end; | |
492 | } | |
493 | ||
494 | exclusion_str_array = calloc(element_array_size, sizeof(char *)); | |
495 | if (!exclusion_str_array) { | |
496 | ERR("calloc exclusion string array"); | |
497 | return_string = NULL; | |
498 | goto end; | |
499 | } | |
500 | ||
501 | /* Fetch data and get full length */ | |
502 | for (int i = 0; i < element_array_size; i++) { | |
503 | exclusion_str_array[i] = config_element_get_element_value(element_array[i], "/exclusion"); | |
504 | if (!exclusion_str_array[i]) { | |
505 | ERR("Fecthing exlusion %d of event config element", i); | |
506 | continue; | |
507 | } | |
508 | length += strlen(exclusion_str_array[i]) + 1; | |
509 | } | |
510 | ||
511 | return_string = zmalloc(length); | |
512 | if (!return_string) { | |
513 | return_string = NULL; | |
514 | goto end; | |
515 | } | |
516 | ||
517 | /* Construct string */ | |
518 | for (int i = 0; i < element_array_size; i++) { | |
519 | if (!exclusion_str_array[i]) { | |
520 | continue; | |
521 | } | |
522 | ||
523 | strcat(return_string, exclusion_str_array[i]); | |
524 | if (i != element_array_size - 1) { | |
525 | strcat(return_string, ","); | |
526 | } | |
527 | } | |
528 | ||
529 | end: | |
530 | config_element_free_array(element_array, element_array_size); | |
531 | if (exclusion_str_array) { | |
532 | for (int i = 0; i < element_array_size; i++) { | |
533 | free(exclusion_str_array[i]); | |
534 | } | |
535 | } | |
536 | free(exclusion_str_array); | |
537 | ||
538 | return return_string; | |
539 | } | |
540 | ||
748bde76 JI |
541 | /* |
542 | * Compare list of exclusions against an event name. | |
543 | * Return a list of legal exclusion names. | |
544 | * Produce an error or a warning about others (depending on the situation) | |
545 | */ | |
546 | static | |
547 | int check_exclusion_subsets(const char *event_name, | |
548 | const char *exclusions, | |
549 | int *exclusion_count_ptr, | |
550 | char ***exclusion_list_ptr) | |
551 | { | |
552 | const char *excluder_ptr; | |
553 | const char *event_ptr; | |
554 | const char *next_excluder; | |
555 | int excluder_length; | |
556 | int exclusion_count = 0; | |
557 | char **exclusion_list = NULL; | |
558 | int ret = CMD_SUCCESS; | |
559 | ||
560 | if (event_name[strlen(event_name) - 1] != '*') { | |
561 | ERR("Event %s: Excluders can only be used with wildcarded events", event_name); | |
562 | goto error; | |
563 | } | |
564 | ||
565 | next_excluder = exclusions; | |
566 | while (*next_excluder != 0) { | |
567 | event_ptr = event_name; | |
568 | excluder_ptr = next_excluder; | |
569 | excluder_length = strcspn(next_excluder, ","); | |
570 | ||
571 | /* Scan both the excluder and the event letter by letter */ | |
572 | while (1) { | |
573 | char e, x; | |
574 | ||
575 | e = *event_ptr; | |
576 | x = *excluder_ptr; | |
577 | ||
578 | if (x == '*') { | |
579 | /* Event is a subset of the excluder */ | |
580 | ERR("Event %s: %.*s excludes all events from %s", | |
581 | event_name, | |
582 | excluder_length, | |
583 | next_excluder, | |
584 | event_name); | |
585 | goto error; | |
586 | } | |
587 | if (e == '*') { | |
5ef79758 MD |
588 | char *string; |
589 | char **new_exclusion_list; | |
590 | ||
748bde76 | 591 | /* Excluder is a proper subset of event */ |
f5436bfc | 592 | string = lttng_strndup(next_excluder, excluder_length); |
5ef79758 | 593 | if (!string) { |
f5436bfc | 594 | PERROR("lttng_strndup error"); |
5ef79758 MD |
595 | goto error; |
596 | } | |
597 | new_exclusion_list = realloc(exclusion_list, | |
1940b29e | 598 | sizeof(char *) * (exclusion_count + 1)); |
5ef79758 MD |
599 | if (!new_exclusion_list) { |
600 | PERROR("realloc"); | |
601 | free(string); | |
602 | goto error; | |
603 | } | |
604 | exclusion_list = new_exclusion_list; | |
748bde76 | 605 | exclusion_count++; |
5ef79758 | 606 | exclusion_list[exclusion_count - 1] = string; |
748bde76 JI |
607 | break; |
608 | } | |
609 | if (x != e) { | |
610 | /* Excluder and event sets have no common elements */ | |
611 | WARN("Event %s: %.*s does not exclude any events from %s", | |
612 | event_name, | |
613 | excluder_length, | |
614 | next_excluder, | |
615 | event_name); | |
616 | break; | |
617 | } | |
618 | excluder_ptr++; | |
619 | event_ptr++; | |
620 | } | |
621 | /* next excluder */ | |
622 | next_excluder += excluder_length; | |
623 | if (*next_excluder == ',') { | |
624 | next_excluder++; | |
625 | } | |
626 | } | |
627 | goto end; | |
628 | error: | |
629 | while (exclusion_count--) { | |
630 | free(exclusion_list[exclusion_count]); | |
631 | } | |
632 | if (exclusion_list != NULL) { | |
633 | free(exclusion_list); | |
634 | } | |
635 | exclusion_list = NULL; | |
636 | exclusion_count = 0; | |
637 | ret = CMD_ERROR; | |
638 | end: | |
639 | *exclusion_count_ptr = exclusion_count; | |
640 | *exclusion_list_ptr = exclusion_list; | |
641 | return ret; | |
642 | } | |
502bbe89 PP |
643 | |
644 | static void warn_on_truncated_exclusion_names(char **exclusion_list, | |
645 | int exclusion_count, int *warn) | |
646 | { | |
647 | size_t i = 0; | |
648 | ||
649 | for (i = 0; i < exclusion_count; ++i) { | |
650 | const char *name = exclusion_list[i]; | |
651 | size_t len = strlen(name); | |
652 | ||
653 | if (len >= LTTNG_SYMBOL_NAME_LEN) { | |
654 | WARN("Event exclusion \"%s\" will be truncated", | |
655 | name); | |
656 | *warn = 1; | |
657 | } | |
658 | } | |
659 | } | |
660 | ||
c7dfbc0e JR |
661 | struct domain_configuration { |
662 | int enable_all; | |
663 | int event_type; | |
664 | char *event_list; | |
665 | char *loglevel; | |
666 | int loglevel_type; | |
667 | enum lttng_domain_type domain_type; | |
668 | char *probe; | |
669 | char *function; | |
670 | char *channel_name; | |
671 | char *filter; | |
672 | char *exclude; | |
673 | }; | |
674 | ||
f3ed775e | 675 | /* |
6181537c | 676 | * Enabling event using the lttng API. |
89476427 | 677 | * Note: in case of error only the last error code will be return. |
f3ed775e | 678 | */ |
c7dfbc0e | 679 | static int enable_events(char *session_name, struct domain_configuration *config) |
f3ed775e | 680 | { |
89476427 JRJ |
681 | int ret = CMD_SUCCESS, command_ret = CMD_SUCCESS; |
682 | int error_holder = CMD_SUCCESS, warn = 0, error = 0, success = 1; | |
b73d0b29 | 683 | char *event_name, *channel_name = NULL; |
f3ed775e | 684 | struct lttng_event ev; |
7d29a247 | 685 | struct lttng_domain dom; |
7ed70bc9 JI |
686 | int exclusion_count = 0; |
687 | char **exclusion_list = NULL; | |
f3ed775e | 688 | |
c7dfbc0e JR |
689 | int config_enable_all; |
690 | int config_event_type; | |
691 | char *config_event_list; | |
692 | char *config_loglevel; | |
693 | int config_loglevel_type; | |
694 | enum lttng_domain_type config_domain_type; | |
695 | char *config_probe; | |
696 | char *config_function; | |
697 | char *config_channel_name; | |
698 | char *config_filter; | |
699 | char *config_exclude; | |
700 | ||
701 | assert(config); | |
702 | ||
441c16a7 MD |
703 | memset(&ev, 0, sizeof(ev)); |
704 | memset(&dom, 0, sizeof(dom)); | |
705 | ||
c7dfbc0e JR |
706 | config_enable_all = config->enable_all; |
707 | config_event_type = config->event_type; | |
708 | config_event_list = config->event_list; | |
709 | config_loglevel = config->loglevel; | |
710 | config_loglevel_type = config->loglevel_type; | |
711 | config_domain_type = config->domain_type; | |
712 | config_probe = config->probe; | |
713 | config_function = config->function; | |
714 | config_channel_name = config->channel_name; | |
715 | config_filter = config->filter; | |
716 | config_exclude = config->exclude; | |
717 | ||
53a80697 | 718 | |
7d29a247 | 719 | /* Create lttng domain */ |
c7dfbc0e JR |
720 | dom.type = config_domain_type; |
721 | switch (config_domain_type) { | |
722 | case LTTNG_DOMAIN_KERNEL: | |
7972aab2 | 723 | dom.buf_type = LTTNG_BUFFER_GLOBAL; |
c7dfbc0e JR |
724 | break; |
725 | case LTTNG_DOMAIN_UST: | |
726 | case LTTNG_DOMAIN_JUL: | |
727 | case LTTNG_DOMAIN_LOG4J: | |
728 | case LTTNG_DOMAIN_PYTHON: | |
0e115563 | 729 | dom.buf_type = LTTNG_BUFFER_PER_UID; |
c7dfbc0e JR |
730 | break; |
731 | case LTTNG_DOMAIN_NONE: | |
732 | default: | |
3ecec76a | 733 | assert(0); |
2bdd86d4 | 734 | } |
7d29a247 | 735 | |
c7dfbc0e | 736 | |
d5dd17fd | 737 | |
c7dfbc0e | 738 | channel_name = config_channel_name; |
ae856491 | 739 | |
cd80958d DG |
740 | handle = lttng_create_handle(session_name, &dom); |
741 | if (handle == NULL) { | |
742 | ret = -1; | |
743 | goto error; | |
744 | } | |
1aef21b6 | 745 | |
89476427 JRJ |
746 | /* Prepare Mi */ |
747 | if (lttng_opt_mi) { | |
c7dfbc0e JR |
748 | /* Open a domain element */ |
749 | ret = mi_lttng_writer_open_element(writer, config_element_domain); | |
750 | if (ret) { | |
751 | ret = CMD_ERROR; | |
752 | goto error; | |
753 | } | |
754 | ||
755 | /* Specify the domain type */ | |
756 | ret = mi_lttng_writer_write_element_string(writer, | |
757 | config_element_type, | |
758 | mi_lttng_domaintype_string(config_domain_type)); | |
759 | if (ret) { | |
760 | ret = CMD_ERROR; | |
761 | goto error; | |
762 | } | |
763 | ||
89476427 JRJ |
764 | /* Open a events element */ |
765 | ret = mi_lttng_writer_open_element(writer, config_element_events); | |
766 | if (ret) { | |
767 | ret = CMD_ERROR; | |
768 | goto error; | |
769 | } | |
770 | } | |
771 | ||
c7dfbc0e | 772 | if (config_enable_all) { |
8c9ae521 | 773 | /* Default setup for enable all */ |
c7dfbc0e JR |
774 | if (config_domain_type == LTTNG_DOMAIN_KERNEL) { |
775 | ev.type = config_event_type; | |
29c62722 | 776 | strcpy(ev.name, "*"); |
300b8fd5 MD |
777 | /* kernel loglevels not implemented */ |
778 | ev.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL; | |
75e8c5ab MD |
779 | } else { |
780 | ev.type = LTTNG_EVENT_TRACEPOINT; | |
781 | strcpy(ev.name, "*"); | |
c7dfbc0e JR |
782 | ev.loglevel_type = config_loglevel_type; |
783 | if (config_loglevel) { | |
1036985c | 784 | ev.loglevel = loglevel_str_to_value(config_loglevel, config_domain_type); |
300b8fd5 | 785 | if (ev.loglevel == -1) { |
c7dfbc0e | 786 | ERR("Unknown loglevel %s", config_loglevel); |
2f70b271 | 787 | ret = -LTTNG_ERR_INVALID; |
300b8fd5 MD |
788 | goto error; |
789 | } | |
22e25b71 | 790 | } else { |
c7dfbc0e JR |
791 | assert(config_domain_type != LTTNG_DOMAIN_NONE || config_domain_type != LTTNG_DOMAIN_KERNEL); |
792 | switch (config_domain_type) { | |
793 | case LTTNG_DOMAIN_UST: | |
b2064f54 | 794 | ev.loglevel = -1; |
c7dfbc0e JR |
795 | break; |
796 | case LTTNG_DOMAIN_JUL: | |
b2064f54 | 797 | ev.loglevel = LTTNG_LOGLEVEL_JUL_ALL; |
c7dfbc0e JR |
798 | break; |
799 | case LTTNG_DOMAIN_LOG4J: | |
34aa3685 | 800 | ev.loglevel = LTTNG_LOGLEVEL_LOG4J_ALL; |
c7dfbc0e JR |
801 | break; |
802 | case LTTNG_DOMAIN_PYTHON: | |
0e115563 | 803 | ev.loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG; |
c7dfbc0e JR |
804 | break; |
805 | default: | |
806 | assert(0); | |
b2064f54 | 807 | } |
300b8fd5 | 808 | } |
75e8c5ab | 809 | } |
8c9ae521 | 810 | |
c7dfbc0e JR |
811 | if (config_exclude) { |
812 | ret = check_exclusion_subsets("*", config_exclude, | |
7ed70bc9 JI |
813 | &exclusion_count, &exclusion_list); |
814 | if (ret == CMD_ERROR) { | |
815 | goto error; | |
816 | } | |
89476427 | 817 | ev.exclusion = 1; |
502bbe89 PP |
818 | |
819 | warn_on_truncated_exclusion_names(exclusion_list, | |
820 | exclusion_count, &warn); | |
7ed70bc9 | 821 | } |
c7dfbc0e | 822 | if (!config_filter) { |
7ed70bc9 JI |
823 | ret = lttng_enable_event_with_exclusions(handle, |
824 | &ev, channel_name, | |
825 | NULL, | |
826 | exclusion_count, exclusion_list); | |
025faf73 DG |
827 | if (ret < 0) { |
828 | switch (-ret) { | |
829 | case LTTNG_ERR_KERN_EVENT_EXIST: | |
830 | WARN("Kernel events already enabled (channel %s, session %s)", | |
85076754 | 831 | print_channel_name(channel_name), session_name); |
89476427 | 832 | warn = 1; |
025faf73 | 833 | break; |
45d5d421 CB |
834 | case LTTNG_ERR_TRACE_ALREADY_STARTED: |
835 | { | |
836 | const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once."; | |
721b94fe | 837 | ERR("Events: %s (domain %s, channel %s, session %s)", |
45d5d421 | 838 | msg, |
721b94fe | 839 | get_domain_str(dom.type), |
45d5d421 CB |
840 | print_channel_name(channel_name), |
841 | session_name); | |
842 | error = 1; | |
843 | break; | |
844 | } | |
025faf73 | 845 | default: |
721b94fe | 846 | ERR("Events: %s (domain %s, channel %s, session %s)", |
85076754 | 847 | lttng_strerror(ret), |
721b94fe | 848 | get_domain_str(dom.type), |
85076754 MD |
849 | ret == -LTTNG_ERR_NEED_CHANNEL_NAME |
850 | ? print_raw_channel_name(channel_name) | |
851 | : print_channel_name(channel_name), | |
852 | session_name); | |
89476427 | 853 | error = 1; |
025faf73 DG |
854 | break; |
855 | } | |
856 | goto end; | |
42224349 | 857 | } |
8c9ae521 | 858 | |
c7dfbc0e | 859 | switch (config_event_type) { |
025faf73 | 860 | case LTTNG_EVENT_TRACEPOINT: |
c7dfbc0e | 861 | if (config_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) { |
9c48cab3 | 862 | char *exclusion_string = print_exclusions(exclusion_count, exclusion_list); |
5ef79758 MD |
863 | |
864 | if (!exclusion_string) { | |
865 | PERROR("Cannot allocate exclusion_string"); | |
866 | error = 1; | |
867 | goto end; | |
868 | } | |
9c48cab3 | 869 | MSG("All %s tracepoints%s are enabled in channel %s for loglevel %s", |
b9dfb167 | 870 | get_domain_str(dom.type), |
9c48cab3 | 871 | exclusion_string, |
85076754 | 872 | print_channel_name(channel_name), |
c7dfbc0e | 873 | config_loglevel); |
9c48cab3 | 874 | free(exclusion_string); |
025faf73 | 875 | } else { |
9c48cab3 | 876 | char *exclusion_string = print_exclusions(exclusion_count, exclusion_list); |
5ef79758 MD |
877 | |
878 | if (!exclusion_string) { | |
879 | PERROR("Cannot allocate exclusion_string"); | |
880 | error = 1; | |
881 | goto end; | |
882 | } | |
9c48cab3 | 883 | MSG("All %s tracepoints%s are enabled in channel %s", |
b9dfb167 | 884 | get_domain_str(dom.type), |
9c48cab3 | 885 | exclusion_string, |
85076754 | 886 | print_channel_name(channel_name)); |
9c48cab3 | 887 | free(exclusion_string); |
025faf73 DG |
888 | } |
889 | break; | |
890 | case LTTNG_EVENT_SYSCALL: | |
891 | if (opt_kernel) { | |
6e911cad MD |
892 | MSG("All %s system calls are enabled in channel %s", |
893 | get_domain_str(dom.type), | |
85076754 | 894 | print_channel_name(channel_name)); |
025faf73 DG |
895 | } |
896 | break; | |
897 | case LTTNG_EVENT_ALL: | |
c7dfbc0e | 898 | if (config_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) { |
9c48cab3 | 899 | char *exclusion_string = print_exclusions(exclusion_count, exclusion_list); |
5ef79758 MD |
900 | |
901 | if (!exclusion_string) { | |
902 | PERROR("Cannot allocate exclusion_string"); | |
903 | error = 1; | |
904 | goto end; | |
905 | } | |
9c48cab3 | 906 | MSG("All %s events%s are enabled in channel %s for loglevel %s", |
b9dfb167 | 907 | get_domain_str(dom.type), |
9c48cab3 | 908 | exclusion_string, |
85076754 | 909 | print_channel_name(channel_name), |
c7dfbc0e | 910 | config_loglevel); |
9c48cab3 | 911 | free(exclusion_string); |
025faf73 | 912 | } else { |
9c48cab3 | 913 | char *exclusion_string = print_exclusions(exclusion_count, exclusion_list); |
5ef79758 MD |
914 | |
915 | if (!exclusion_string) { | |
916 | PERROR("Cannot allocate exclusion_string"); | |
917 | error = 1; | |
918 | goto end; | |
919 | } | |
9c48cab3 | 920 | MSG("All %s events%s are enabled in channel %s", |
b9dfb167 | 921 | get_domain_str(dom.type), |
9c48cab3 | 922 | exclusion_string, |
85076754 | 923 | print_channel_name(channel_name)); |
9c48cab3 | 924 | free(exclusion_string); |
025faf73 DG |
925 | } |
926 | break; | |
927 | default: | |
928 | /* | |
929 | * We should not be here since lttng_enable_event should have | |
930 | * failed on the event type. | |
931 | */ | |
932 | goto error; | |
57064ada | 933 | } |
f3ed775e | 934 | } |
89476427 | 935 | |
c7dfbc0e | 936 | if (config_filter) { |
89476427 | 937 | command_ret = lttng_enable_event_with_exclusions(handle, &ev, channel_name, |
c7dfbc0e | 938 | config_filter, exclusion_count, exclusion_list); |
89476427 JRJ |
939 | if (command_ret < 0) { |
940 | switch (-command_ret) { | |
16363652 | 941 | case LTTNG_ERR_FILTER_EXIST: |
85076754 | 942 | WARN("Filter on all events is already enabled" |
721b94fe JR |
943 | " (domain %s, channel %s, session %s)", |
944 | get_domain_str(dom.type), | |
85076754 | 945 | print_channel_name(channel_name), session_name); |
89476427 | 946 | warn = 1; |
16363652 | 947 | break; |
45d5d421 CB |
948 | case LTTNG_ERR_TRACE_ALREADY_STARTED: |
949 | { | |
950 | const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once."; | |
721b94fe | 951 | ERR("All events: %s (domain %s, channel %s, session %s, filter \'%s\')", |
45d5d421 | 952 | msg, |
721b94fe | 953 | get_domain_str(dom.type), |
45d5d421 | 954 | print_channel_name(channel_name), |
c7dfbc0e | 955 | session_name, config_filter); |
45d5d421 CB |
956 | error = 1; |
957 | break; | |
958 | } | |
16363652 | 959 | default: |
721b94fe | 960 | ERR("All events: %s (domain %s, channel %s, session %s, filter \'%s\')", |
da3d7d0e | 961 | lttng_strerror(command_ret), |
721b94fe | 962 | get_domain_str(dom.type), |
da3d7d0e | 963 | command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME |
85076754 MD |
964 | ? print_raw_channel_name(channel_name) |
965 | : print_channel_name(channel_name), | |
c7dfbc0e | 966 | session_name, config_filter); |
89476427 | 967 | error = 1; |
16363652 DG |
968 | break; |
969 | } | |
89476427 | 970 | error_holder = command_ret; |
16363652 | 971 | } else { |
89476427 | 972 | ev.filter = 1; |
c7dfbc0e | 973 | MSG("Filter '%s' successfully set", config_filter); |
16363652 DG |
974 | } |
975 | } | |
89476427 JRJ |
976 | |
977 | if (lttng_opt_mi) { | |
978 | /* The wildcard * is used for kernel and ust domain to | |
979 | * represent ALL. We copy * in event name to force the wildcard use | |
980 | * for kernel domain | |
981 | * | |
982 | * Note: this is strictly for semantic and printing while in | |
983 | * machine interface mode. | |
984 | */ | |
985 | strcpy(ev.name, "*"); | |
986 | ||
987 | /* If we reach here the events are enabled */ | |
988 | if (!error && !warn) { | |
989 | ev.enabled = 1; | |
990 | } else { | |
991 | ev.enabled = 0; | |
992 | success = 0; | |
993 | } | |
970d848b | 994 | ret = mi_lttng_event(writer, &ev, 1, handle->domain.type); |
89476427 JRJ |
995 | if (ret) { |
996 | ret = CMD_ERROR; | |
997 | goto error; | |
998 | } | |
999 | ||
1000 | /* print exclusion */ | |
1001 | ret = mi_print_exclusion(exclusion_count, exclusion_list); | |
1002 | if (ret) { | |
1003 | ret = CMD_ERROR; | |
1004 | goto error; | |
1005 | } | |
1006 | ||
1007 | /* Success ? */ | |
1008 | ret = mi_lttng_writer_write_element_bool(writer, | |
1009 | mi_lttng_element_command_success, success); | |
1010 | if (ret) { | |
1011 | ret = CMD_ERROR; | |
1012 | goto error; | |
1013 | } | |
1014 | ||
1015 | /* Close event element */ | |
1016 | ret = mi_lttng_writer_close_element(writer); | |
1017 | if (ret) { | |
1018 | ret = CMD_ERROR; | |
1019 | goto error; | |
1020 | } | |
1021 | } | |
1022 | ||
8c9ae521 | 1023 | goto end; |
f3ed775e DG |
1024 | } |
1025 | ||
1026 | /* Strip event list */ | |
c7dfbc0e | 1027 | event_name = strtok(config_event_list, ","); |
f3ed775e | 1028 | while (event_name != NULL) { |
6181537c DG |
1029 | /* Copy name and type of the event */ |
1030 | strncpy(ev.name, event_name, LTTNG_SYMBOL_NAME_LEN); | |
1031 | ev.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; | |
c7dfbc0e | 1032 | ev.type = config_event_type; |
6181537c | 1033 | |
f3ed775e | 1034 | /* Kernel tracer action */ |
c7dfbc0e JR |
1035 | switch (config_domain_type) { |
1036 | case LTTNG_DOMAIN_KERNEL: | |
f3ed775e | 1037 | DBG("Enabling kernel event %s for channel %s", |
85076754 MD |
1038 | event_name, |
1039 | print_channel_name(channel_name)); | |
f3ed775e | 1040 | |
c7dfbc0e | 1041 | switch (config_event_type) { |
29c62722 MD |
1042 | case LTTNG_EVENT_ALL: /* Enable tracepoints and syscalls */ |
1043 | /* If event name differs from *, select tracepoint. */ | |
1044 | if (strcmp(ev.name, "*")) { | |
1045 | ev.type = LTTNG_EVENT_TRACEPOINT; | |
1046 | } | |
1047 | break; | |
e6ddca71 | 1048 | case LTTNG_EVENT_TRACEPOINT: |
f3ed775e | 1049 | break; |
7d29a247 | 1050 | case LTTNG_EVENT_PROBE: |
c7dfbc0e | 1051 | ret = parse_probe_opts(&ev, config_probe); |
49d4e302 | 1052 | if (ret) { |
cf0e5467 | 1053 | ERR("Unable to parse probe options"); |
0d63dd19 DG |
1054 | ret = 0; |
1055 | goto error; | |
1056 | } | |
f3ed775e DG |
1057 | break; |
1058 | case LTTNG_EVENT_FUNCTION: | |
c7dfbc0e | 1059 | ret = parse_probe_opts(&ev, config_function); |
49d4e302 | 1060 | if (ret) { |
8f0d098b MD |
1061 | ERR("Unable to parse function probe options"); |
1062 | ret = 0; | |
1063 | goto error; | |
1064 | } | |
1065 | break; | |
a54bd42d | 1066 | case LTTNG_EVENT_SYSCALL: |
c6aa2d41 MD |
1067 | ev.type = LTTNG_EVENT_SYSCALL; |
1068 | break; | |
f3ed775e | 1069 | default: |
1ab1ea0b | 1070 | ret = CMD_UNDEFINED; |
f3ed775e DG |
1071 | goto error; |
1072 | } | |
0cda4f28 | 1073 | |
0cda4f28 | 1074 | /* kernel loglevels not implemented */ |
8005f29a | 1075 | ev.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL; |
c7dfbc0e JR |
1076 | break; |
1077 | case LTTNG_DOMAIN_UST: | |
1078 | /* User-space tracer action */ | |
300b8fd5 | 1079 | DBG("Enabling UST event %s for channel %s, loglevel %s", event_name, |
c7dfbc0e | 1080 | print_channel_name(channel_name), config_loglevel ? : "<all>"); |
2bdd86d4 | 1081 | |
c7dfbc0e | 1082 | switch (config_event_type) { |
2bdd86d4 | 1083 | case LTTNG_EVENT_ALL: /* Default behavior is tracepoint */ |
2bdd86d4 MD |
1084 | /* Fall-through */ |
1085 | case LTTNG_EVENT_TRACEPOINT: | |
e4baff1e MD |
1086 | /* Copy name and type of the event */ |
1087 | ev.type = LTTNG_EVENT_TRACEPOINT; | |
1088 | strncpy(ev.name, event_name, LTTNG_SYMBOL_NAME_LEN); | |
1089 | ev.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; | |
2bdd86d4 MD |
1090 | break; |
1091 | case LTTNG_EVENT_PROBE: | |
1092 | case LTTNG_EVENT_FUNCTION: | |
2bdd86d4 MD |
1093 | case LTTNG_EVENT_SYSCALL: |
1094 | default: | |
cc62c0c0 | 1095 | ERR("Event type not available for user-space tracing"); |
4ce78777 | 1096 | ret = CMD_UNSUPPORTED; |
2bdd86d4 MD |
1097 | goto error; |
1098 | } | |
0cda4f28 | 1099 | |
c7dfbc0e | 1100 | if (config_exclude) { |
89476427 | 1101 | ev.exclusion = 1; |
d0f1c989 | 1102 | if (config_event_type != LTTNG_EVENT_ALL && config_event_type != LTTNG_EVENT_TRACEPOINT) { |
d5dd17fd JI |
1103 | ERR("Exclusion option can only be used with tracepoint events"); |
1104 | ret = CMD_ERROR; | |
1105 | goto error; | |
1106 | } | |
7ed70bc9 JI |
1107 | /* Free previously allocated items */ |
1108 | if (exclusion_list != NULL) { | |
1109 | while (exclusion_count--) { | |
1110 | free(exclusion_list[exclusion_count]); | |
1111 | } | |
1112 | free(exclusion_list); | |
1113 | exclusion_list = NULL; | |
1114 | } | |
1115 | /* Check for proper subsets */ | |
c7dfbc0e | 1116 | ret = check_exclusion_subsets(event_name, config_exclude, |
7ed70bc9 JI |
1117 | &exclusion_count, &exclusion_list); |
1118 | if (ret == CMD_ERROR) { | |
1119 | goto error; | |
1120 | } | |
502bbe89 PP |
1121 | |
1122 | warn_on_truncated_exclusion_names( | |
1123 | exclusion_list, exclusion_count, &warn); | |
7ed70bc9 JI |
1124 | } |
1125 | ||
c7dfbc0e JR |
1126 | ev.loglevel_type = config_loglevel_type; |
1127 | if (config_loglevel) { | |
1036985c | 1128 | ev.loglevel = loglevel_ust_str_to_value(config_loglevel); |
8005f29a | 1129 | if (ev.loglevel == -1) { |
c7dfbc0e | 1130 | ERR("Unknown loglevel %s", config_loglevel); |
2f70b271 | 1131 | ret = -LTTNG_ERR_INVALID; |
8005f29a MD |
1132 | goto error; |
1133 | } | |
22e25b71 MD |
1134 | } else { |
1135 | ev.loglevel = -1; | |
ed7f4083 | 1136 | } |
c7dfbc0e JR |
1137 | break; |
1138 | case LTTNG_DOMAIN_JUL: | |
1139 | case LTTNG_DOMAIN_LOG4J: | |
1140 | case LTTNG_DOMAIN_PYTHON: | |
1141 | if (config_event_type != LTTNG_EVENT_ALL && | |
1142 | config_event_type != LTTNG_EVENT_TRACEPOINT) { | |
5cdb6027 | 1143 | ERR("Event type not supported for domain."); |
b9dfb167 DG |
1144 | ret = CMD_UNSUPPORTED; |
1145 | goto error; | |
1146 | } | |
b2064f54 | 1147 | |
c7dfbc0e JR |
1148 | ev.loglevel_type = config_loglevel_type; |
1149 | if (config_loglevel) { | |
1036985c | 1150 | ev.loglevel = loglevel_str_to_value(config_loglevel, config_domain_type); |
b2064f54 | 1151 | if (ev.loglevel == -1) { |
c7dfbc0e | 1152 | ERR("Unknown loglevel %s", config_loglevel); |
b2064f54 DG |
1153 | ret = -LTTNG_ERR_INVALID; |
1154 | goto error; | |
1155 | } | |
1156 | } else { | |
c7dfbc0e JR |
1157 | switch (config_domain_type) { |
1158 | case LTTNG_DOMAIN_JUL: | |
5cdb6027 | 1159 | ev.loglevel = LTTNG_LOGLEVEL_JUL_ALL; |
c7dfbc0e JR |
1160 | break; |
1161 | case LTTNG_DOMAIN_LOG4J: | |
5cdb6027 | 1162 | ev.loglevel = LTTNG_LOGLEVEL_LOG4J_ALL; |
c7dfbc0e JR |
1163 | break; |
1164 | case LTTNG_DOMAIN_PYTHON: | |
0e115563 | 1165 | ev.loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG; |
c7dfbc0e JR |
1166 | break; |
1167 | default: | |
1168 | assert(0); | |
1169 | break; | |
5cdb6027 | 1170 | } |
b2064f54 | 1171 | } |
b9dfb167 DG |
1172 | ev.type = LTTNG_EVENT_TRACEPOINT; |
1173 | strncpy(ev.name, event_name, LTTNG_SYMBOL_NAME_LEN); | |
1174 | ev.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; | |
c7dfbc0e JR |
1175 | break; |
1176 | default: | |
3ecec76a | 1177 | assert(0); |
f3ed775e DG |
1178 | } |
1179 | ||
c7dfbc0e | 1180 | if (!config_filter) { |
9c48cab3 JI |
1181 | char *exclusion_string; |
1182 | ||
89476427 | 1183 | command_ret = lttng_enable_event_with_exclusions(handle, |
7ed70bc9 JI |
1184 | &ev, channel_name, |
1185 | NULL, exclusion_count, exclusion_list); | |
9c48cab3 | 1186 | exclusion_string = print_exclusions(exclusion_count, exclusion_list); |
5ef79758 MD |
1187 | if (!exclusion_string) { |
1188 | PERROR("Cannot allocate exclusion_string"); | |
1189 | error = 1; | |
1190 | goto end; | |
1191 | } | |
89476427 | 1192 | if (command_ret < 0) { |
025faf73 | 1193 | /* Turn ret to positive value to handle the positive error code */ |
89476427 | 1194 | switch (-command_ret) { |
025faf73 | 1195 | case LTTNG_ERR_KERN_EVENT_EXIST: |
9c48cab3 | 1196 | WARN("Kernel event %s%s already enabled (channel %s, session %s)", |
85076754 | 1197 | event_name, |
9c48cab3 | 1198 | exclusion_string, |
85076754 | 1199 | print_channel_name(channel_name), session_name); |
89476427 | 1200 | warn = 1; |
025faf73 | 1201 | break; |
45d5d421 CB |
1202 | case LTTNG_ERR_TRACE_ALREADY_STARTED: |
1203 | { | |
1204 | const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once."; | |
721b94fe | 1205 | ERR("Event %s%s: %s (domain %s,channel %s, session %s)", event_name, |
45d5d421 CB |
1206 | exclusion_string, |
1207 | msg, | |
721b94fe | 1208 | get_domain_str(dom.type), |
45d5d421 CB |
1209 | print_channel_name(channel_name), |
1210 | session_name); | |
1211 | error = 1; | |
1212 | break; | |
1213 | } | |
025faf73 | 1214 | default: |
721b94fe | 1215 | ERR("Event %s%s: %s (domain %s, channel %s, session %s)", event_name, |
9c48cab3 | 1216 | exclusion_string, |
da3d7d0e | 1217 | lttng_strerror(command_ret), |
721b94fe | 1218 | get_domain_str(dom.type), |
da3d7d0e | 1219 | command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME |
85076754 MD |
1220 | ? print_raw_channel_name(channel_name) |
1221 | : print_channel_name(channel_name), | |
1222 | session_name); | |
89476427 | 1223 | error = 1; |
025faf73 DG |
1224 | break; |
1225 | } | |
89476427 | 1226 | error_holder = command_ret; |
025faf73 | 1227 | } else { |
8274eeba AB |
1228 | switch (dom.type) { |
1229 | case LTTNG_DOMAIN_KERNEL: | |
1230 | case LTTNG_DOMAIN_UST: | |
49ceaa70 | 1231 | MSG("%s event %s%s created in channel %s", |
8274eeba AB |
1232 | get_domain_str(dom.type), |
1233 | event_name, | |
1234 | exclusion_string, | |
1235 | print_channel_name(channel_name)); | |
1236 | break; | |
1237 | case LTTNG_DOMAIN_JUL: | |
1238 | case LTTNG_DOMAIN_LOG4J: | |
1239 | case LTTNG_DOMAIN_PYTHON: | |
1240 | /* | |
1241 | * Don't print the default channel | |
1242 | * name for agent domains. | |
1243 | */ | |
895707da | 1244 | MSG("%s event %s%s enabled", |
8274eeba AB |
1245 | get_domain_str(dom.type), |
1246 | event_name, | |
1247 | exclusion_string); | |
1248 | break; | |
1249 | default: | |
1250 | assert(0); | |
49ceaa70 | 1251 | } |
42224349 | 1252 | } |
9c48cab3 | 1253 | free(exclusion_string); |
6181537c | 1254 | } |
025faf73 | 1255 | |
c7dfbc0e | 1256 | if (config_filter) { |
9c48cab3 JI |
1257 | char *exclusion_string; |
1258 | ||
89476427 JRJ |
1259 | /* Filter present */ |
1260 | ev.filter = 1; | |
1261 | ||
1262 | command_ret = lttng_enable_event_with_exclusions(handle, &ev, channel_name, | |
c7dfbc0e | 1263 | config_filter, exclusion_count, exclusion_list); |
9c48cab3 | 1264 | exclusion_string = print_exclusions(exclusion_count, exclusion_list); |
5ef79758 MD |
1265 | if (!exclusion_string) { |
1266 | PERROR("Cannot allocate exclusion_string"); | |
1267 | error = 1; | |
1268 | goto end; | |
1269 | } | |
89476427 JRJ |
1270 | if (command_ret < 0) { |
1271 | switch (-command_ret) { | |
7671f53c | 1272 | case LTTNG_ERR_FILTER_EXIST: |
9c48cab3 | 1273 | WARN("Filter on event %s%s is already enabled" |
721b94fe | 1274 | " (domain %s, channel %s, session %s)", |
85076754 | 1275 | event_name, |
9c48cab3 | 1276 | exclusion_string, |
721b94fe | 1277 | get_domain_str(dom.type), |
85076754 | 1278 | print_channel_name(channel_name), session_name); |
89476427 | 1279 | warn = 1; |
7671f53c | 1280 | break; |
45d5d421 CB |
1281 | case LTTNG_ERR_TRACE_ALREADY_STARTED: |
1282 | { | |
1283 | const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once."; | |
721b94fe | 1284 | ERR("Event %s%s: %s (domain %s, channel %s, session %s, filter \'%s\')", ev.name, |
45d5d421 CB |
1285 | exclusion_string, |
1286 | msg, | |
721b94fe | 1287 | get_domain_str(dom.type), |
45d5d421 | 1288 | print_channel_name(channel_name), |
c7dfbc0e | 1289 | session_name, config_filter); |
45d5d421 CB |
1290 | error = 1; |
1291 | break; | |
1292 | } | |
7671f53c | 1293 | default: |
721b94fe | 1294 | ERR("Event %s%s: %s (domain %s, channel %s, session %s, filter \'%s\')", ev.name, |
9c48cab3 | 1295 | exclusion_string, |
da3d7d0e | 1296 | lttng_strerror(command_ret), |
721b94fe | 1297 | get_domain_str(dom.type), |
da3d7d0e | 1298 | command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME |
85076754 MD |
1299 | ? print_raw_channel_name(channel_name) |
1300 | : print_channel_name(channel_name), | |
c7dfbc0e | 1301 | session_name, config_filter); |
89476427 | 1302 | error = 1; |
7671f53c CB |
1303 | break; |
1304 | } | |
89476427 JRJ |
1305 | error_holder = command_ret; |
1306 | ||
16363652 | 1307 | } else { |
721b94fe | 1308 | MSG("Event %s%s: Filter '%s' for domain %s successfully set", |
9c48cab3 | 1309 | event_name, exclusion_string, |
c7dfbc0e | 1310 | config_filter, |
721b94fe | 1311 | get_domain_str(dom.type)); |
53a80697 | 1312 | } |
9c48cab3 | 1313 | free(exclusion_string); |
53a80697 | 1314 | } |
6181537c | 1315 | |
89476427 JRJ |
1316 | if (lttng_opt_mi) { |
1317 | if (command_ret) { | |
1318 | success = 0; | |
1319 | ev.enabled = 0; | |
1320 | } else { | |
1321 | ev.enabled = 1; | |
1322 | } | |
1323 | ||
970d848b | 1324 | ret = mi_lttng_event(writer, &ev, 1, handle->domain.type); |
89476427 JRJ |
1325 | if (ret) { |
1326 | ret = CMD_ERROR; | |
1327 | goto error; | |
1328 | } | |
1329 | ||
1330 | /* print exclusion */ | |
1331 | ret = mi_print_exclusion(exclusion_count, exclusion_list); | |
1332 | if (ret) { | |
1333 | ret = CMD_ERROR; | |
1334 | goto error; | |
1335 | } | |
1336 | ||
1337 | /* Success ? */ | |
1338 | ret = mi_lttng_writer_write_element_bool(writer, | |
1339 | mi_lttng_element_command_success, success); | |
1340 | if (ret) { | |
1341 | ret = CMD_ERROR; | |
1342 | goto end; | |
1343 | } | |
1344 | ||
1345 | /* Close event element */ | |
1346 | ret = mi_lttng_writer_close_element(writer); | |
1347 | if (ret) { | |
1348 | ret = CMD_ERROR; | |
1349 | goto end; | |
1350 | } | |
1351 | } | |
1352 | ||
f3ed775e DG |
1353 | /* Next event */ |
1354 | event_name = strtok(NULL, ","); | |
89476427 JRJ |
1355 | /* Reset warn, error and success */ |
1356 | success = 1; | |
f3ed775e DG |
1357 | } |
1358 | ||
8c9ae521 | 1359 | end: |
89476427 JRJ |
1360 | /* Close Mi */ |
1361 | if (lttng_opt_mi) { | |
c7dfbc0e JR |
1362 | /* Close events and domain element */ |
1363 | ret = mi_lttng_close_multi_element(writer, 2); | |
89476427 JRJ |
1364 | if (ret) { |
1365 | ret = CMD_ERROR; | |
1366 | goto error; | |
1367 | } | |
1368 | } | |
f3ed775e | 1369 | error: |
ae856491 DG |
1370 | if (warn) { |
1371 | ret = CMD_WARNING; | |
1372 | } | |
89476427 JRJ |
1373 | if (error) { |
1374 | ret = CMD_ERROR; | |
1375 | } | |
cd80958d DG |
1376 | lttng_destroy_handle(handle); |
1377 | ||
7ed70bc9 JI |
1378 | if (exclusion_list != NULL) { |
1379 | while (exclusion_count--) { | |
1380 | free(exclusion_list[exclusion_count]); | |
1381 | } | |
1382 | free(exclusion_list); | |
1383 | } | |
1384 | ||
89476427 JRJ |
1385 | /* Overwrite ret with error_holder if there was an actual error with |
1386 | * enabling an event. | |
1387 | */ | |
1388 | ret = error_holder ? error_holder : ret; | |
1389 | ||
f3ed775e DG |
1390 | return ret; |
1391 | } | |
1392 | ||
7b0e3fab JR |
1393 | struct exclusions_tuple { |
1394 | char **exclusion_list; | |
1395 | int exclusion_count; | |
1396 | }; | |
1397 | ||
1398 | static int enable_event_template_per_domain(const struct config_document *document, | |
1399 | const char* session_name, | |
1400 | const struct domain_configuration *config) | |
1401 | { | |
1402 | int ret = 0; | |
1403 | int warn = 0; | |
1404 | int error = 0; | |
1405 | int printed_bytes = 0; | |
1406 | char *query = NULL; | |
1407 | struct config_element **element_array = NULL; | |
1408 | int element_array_size = 0; | |
1409 | struct config_element *config_loglevel_type = NULL; | |
1410 | struct config_element *config_loglevel = NULL; | |
1411 | struct config_element *config_filter = NULL; | |
1412 | struct exclusions_tuple *event_exclusion_array = NULL; | |
1413 | ||
1414 | assert(document); | |
1415 | assert(config); | |
1416 | ||
1417 | ||
1418 | printed_bytes = asprintf(&query, "//sessions/session/domains/domain[./type = '%s']/channels/channel/events/event[./enabled = 'true']", config_get_domain_str(config->domain_type)); | |
1419 | if (printed_bytes <= 0) { | |
1420 | ERR("Asprintf template events query"); | |
1421 | ret = -1; | |
1422 | goto end; | |
1423 | } | |
1424 | ||
1425 | config_document_get_element_array(document, query, &element_array, &element_array_size); | |
1426 | if (!element_array) { | |
1427 | /* No event */ | |
1428 | goto end; | |
1429 | } | |
1430 | ||
1431 | /* | |
1432 | * Handle log_level | |
1433 | * Only userspace domain accept loglevel. | |
1434 | * | |
1435 | * config-> loglevel is only set when the user pass --logleve/ | |
1436 | * --loglevel-only on the command line so use it as a way to | |
1437 | * know if a loglevel override is necessary | |
1438 | */ | |
1439 | if (config->domain_type != LTTNG_DOMAIN_KERNEL && config->loglevel) { | |
1440 | char *loglevel_value_str = NULL; | |
1441 | int loglevel_value = -1; | |
1442 | ||
1443 | loglevel_value = loglevel_str_to_value(config->loglevel, config->domain_type); | |
1444 | if (loglevel_value == -1) { | |
1445 | ERR("Unknown loglevel %s", config->loglevel); | |
1446 | ret = 1; | |
1447 | goto end; | |
1448 | } | |
1449 | ||
1450 | printed_bytes = asprintf(&loglevel_value_str, "%d", loglevel_value); | |
1451 | if (printed_bytes <= 0 ) { | |
1452 | ERR("Asprintf loglevel"); | |
1453 | ret = 1; | |
1454 | goto end; | |
1455 | } | |
1456 | ||
1457 | config_loglevel = config_element_create(config_element_loglevel, loglevel_value_str); | |
1458 | free(loglevel_value_str); | |
1459 | if (!config_loglevel) { | |
1460 | ERR("Loglevel config creation failed"); | |
1461 | ret = 1; | |
1462 | goto end; | |
1463 | } | |
1464 | ||
1465 | config_loglevel_type = config_element_create(config_element_loglevel_type, config_get_loglevel_type_string(config->loglevel_type)); | |
1466 | if (!config_loglevel_type) { | |
1467 | ERR("Loglevel type config creattion failed"); | |
1468 | ret = 1; | |
1469 | goto end; | |
1470 | } | |
1471 | } | |
1472 | ||
1473 | /* Handle the filter */ | |
1474 | if (config->filter) { | |
1475 | config_filter = config_element_create(config_element_filter, config->filter); | |
1476 | if (!config_filter) { | |
1477 | ERR("Filter config creattion failed"); | |
1478 | ret = 1; | |
1479 | goto end; | |
1480 | } | |
1481 | } | |
1482 | ||
1483 | /* | |
1484 | * Handle exclusion on a per event base | |
1485 | * For now only userspace domains can have exclusions. | |
1486 | */ | |
1487 | event_exclusion_array = calloc(element_array_size, sizeof(struct exclusions_tuple)); | |
1488 | if (!event_exclusion_array) { | |
1489 | ERR("Calloc exclusion list array"); | |
1490 | ret = 1; | |
1491 | goto end; | |
1492 | } | |
1493 | ||
1494 | ||
1495 | if (config->domain_type != LTTNG_DOMAIN_KERNEL && config->exclude) { | |
1496 | for (int i = 0; i < element_array_size; i++) { | |
1497 | struct config_element *cur_event = element_array[i]; | |
1498 | char ***exclusion_list = &(event_exclusion_array[i].exclusion_list); | |
1499 | int *exclusion_count = &(event_exclusion_array[i].exclusion_count); | |
1500 | char *event_type_str = NULL; | |
1501 | int event_type; | |
1502 | char *event_name = NULL; | |
1503 | ||
1504 | *exclusion_list = NULL; | |
1505 | *exclusion_count = 0; | |
1506 | ||
1507 | /* Get event name */ | |
1508 | event_name = config_element_get_element_value(cur_event, "/event/name"); | |
1509 | if (!event_name) { | |
1510 | ERR("Reading event name from config element"); | |
1511 | continue; | |
1512 | } | |
1513 | event_type_str = config_element_get_element_value(cur_event, "/event/type"); | |
1514 | if (!event_type_str) { | |
1515 | ERR("Reading event type from config element"); | |
1516 | free(event_name); | |
1517 | continue; | |
1518 | } | |
1519 | ||
1520 | event_type = config_get_event_type(event_type_str); | |
1521 | if (event_type != LTTNG_EVENT_ALL && event_type != LTTNG_EVENT_TRACEPOINT) { | |
1522 | const char *msg = "Exclusions do not apply to this event"; | |
1523 | WARN("Event %s: %s exclusions: %s (domain %s, channel %s, session %s)", | |
1524 | event_name, msg, config->exclude, | |
1525 | get_domain_str(config->domain_type), | |
1526 | print_channel_name(config->channel_name), | |
1527 | session_name); | |
1528 | free(event_type_str); | |
1529 | free(event_name); | |
1530 | goto end; | |
1531 | } | |
1532 | ||
1533 | /* Check for proper subsets */ | |
1534 | ret = check_exclusion_subsets(event_name, config->exclude, | |
1535 | exclusion_count, exclusion_list); | |
1536 | ||
1537 | warn_on_truncated_exclusion_names( | |
1538 | *exclusion_list, *exclusion_count, &warn); | |
1539 | free(event_type_str); | |
1540 | free(event_name); | |
1541 | } | |
1542 | } | |
1543 | ||
1544 | /* | |
1545 | * Create valid events config_element and try to enable them one by one | |
1546 | */ | |
1547 | for (int i = 0; i < element_array_size; i++) { | |
1548 | const char *sub_msg = NULL; | |
1549 | bool success = false; | |
1550 | bool warn = false; | |
1551 | ||
1552 | struct config_element *cur_event = element_array[i]; | |
1553 | struct config_element *success_element = NULL; | |
1554 | char *msg = NULL; | |
1555 | char *exclusions_string = NULL; | |
1556 | char *filter_string = NULL; | |
1557 | char *event_name = NULL; | |
1558 | ||
1559 | event_name = config_element_get_element_value(cur_event, "/event/name"); | |
1560 | if (!event_name) { | |
1561 | sub_msg = "event name not present abort event creation "; | |
1562 | event_name = strdup("<Error fetching event name>"); | |
1563 | goto enable_event_continue; | |
1564 | } | |
1565 | ||
1566 | /* Add the loglevel */ | |
1567 | if (config_loglevel && config_loglevel_type) { | |
1568 | config_element_add_or_replace_child(cur_event, config_loglevel); | |
1569 | config_element_add_or_replace_child(cur_event, config_loglevel_type); | |
1570 | } | |
1571 | if (config_filter) { | |
1572 | config_element_add_or_replace_child(cur_event, config_filter); | |
1573 | } | |
1574 | ||
1575 | if (event_exclusion_array[i].exclusion_list) { | |
1576 | char **exclusion_list = event_exclusion_array[i].exclusion_list; | |
1577 | const int exclusion_count = event_exclusion_array[i].exclusion_count; | |
1578 | struct config_element *config_exclusions = NULL; | |
1579 | struct config_element *exclusion = NULL; | |
1580 | ||
1581 | config_exclusions = config_element_create(config_element_exclusions, NULL); | |
1582 | if (!config_exclusions) { | |
1583 | sub_msg = "Exclusions config element ration failed abort event creation"; | |
1584 | goto enable_event_continue; | |
1585 | } | |
1586 | ||
1587 | for (int j = 0; j < exclusion_count; j++) { | |
1588 | exclusion = config_element_create(config_element_exclusion, exclusion_list[j]); | |
1589 | if (!exclusion) { | |
1590 | sub_msg = "Exclusion config element creation failed abort event creation"; | |
1591 | config_element_free(config_exclusions); | |
1592 | goto enable_event_continue; | |
1593 | } | |
1594 | ret = config_element_add_child(config_exclusions, exclusion); | |
1595 | if (ret) { | |
1596 | sub_msg = "Exclusion config element child addition failed abort event creation"; | |
1597 | config_element_free(config_exclusions); | |
1598 | config_element_free(exclusion); | |
1599 | goto enable_event_continue; | |
1600 | } | |
1601 | ||
1602 | config_element_free(exclusion); | |
1603 | } | |
1604 | ||
1605 | ret = config_element_add_or_replace_child(cur_event, config_exclusions); | |
1606 | if (ret) { | |
1607 | sub_msg = "Exclusions config element child addition failed abort event creation"; | |
1608 | config_element_free(config_exclusions); | |
1609 | goto enable_event_continue; | |
1610 | } | |
1611 | config_element_free(config_exclusions); | |
1612 | } | |
1613 | ||
1614 | ||
1615 | ret = config_process_event_element(cur_event, session_name, config->domain_type, config->channel_name); | |
1616 | if (!ret) { | |
1617 | success = true; | |
1618 | sub_msg = "created"; | |
1619 | ||
1620 | /* Mi element insertion */ | |
1621 | success_element = config_element_create(mi_lttng_element_command_success, "true"); | |
1622 | if (success_element) { | |
1623 | ret = config_element_add_or_replace_child(cur_event, success_element); | |
1624 | if (ret) { | |
1625 | error = 1; | |
1626 | } | |
1627 | } else { | |
1628 | error = 1; | |
1629 | } | |
1630 | ||
1631 | } else { | |
1632 | success = false; | |
1633 | if (ret < 0) { | |
1634 | sub_msg = lttng_strerror(ret); | |
1635 | if (-ret == LTTNG_ERR_UST_EVENT_ENABLED || -ret == LTTNG_ERR_KERN_EVENT_EXIST) { | |
1636 | /*This is not an error */ | |
1637 | warn = true; | |
1638 | } | |
1639 | } else { | |
1640 | sub_msg = "creation failed"; | |
1641 | } | |
1642 | ||
1643 | /* Mi related insertion */ | |
1644 | success_element = config_element_create(mi_lttng_element_command_success, "false"); | |
1645 | if (success_element) { | |
1646 | ret = config_element_add_or_replace_child(cur_event, success_element); | |
1647 | if (ret) { | |
1648 | error = 1; | |
1649 | } | |
1650 | } else { | |
1651 | error = 1; | |
1652 | } | |
1653 | } | |
1654 | ||
1655 | enable_event_continue: | |
1656 | ||
1657 | /* Get exclusions string for printing */ | |
1658 | exclusions_string = print_exclusions_config(cur_event); | |
1659 | filter_string = config_element_get_element_value(cur_event, "/event/filter"); | |
1660 | ||
1661 | ||
1662 | /* Domain is already present inside the error or msg */ | |
1663 | printed_bytes = asprintf(&msg,"%s%sEvent %s: %s (exclusions: [%s] filter: [%s] session %s, channel %s)", | |
1664 | success ? get_domain_str(config->domain_type): "", | |
1665 | success ? " " : "", | |
1666 | event_name, | |
1667 | sub_msg, | |
1668 | /* | |
1669 | * TODO: print actual exclusion of loaded event | |
1670 | */ | |
1671 | exclusions_string ? : "", | |
1672 | /* | |
1673 | * TODO: print actual exclusion of loaded event | |
1674 | */ | |
1675 | filter_string ? : "", | |
1676 | session_name, | |
1677 | print_channel_name(config->channel_name)); | |
1678 | ||
1679 | if (printed_bytes > 0 && success) { | |
1680 | MSG("%s", msg); | |
1681 | } else if (printed_bytes > 0 && warn) { | |
1682 | WARN("%s", msg); | |
1683 | /* At least one event failed */ | |
1684 | error = 1; | |
1685 | } else if (printed_bytes > 0) { | |
1686 | ERR("%s", msg); | |
1687 | } else { | |
1688 | ERR("Asprintf enable event message"); | |
1689 | /* At least one event failed */ | |
1690 | error = 1; | |
1691 | } | |
1692 | config_element_free(success_element); | |
1693 | free(exclusions_string); | |
1694 | free(event_name); | |
1695 | free(filter_string); | |
1696 | free(msg); | |
1697 | continue; | |
1698 | } | |
1699 | ||
1700 | /* Prepare Mi */ | |
1701 | if (lttng_opt_mi) { | |
1702 | /* Open a domain element */ | |
1703 | ret = mi_lttng_writer_open_element(writer, config_element_domain); | |
1704 | if (ret) { | |
1705 | ret = 1; | |
1706 | goto end; | |
1707 | } | |
1708 | ||
1709 | /* Specify the domain type */ | |
1710 | ret = mi_lttng_writer_write_element_string(writer, | |
1711 | config_element_type, | |
1712 | mi_lttng_domaintype_string(config->domain_type)); | |
1713 | if (ret) { | |
1714 | ret = 1; | |
1715 | goto end; | |
1716 | } | |
1717 | ||
1718 | /* Open a events element */ | |
1719 | ret = mi_lttng_writer_open_element(writer, config_element_events); | |
1720 | if (ret) { | |
1721 | ret = 1; | |
1722 | goto end; | |
1723 | } | |
1724 | ||
1725 | for (int i = 0; i < element_array_size; i++) { | |
1726 | ret = mi_lttng_writer_write_config_element(writer, | |
1727 | element_array[i]); | |
1728 | if (ret) { | |
1729 | ret = 1; | |
1730 | goto end; | |
1731 | } | |
1732 | } | |
1733 | ||
1734 | ret = mi_lttng_close_multi_element(writer, 2); | |
1735 | if (ret) { | |
1736 | ret = 1; | |
1737 | goto end; | |
1738 | } | |
1739 | } | |
1740 | ||
1741 | ||
1742 | end: | |
1743 | /* Free exclusion allocated items */ | |
1744 | if (event_exclusion_array != NULL) { | |
1745 | for (int i = 0; i < element_array_size; i++) { | |
1746 | char **exclusion_list = event_exclusion_array[i].exclusion_list; | |
1747 | int exclusion_count = event_exclusion_array[i].exclusion_count; | |
1748 | if (exclusion_list != NULL) { | |
1749 | while (exclusion_count--) { | |
1750 | free(exclusion_list[exclusion_count]); | |
1751 | } | |
1752 | } | |
1753 | free(exclusion_list); | |
1754 | exclusion_list = NULL; | |
1755 | } | |
1756 | free(event_exclusion_array); | |
1757 | } | |
1758 | config_element_free_array(element_array, element_array_size); | |
1759 | config_element_free(config_loglevel); | |
1760 | config_element_free(config_loglevel_type); | |
1761 | config_element_free(config_filter); | |
1762 | free(query); | |
1763 | if (error) { | |
1764 | ret = 1; | |
1765 | } | |
1766 | return ret; | |
1767 | } | |
1768 | ||
1769 | ||
1770 | static int enable_event_from_template(const struct config_document *document, | |
1771 | const char* session_name, | |
1772 | const struct domain_configuration *kernel_config, | |
1773 | const struct domain_configuration *ust_config, | |
1774 | const struct domain_configuration *jul_config, | |
1775 | const struct domain_configuration *log4j_config, | |
1776 | const struct domain_configuration *python_config) | |
1777 | { | |
1778 | int ret = 0; | |
1779 | int error = 0; | |
1780 | ||
1781 | ret = enable_event_template_per_domain(document, session_name, kernel_config); | |
1782 | if (ret) { | |
1783 | error = ret; | |
1784 | } | |
1785 | ret = enable_event_template_per_domain(document, session_name, ust_config); | |
1786 | if (ret) { | |
1787 | error = ret; | |
1788 | } | |
1789 | ret = enable_event_template_per_domain(document, session_name, jul_config); | |
1790 | if (ret) { | |
1791 | error = ret; | |
1792 | } | |
1793 | ret = enable_event_template_per_domain(document, session_name, log4j_config); | |
1794 | if (ret) { | |
1795 | error = ret; | |
1796 | } | |
1797 | ret = enable_event_template_per_domain(document, session_name, python_config); | |
1798 | if (ret) { | |
1799 | error = ret; | |
1800 | } | |
1801 | ||
1802 | return error; | |
1803 | } | |
1804 | ||
f3ed775e | 1805 | /* |
6181537c | 1806 | * Add event to trace session |
f3ed775e | 1807 | */ |
721b94fe JR |
1808 | |
1809 | struct args_tuple { | |
1810 | int argv_index_start; | |
1811 | int argv_index_end; | |
1812 | }; | |
1813 | ||
721b94fe JR |
1814 | |
1815 | static struct domain_configuration *initialize_domain_configuration(enum lttng_domain_type type) | |
f3ed775e | 1816 | { |
f3ed775e | 1817 | |
721b94fe | 1818 | struct domain_configuration *config = malloc(sizeof(struct domain_configuration)); |
f3ed775e | 1819 | |
721b94fe JR |
1820 | if (!config) { |
1821 | goto end; | |
1822 | } | |
f3ed775e | 1823 | |
721b94fe | 1824 | switch(type) { |
c7dfbc0e JR |
1825 | case LTTNG_DOMAIN_KERNEL: |
1826 | config->domain_type = LTTNG_DOMAIN_KERNEL; | |
1827 | break; | |
1828 | case LTTNG_DOMAIN_UST: | |
1829 | config->domain_type = LTTNG_DOMAIN_UST; | |
1830 | break; | |
1831 | case LTTNG_DOMAIN_JUL: | |
1832 | config->domain_type = LTTNG_DOMAIN_JUL; | |
1833 | break; | |
1834 | case LTTNG_DOMAIN_LOG4J: | |
1835 | config->domain_type = LTTNG_DOMAIN_LOG4J; | |
1836 | break; | |
1837 | case LTTNG_DOMAIN_PYTHON: | |
1838 | config->domain_type = LTTNG_DOMAIN_PYTHON; | |
1839 | break; | |
1840 | case LTTNG_DOMAIN_NONE: | |
1841 | default: | |
1842 | free(config); | |
1843 | config=NULL; | |
1844 | goto end; | |
721b94fe JR |
1845 | }; |
1846 | ||
1847 | config->event_type = LTTNG_EVENT_ALL ; | |
1848 | config->enable_all = 0; | |
1849 | config->loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL; | |
1850 | config->loglevel = NULL; | |
1851 | config->probe = NULL; | |
1852 | config->function = NULL; | |
1853 | config->channel_name = NULL; | |
1854 | config->filter = NULL; | |
1855 | config->exclude = NULL; | |
1856 | config->event_list = NULL; | |
1857 | end: | |
1858 | return config; | |
1859 | } | |
de044b7a | 1860 | |
721b94fe JR |
1861 | int cmd_enable_events(int argc, const char **argv) |
1862 | { | |
1863 | int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1; | |
1864 | static poptContext pc; | |
1865 | char *session_name = NULL; | |
1866 | int event_type = -1; | |
7b0e3fab JR |
1867 | int i; |
1868 | int args_tuple_count = 0; | |
1869 | int arg_state_looking_for_end = 0; | |
1870 | struct args_tuple *args_tuple_list = NULL; | |
1871 | struct domain_configuration *tmp_config = NULL; | |
1872 | ||
1873 | struct config_document *template = NULL; | |
f3ed775e | 1874 | |
721b94fe | 1875 | struct domain_configuration *jul_config = NULL; |
c7dfbc0e | 1876 | struct domain_configuration *kernel_config = NULL; |
721b94fe JR |
1877 | struct domain_configuration *log4j_config = NULL; |
1878 | struct domain_configuration *python_config = NULL; | |
c7dfbc0e | 1879 | struct domain_configuration *ust_config = NULL; |
3ecec76a | 1880 | |
89476427 JRJ |
1881 | /* Mi check */ |
1882 | if (lttng_opt_mi) { | |
1883 | writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi); | |
1884 | if (!writer) { | |
1885 | ret = -LTTNG_ERR_NOMEM; | |
1886 | goto end; | |
1887 | } | |
1888 | ||
1889 | /* Open command element */ | |
1890 | ret = mi_lttng_writer_command_open(writer, | |
1891 | mi_lttng_element_command_enable_event); | |
1892 | if (ret) { | |
1893 | ret = CMD_ERROR; | |
1894 | goto end; | |
1895 | } | |
1896 | ||
1897 | /* Open output element */ | |
1898 | ret = mi_lttng_writer_open_element(writer, | |
1899 | mi_lttng_element_command_output); | |
1900 | if (ret) { | |
1901 | ret = CMD_ERROR; | |
1902 | goto end; | |
1903 | } | |
c7dfbc0e JR |
1904 | |
1905 | /* Open the domains element */ | |
1906 | ret = mi_lttng_domains_open(writer); | |
1907 | if (ret) { | |
1908 | ret = CMD_ERROR; | |
1909 | goto end; | |
1910 | } | |
1911 | ||
89476427 JRJ |
1912 | } |
1913 | ||
721b94fe JR |
1914 | /* Parse global arguments */ |
1915 | pc = poptGetContext(NULL, argc, argv, global_long_options, 0); | |
1916 | poptReadDefaultConfig(pc, 0); | |
1917 | ||
1918 | ||
1919 | while ((opt = poptGetNextOpt(pc)) != -1) { | |
1920 | switch (opt) { | |
1921 | case OPT_HELP: | |
1922 | SHOW_HELP(); | |
1923 | goto end; | |
1924 | case OPT_LIST_OPTIONS: | |
1925 | list_cmd_options(stdout, long_options); | |
1926 | goto end; | |
1927 | default: | |
1928 | break; | |
1929 | } | |
f3ed775e DG |
1930 | } |
1931 | ||
721b94fe JR |
1932 | /* Dispose the global arguments context */ |
1933 | poptFreeContext(pc); | |
1934 | pc = NULL; | |
1935 | ||
c7dfbc0e JR |
1936 | if (!opt_session_name) { |
1937 | session_name = get_session_name(); | |
1938 | if (session_name == NULL) { | |
1939 | command_ret = CMD_ERROR; | |
1940 | success = 0; | |
1941 | goto mi_closing; | |
1942 | } | |
1943 | } else { | |
1944 | session_name = opt_session_name; | |
1945 | } | |
1946 | ||
721b94fe | 1947 | /* Find the number of domain based on the passed arguments */ |
721b94fe JR |
1948 | for (i = 1; i < argc ; i++) { |
1949 | ||
1950 | if (strcmp("-u", argv[i]) && strcmp("--userspace", argv[i]) && | |
1951 | strcmp("-j", argv[i]) && strcmp("--jul", argv[i]) && | |
1952 | strcmp("-l", argv[i]) && strcmp("--log4j", argv[i]) && | |
1953 | strcmp("-p", argv[i]) && strcmp("--python", argv[i]) && | |
1954 | strcmp("-k", argv[i]) && strcmp("--kernel", argv[i])) { | |
1955 | continue; | |
1956 | } | |
1957 | ||
1958 | ||
1959 | struct args_tuple *tmp_pointer = NULL; | |
1960 | args_tuple_count++; | |
1961 | tmp_pointer = realloc(args_tuple_list, sizeof(struct args_tuple) * args_tuple_count); | |
1962 | if (!tmp_pointer) { | |
1963 | ERR("Realoc of args tuple failed"); | |
1964 | ret = CMD_ERROR; | |
1965 | goto end; | |
1966 | } | |
1967 | args_tuple_list = tmp_pointer; | |
1968 | ||
1969 | if (!arg_state_looking_for_end) { | |
1970 | if (args_tuple_count -1 < 0) { | |
1971 | ERR("Args parsing illegal state"); | |
1972 | ret = CMD_ERROR; | |
1973 | goto end; | |
1974 | } | |
1975 | args_tuple_list[args_tuple_count-1].argv_index_start = i; | |
1976 | arg_state_looking_for_end = 1; | |
1977 | } else { | |
1978 | if (args_tuple_count - 2 < 0 || args_tuple_count -1 < 0) { | |
1979 | ERR("Args parsing illegal state"); | |
1980 | ret = CMD_ERROR; | |
1981 | goto end; | |
1982 | } | |
1983 | ||
1984 | /* Close the previous tuple */ | |
1985 | args_tuple_list[args_tuple_count-2].argv_index_end = i - 1; | |
1986 | ||
1987 | /* Start the new tuple */ | |
1988 | args_tuple_list[args_tuple_count-1].argv_index_start = i; | |
cd80958d | 1989 | } |
cd80958d DG |
1990 | } |
1991 | ||
7b0e3fab | 1992 | if (args_tuple_count == 0 && !opt_template_path) { |
721b94fe JR |
1993 | ret = print_missing_or_multiple_domains(0); |
1994 | if (ret) { | |
1995 | ret = CMD_ERROR; | |
1996 | goto end; | |
1997 | } | |
1998 | goto end; | |
7b0e3fab JR |
1999 | } else if (args_tuple_count > 0) { |
2000 | /* Close the last tuple */ | |
2001 | args_tuple_list[args_tuple_count-1].argv_index_end = i - 1; | |
721b94fe | 2002 | |
7b0e3fab JR |
2003 | if (args_tuple_count == 1) { |
2004 | /* Preserve the old way with a domain flag that can be anywhere */ | |
2005 | args_tuple_list[0].argv_index_start = 1; | |
2006 | } | |
721b94fe JR |
2007 | } |
2008 | ||
2009 | for (i = 0; i < args_tuple_count; i++) { | |
2010 | struct args_tuple *tuple = &args_tuple_list[i]; | |
2011 | int cur_argc = tuple->argv_index_end - tuple-> argv_index_start + 1; | |
2012 | const char **cur_argv = &argv[tuple->argv_index_start]; | |
2013 | ||
2014 | /* Default options */ | |
2015 | ||
2016 | /* Domain */ | |
2017 | opt_domain = LTTNG_DOMAIN_NONE; | |
2018 | ||
2019 | /* Event options */ | |
2020 | opt_enable_all = 0; | |
2021 | opt_event_type = LTTNG_EVENT_ALL; | |
2022 | opt_loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL; | |
2023 | opt_event_list = NULL; | |
2024 | opt_loglevel = NULL; | |
2025 | opt_probe = NULL; | |
2026 | opt_function = NULL; | |
2027 | opt_channel_name = NULL; | |
2028 | opt_filter = NULL; | |
2029 | opt_exclude = NULL; | |
2030 | ||
2031 | pc = poptGetContext(NULL, cur_argc, cur_argv, long_options, POPT_CONTEXT_KEEP_FIRST); | |
2032 | poptReadDefaultConfig(pc, 0); | |
2033 | ||
2034 | /* Default event type */ | |
2035 | opt_event_type = LTTNG_EVENT_ALL; | |
2036 | ||
2037 | while ((opt = poptGetNextOpt(pc)) != -1) { | |
2038 | switch (opt) { | |
2039 | case OPT_HELP: | |
2040 | SHOW_HELP(); | |
2041 | goto end; | |
2042 | case OPT_TRACEPOINT: | |
2043 | opt_event_type = LTTNG_EVENT_TRACEPOINT; | |
2044 | break; | |
2045 | case OPT_PROBE: | |
2046 | opt_event_type = LTTNG_EVENT_PROBE; | |
2047 | break; | |
2048 | case OPT_FUNCTION: | |
2049 | opt_event_type = LTTNG_EVENT_FUNCTION; | |
2050 | break; | |
2051 | case OPT_SYSCALL: | |
2052 | opt_event_type = LTTNG_EVENT_SYSCALL; | |
2053 | break; | |
2054 | case OPT_LOGLEVEL: | |
2055 | opt_loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE; | |
2056 | opt_loglevel = poptGetOptArg(pc); | |
2057 | break; | |
2058 | case OPT_LOGLEVEL_ONLY: | |
2059 | opt_loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE; | |
2060 | opt_loglevel = poptGetOptArg(pc); | |
2061 | break; | |
2062 | case OPT_LIST_OPTIONS: | |
2063 | list_cmd_options(stdout, long_options); | |
2064 | goto end; | |
2065 | case OPT_FILTER: | |
2066 | break; | |
2067 | case OPT_EXCLUDE: | |
2068 | break; | |
2069 | default: | |
2070 | ret = CMD_UNDEFINED; | |
2071 | goto end; | |
2072 | } | |
2073 | ||
2074 | /* Validate event type. Multiple event type are not supported. */ | |
2075 | if (event_type == -1) { | |
2076 | event_type = opt_event_type; | |
2077 | } else { | |
2078 | if (event_type != opt_event_type) { | |
2079 | ERR("Multiple event type not supported."); | |
2080 | ret = CMD_ERROR; | |
2081 | goto end; | |
2082 | } | |
2083 | } | |
2084 | } | |
2085 | ||
7b0e3fab | 2086 | tmp_config = initialize_domain_configuration(opt_domain); |
721b94fe JR |
2087 | |
2088 | opt_event_list = (char*) poptGetArg(pc); | |
7b0e3fab | 2089 | if (opt_event_list == NULL && opt_enable_all == 0 && !opt_template_path) { |
721b94fe JR |
2090 | ERR("Missing event name(s).\n"); |
2091 | ret = CMD_ERROR; | |
2092 | goto end; | |
2093 | } | |
2094 | ||
7b0e3fab JR |
2095 | /* Option check */ |
2096 | if (opt_domain == LTTNG_DOMAIN_KERNEL) { | |
2097 | if (opt_loglevel) { | |
2098 | WARN("Kernel loglevels are not supported."); | |
2099 | } | |
2100 | } | |
721b94fe | 2101 | |
7b0e3fab JR |
2102 | if (opt_exclude) { |
2103 | switch (opt_domain) { | |
2104 | case LTTNG_DOMAIN_KERNEL: | |
2105 | case LTTNG_DOMAIN_JUL: | |
2106 | case LTTNG_DOMAIN_LOG4J: | |
2107 | case LTTNG_DOMAIN_PYTHON: | |
2108 | ERR("Event name exclusions are not yet implemented for %s events", | |
2109 | get_domain_str(opt_domain)); | |
2110 | ret = CMD_ERROR; | |
2111 | goto end; | |
2112 | case LTTNG_DOMAIN_UST: | |
2113 | /* Exclusions supported */ | |
2114 | break; | |
2115 | default: | |
2116 | assert(0); | |
2117 | } | |
2118 | } | |
2119 | ||
2120 | if (opt_template_path) { | |
2121 | if (event_type != LTTNG_EVENT_ALL) { | |
2122 | WARN("Type options for events while using a template have no effect (--function,--probe,--syscall,--tracepoint)."); | |
2123 | } | |
2124 | if (opt_enable_all) { | |
2125 | WARN("The all (-a) shortcut for enabling all events while using a template have no effect."); | |
2126 | } | |
2127 | } | |
2128 | ||
2129 | tmp_config->event_type = event_type ; | |
c7dfbc0e JR |
2130 | tmp_config->enable_all = opt_enable_all; |
2131 | tmp_config->loglevel_type = opt_loglevel_type; | |
2132 | tmp_config->loglevel = opt_loglevel; | |
2133 | tmp_config->probe = opt_probe; | |
2134 | tmp_config->function = opt_function; | |
2135 | tmp_config->channel_name = opt_channel_name; | |
2136 | tmp_config->filter = opt_filter; | |
2137 | tmp_config->exclude = opt_exclude; | |
2138 | tmp_config->event_list = opt_event_list; | |
721b94fe | 2139 | |
7b0e3fab | 2140 | |
721b94fe JR |
2141 | switch(opt_domain) { |
2142 | case LTTNG_DOMAIN_KERNEL: | |
2143 | if (kernel_config) { | |
2144 | ERR("Only one -k option is permitted per command"); | |
2145 | ret = CMD_ERROR; | |
2146 | goto end; | |
2147 | } | |
2148 | kernel_config = tmp_config; | |
2149 | break; | |
2150 | case LTTNG_DOMAIN_UST: | |
2151 | if (ust_config) { | |
2152 | ERR("Only one -u option is permitted per command"); | |
2153 | ret = CMD_ERROR; | |
2154 | goto end; | |
2155 | } | |
2156 | ust_config = tmp_config; | |
2157 | break; | |
2158 | case LTTNG_DOMAIN_JUL: | |
2159 | if (jul_config) { | |
2160 | ERR("Only one -j option is permitted per command"); | |
2161 | ret = CMD_ERROR; | |
2162 | goto end; | |
2163 | } | |
2164 | jul_config = tmp_config; | |
2165 | break; | |
2166 | case LTTNG_DOMAIN_LOG4J: | |
2167 | if (log4j_config) { | |
2168 | ERR("Only one -l option is permitted per command"); | |
2169 | ret = CMD_ERROR; | |
2170 | goto end; | |
2171 | } | |
2172 | log4j_config = tmp_config; | |
2173 | break; | |
2174 | case LTTNG_DOMAIN_PYTHON: | |
2175 | if (python_config) { | |
2176 | ERR("Only one -p option is permitted per command"); | |
2177 | ret = CMD_ERROR; | |
2178 | goto end; | |
2179 | } | |
2180 | python_config = tmp_config; | |
2181 | break; | |
2182 | case LTTNG_DOMAIN_NONE: | |
2183 | default: | |
2184 | ret = CMD_ERROR; | |
c7dfbc0e JR |
2185 | goto end; |
2186 | } | |
721b94fe JR |
2187 | |
2188 | tmp_config = NULL; | |
2189 | ||
c7dfbc0e JR |
2190 | poptFreeContext(pc); |
2191 | pc = NULL; | |
721b94fe JR |
2192 | } |
2193 | ||
7b0e3fab JR |
2194 | |
2195 | if (opt_template_path) { | |
2196 | /* validate template */ | |
2197 | template = config_document_get(opt_template_path, 0); | |
2198 | if (!template) { | |
2199 | ERR("Could not load the template"); | |
2200 | ret = CMD_ERROR; | |
2201 | goto end; | |
2202 | } | |
2203 | /* TODO: validate the xml */ | |
2204 | /* Only one session, only one channel per domain */ | |
2205 | if (!kernel_config) { | |
2206 | kernel_config = initialize_domain_configuration(LTTNG_DOMAIN_KERNEL); | |
2207 | if (!kernel_config) { | |
2208 | ERR("Default initialization for kernel domain configuration"); | |
2209 | ret = CMD_ERROR; | |
2210 | goto end; | |
2211 | } | |
2212 | } | |
2213 | ||
2214 | if (!ust_config) { | |
2215 | ust_config = initialize_domain_configuration(LTTNG_DOMAIN_UST); | |
2216 | if (!ust_config) { | |
2217 | ERR("Default initialization for ust domain configuration"); | |
2218 | ret = CMD_ERROR; | |
2219 | goto end; | |
2220 | } | |
2221 | } | |
2222 | ||
2223 | if (!jul_config) { | |
2224 | jul_config = initialize_domain_configuration(LTTNG_DOMAIN_JUL); | |
2225 | if (!jul_config) { | |
2226 | ERR("Default initialization for jul domain configuration"); | |
2227 | ret = CMD_ERROR; | |
2228 | goto end; | |
2229 | } | |
2230 | } | |
2231 | ||
2232 | if (!log4j_config) { | |
2233 | log4j_config = initialize_domain_configuration(LTTNG_DOMAIN_LOG4J); | |
2234 | if (!log4j_config) { | |
2235 | ERR("Default initialization for log4j domain configuration"); | |
2236 | ret = CMD_ERROR; | |
2237 | goto end; | |
2238 | } | |
2239 | } | |
2240 | ||
2241 | if (!python_config) { | |
2242 | python_config = initialize_domain_configuration(LTTNG_DOMAIN_PYTHON); | |
2243 | if (!python_config) { | |
2244 | ERR("Default initialization for python domain configuration"); | |
2245 | ret = CMD_ERROR; | |
2246 | goto end; | |
2247 | } | |
2248 | } | |
2249 | ||
2250 | command_ret = enable_event_from_template(template, session_name, kernel_config, ust_config, | |
2251 | jul_config, log4j_config, python_config); | |
2252 | ||
2253 | goto end; | |
2254 | } | |
2255 | ||
c7dfbc0e JR |
2256 | if (kernel_config) { |
2257 | command_ret = enable_events(session_name, kernel_config); | |
721b94fe JR |
2258 | if (command_ret) { |
2259 | success = 0; | |
2260 | } | |
c7dfbc0e JR |
2261 | } |
2262 | ||
2263 | if (ust_config) { | |
2264 | command_ret = enable_events(session_name, ust_config); | |
2265 | if (command_ret) { | |
2266 | success = 0; | |
2267 | } | |
2268 | } | |
2269 | ||
2270 | if (jul_config) { | |
2271 | command_ret = enable_events(session_name, jul_config); | |
2272 | if (command_ret) { | |
2273 | success = 0; | |
2274 | } | |
2275 | } | |
2276 | ||
2277 | if (log4j_config) { | |
2278 | command_ret = enable_events(session_name, log4j_config); | |
2279 | if (command_ret) { | |
2280 | success = 0; | |
2281 | } | |
2282 | } | |
2283 | ||
2284 | if (python_config) { | |
2285 | command_ret = enable_events(session_name, python_config); | |
2286 | if (command_ret) { | |
2287 | success = 0; | |
2288 | } | |
2289 | } | |
721b94fe | 2290 | |
89476427 JRJ |
2291 | mi_closing: |
2292 | /* Mi closing */ | |
2293 | if (lttng_opt_mi) { | |
c7dfbc0e JR |
2294 | /* Close domains and output element */ |
2295 | ret = mi_lttng_close_multi_element(writer, 2); | |
89476427 JRJ |
2296 | if (ret) { |
2297 | ret = CMD_ERROR; | |
2298 | goto end; | |
2299 | } | |
2300 | ||
2301 | ret = mi_lttng_writer_write_element_bool(writer, | |
2302 | mi_lttng_element_command_success, success); | |
2303 | if (ret) { | |
2304 | ret = CMD_ERROR; | |
2305 | goto end; | |
2306 | } | |
2307 | ||
2308 | /* Command element close */ | |
2309 | ret = mi_lttng_writer_command_close(writer); | |
2310 | if (ret) { | |
2311 | ret = CMD_ERROR; | |
2312 | goto end; | |
2313 | } | |
2314 | } | |
f3ed775e DG |
2315 | |
2316 | end: | |
89476427 JRJ |
2317 | /* Mi clean-up */ |
2318 | if (writer && mi_lttng_writer_destroy(writer)) { | |
2319 | /* Preserve original error code */ | |
2320 | ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL; | |
2321 | } | |
2322 | ||
cd80958d DG |
2323 | if (opt_session_name == NULL) { |
2324 | free(session_name); | |
2325 | } | |
2326 | ||
89476427 JRJ |
2327 | /* Overwrite ret if an error occurred in enable_events */ |
2328 | ret = command_ret ? command_ret : ret; | |
2329 | ||
7b0e3fab | 2330 | config_document_free(template); |
c7dfbc0e | 2331 | free(args_tuple_list); |
7b0e3fab | 2332 | free(tmp_config); |
721b94fe | 2333 | free(jul_config); |
c7dfbc0e | 2334 | free(kernel_config); |
721b94fe JR |
2335 | free(log4j_config); |
2336 | free(python_config); | |
c7dfbc0e | 2337 | free(ust_config); |
ca1c3607 | 2338 | poptFreeContext(pc); |
f3ed775e DG |
2339 | return ret; |
2340 | } |