SoW-2020-0003: Trace Hit Counters
[lttng-tools.git] / src / bin / lttng / commands / add_trigger.c
CommitLineData
4624dad0
SM
1/*
2 * Copyright (C) 2021 Simon Marchi <simon.marchi@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8#include <ctype.h>
9#include <stdio.h>
10
11#include "../command.h"
12#include "../loglevel.h"
13#include "../uprobe.h"
14
15#include "common/argpar/argpar.h"
16#include "common/dynamic-array.h"
17#include "common/string-utils/string-utils.h"
18#include "common/utils.h"
19/* For lttng_event_rule_type_str(). */
20#include <lttng/event-rule/event-rule-internal.h>
21#include <lttng/lttng.h>
ebdb334b
JR
22#include "lttng/event-rule/kernel-function.h"
23#include "lttng/event-rule/kernel-probe.h"
24#include "lttng/event-rule/syscall.h"
25#include <lttng/event-rule/tracepoint.h>
26#include "lttng/event-rule/userspace-probe.h"
27#include "lttng/kernel-function.h"
28#include "lttng/kernel-probe.h"
29#include "lttng/log-level-rule.h"
30#include "lttng/map-key-internal.h"
20a01d15
SM
31#include "common/filter/filter-ast.h"
32#include "common/filter/filter-ir.h"
33#include "common/dynamic-array.h"
4624dad0
SM
34
35#if (LTTNG_SYMBOL_NAME_LEN == 256)
36#define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "255"
37#endif
38
39#ifdef LTTNG_EMBED_HELP
40static const char help_msg[] =
41#include <lttng-add-trigger.1.h>
42;
43#endif
44
45enum {
46 OPT_HELP,
47 OPT_LIST_OPTIONS,
48
49 OPT_CONDITION,
50 OPT_ACTION,
51 OPT_ID,
52 OPT_FIRE_ONCE_AFTER,
53 OPT_FIRE_EVERY,
54 OPT_USER_ID,
55
56 OPT_ALL,
57 OPT_FILTER,
58 OPT_EXCLUDE,
59 OPT_LOGLEVEL,
60 OPT_LOGLEVEL_ONLY,
61
62 OPT_USERSPACE,
63 OPT_KERNEL,
64 OPT_LOG4J,
65 OPT_JUL,
66 OPT_PYTHON,
67
68 OPT_FUNCTION,
69 OPT_PROBE,
70 OPT_USERSPACE_PROBE,
71 OPT_SYSCALL,
72 OPT_TRACEPOINT,
73
74 OPT_NAME,
75 OPT_MAX_SIZE,
76 OPT_DATA_URL,
77 OPT_CTRL_URL,
78 OPT_URL,
79 OPT_PATH,
20a01d15 80
ebdb334b
JR
81 OPT_SESSION_NAME,
82 OPT_MAP_NAME,
83 OPT_KEY,
84
20a01d15 85 OPT_CAPTURE,
4624dad0
SM
86};
87
88static const struct argpar_opt_descr event_rule_opt_descrs[] = {
89 { OPT_ALL, 'a', "all", false },
90 { OPT_FILTER, 'f', "filter", true },
91 { OPT_EXCLUDE, 'x', "exclude", true },
92 { OPT_LOGLEVEL, '\0', "loglevel", true },
93 { OPT_LOGLEVEL_ONLY, '\0', "loglevel-only", true },
94
95 /* Domains */
96 { OPT_USERSPACE, 'u', "userspace", false },
97 { OPT_KERNEL, 'k', "kernel", false },
98 { OPT_LOG4J, 'l', "log4j", false },
99 { OPT_JUL, 'j', "jul", false },
100 { OPT_PYTHON, 'p', "python", false },
101
102 /* Event rule types */
103 { OPT_FUNCTION, '\0', "function", true },
104 { OPT_PROBE, '\0', "probe", true },
105 { OPT_USERSPACE_PROBE, '\0', "userspace-probe", true },
106 { OPT_SYSCALL, '\0', "syscall" },
107 { OPT_TRACEPOINT, '\0', "tracepoint" },
108
20a01d15
SM
109 /* Capture descriptor */
110 { OPT_CAPTURE, '\0', "capture", true },
111
4624dad0
SM
112 ARGPAR_OPT_DESCR_SENTINEL
113};
114
115static
116bool assign_domain_type(enum lttng_domain_type *dest,
117 enum lttng_domain_type src)
118{
119 bool ret;
120
121 if (*dest == LTTNG_DOMAIN_NONE || *dest == src) {
122 *dest = src;
123 ret = true;
124 } else {
125 ERR("Multiple domains specified.");
126 ret = false;
127 }
128
129 return ret;
130}
131
132static
133bool assign_event_rule_type(enum lttng_event_rule_type *dest,
134 enum lttng_event_rule_type src)
135{
136 bool ret;
137
138 if (*dest == LTTNG_EVENT_RULE_TYPE_UNKNOWN || *dest == src) {
139 *dest = src;
140 ret = true;
141 } else {
142 ERR("Multiple event types specified.");
143 ret = false;
144 }
145
146 return ret;
147}
148
149static
150bool assign_string(char **dest, const char *src, const char *opt_name)
151{
152 bool ret;
153
154 if (*dest) {
155 ERR("Duplicate '%s' given.", opt_name);
156 goto error;
157 }
158
159 *dest = strdup(src);
160 if (!*dest) {
161 PERROR("Failed to allocate string '%s'.", opt_name);
162 goto error;
163 }
164
165 ret = true;
166 goto end;
167
168error:
169 ret = false;
170
171end:
172 return ret;
173}
174
175/* This is defined in enable_events.c. */
176LTTNG_HIDDEN
177int create_exclusion_list_and_validate(const char *event_name,
178 const char *exclusions_arg,
179 char ***exclusion_list);
180
181/*
182 * Parse `str` as a log level in domain `domain_type`. Return -1 if the string
183 * is not recognized as a valid log level.
184 */
185static
186int parse_loglevel_string(const char *str, enum lttng_domain_type domain_type)
187{
188 switch (domain_type) {
189 case LTTNG_DOMAIN_UST:
190 {
191 enum lttng_loglevel loglevel;
192 const int ret = loglevel_name_to_value(str, &loglevel);
193
194 return ret == -1 ? ret : (int) loglevel;
195 }
196 case LTTNG_DOMAIN_LOG4J:
197 {
198 enum lttng_loglevel_log4j loglevel;
199 const int ret = loglevel_log4j_name_to_value(str, &loglevel);
200
201 return ret == -1 ? ret : (int) loglevel;
202 }
203 case LTTNG_DOMAIN_JUL:
204 {
205 enum lttng_loglevel_jul loglevel;
206 const int ret = loglevel_jul_name_to_value(str, &loglevel);
207
208 return ret == -1 ? ret : (int) loglevel;
209 }
210 case LTTNG_DOMAIN_PYTHON:
211 {
212 enum lttng_loglevel_python loglevel;
213 const int ret = loglevel_python_name_to_value(str, &loglevel);
214
215 return ret == -1 ? ret : (int) loglevel;
216 }
217 default:
218 /* Invalid domain type. */
219 abort();
220 }
221}
222
223static int parse_kernel_probe_opts(const char *source,
224 struct lttng_kernel_probe_location **location)
225{
226 int ret = 0;
227 int match;
228 char s_hex[19];
229 char name[LTTNG_SYMBOL_NAME_LEN];
230 char *symbol_name = NULL;
231 uint64_t offset;
232
233 /* Check for symbol+offset. */
234 match = sscanf(source,
235 "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
236 "[^'+']+%18s",
237 name, s_hex);
238 if (match == 2) {
239 if (*s_hex == '\0') {
240 ERR("Kernel probe symbol offset is missing.");
241 goto error;
242 }
243
244 symbol_name = strndup(name, LTTNG_SYMBOL_NAME_LEN);
245 if (!symbol_name) {
246 PERROR("Failed to copy kernel probe location symbol name.");
247 goto error;
248 }
249 offset = strtoul(s_hex, NULL, 0);
250
251 *location = lttng_kernel_probe_location_symbol_create(
252 symbol_name, offset);
f6e30a8a 253 if (!*location) {
4624dad0
SM
254 ERR("Failed to create symbol kernel probe location.");
255 goto error;
256 }
257
258 goto end;
259 }
260
261 /* Check for symbol. */
262 if (isalpha(name[0]) || name[0] == '_') {
263 match = sscanf(source,
264 "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
265 "s",
266 name);
267 if (match == 1) {
268 symbol_name = strndup(name, LTTNG_SYMBOL_NAME_LEN);
269 if (!symbol_name) {
270 ERR("Failed to copy kernel probe location symbol name.");
271 goto error;
272 }
273
274 *location = lttng_kernel_probe_location_symbol_create(
275 symbol_name, 0);
14f27f79 276 if (!*location) {
4624dad0
SM
277 ERR("Failed to create symbol kernel probe location.");
278 goto error;
279 }
280
281 goto end;
282 }
283 }
284
285 /* Check for address. */
286 match = sscanf(source, "%18s", s_hex);
287 if (match > 0) {
288 uint64_t address;
289
290 if (*s_hex == '\0') {
291 ERR("Invalid kernel probe location address.");
292 goto error;
293 }
294
295 address = strtoul(s_hex, NULL, 0);
296 *location = lttng_kernel_probe_location_address_create(address);
5c6ca809 297 if (!*location) {
4624dad0
SM
298 ERR("Failed to create symbol kernel probe location.");
299 goto error;
300 }
301
302 goto end;
303 }
304
305error:
306 /* No match */
307 ret = -1;
308 *location = NULL;
309
310end:
311 free(symbol_name);
312 return ret;
313}
314
ebdb334b
JR
315static int parse_kernel_function_opts(const char *source,
316 struct lttng_kernel_function_location **location)
317{
318 int ret = 0;
319 int match;
320 char s_hex[19];
321 char name[LTTNG_SYMBOL_NAME_LEN];
322 char *symbol_name = NULL;
323 uint64_t offset;
324
325 /* Check for symbol+offset. */
326 match = sscanf(source,
327 "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
328 "[^'+']+%18s",
329 name, s_hex);
330 if (match == 2) {
331 if (*s_hex == '\0') {
332 ERR("Kernel function symbol offset is missing.");
333 goto error;
334 }
335
336 symbol_name = strndup(name, LTTNG_SYMBOL_NAME_LEN);
337 if (!symbol_name) {
338 PERROR("Failed to copy kernel function location symbol name.");
339 goto error;
340 }
341 offset = strtoul(s_hex, NULL, 0);
342
343 *location = lttng_kernel_function_location_symbol_create(
344 symbol_name, offset);
345 if (!*location) {
346 ERR("Failed to create symbol kernel function location.");
347 goto error;
348 }
349
350 goto end;
351 }
352
353 /* Check for symbol. */
354 if (isalpha(name[0]) || name[0] == '_') {
355 match = sscanf(source,
356 "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
357 "s",
358 name);
359 if (match == 1) {
360 symbol_name = strndup(name, LTTNG_SYMBOL_NAME_LEN);
361 if (!symbol_name) {
362 ERR("Failed to copy kernel function location symbol name.");
363 goto error;
364 }
365
366 *location = lttng_kernel_function_location_symbol_create(
367 symbol_name, 0);
368 if (!*location) {
369 ERR("Failed to create symbol kernel function location.");
370 goto error;
371 }
372
373 goto end;
374 }
375 }
376
377 /* Check for address. */
378 match = sscanf(source, "%18s", s_hex);
379 if (match > 0) {
380 uint64_t address;
381
382 if (*s_hex == '\0') {
383 ERR("Invalid kernel function location address.");
384 goto error;
385 }
386
387 address = strtoul(s_hex, NULL, 0);
388 *location = lttng_kernel_function_location_address_create(address);
389 if (!*location) {
390 ERR("Failed to create symbol kernel function location.");
391 goto error;
392 }
393
394 goto end;
395 }
396
397error:
398 /* No match */
399 ret = -1;
400 *location = NULL;
401
402end:
403 free(symbol_name);
404 return ret;
405}
406
20a01d15
SM
407static
408struct lttng_event_expr *ir_op_load_expr_to_event_expr(
3363a4c3
JG
409 const struct ir_load_expression *load_expr,
410 const char *capture_str)
20a01d15
SM
411{
412 char *provider_name = NULL;
413 struct lttng_event_expr *event_expr = NULL;
3363a4c3
JG
414 const struct ir_load_expression_op *load_expr_op = load_expr->child;
415 const enum ir_load_expression_type load_expr_child_type =
416 load_expr_op->type;
20a01d15 417
3363a4c3 418 switch (load_expr_child_type) {
20a01d15
SM
419 case IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT:
420 case IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT:
421 {
422 const char *field_name;
423
424 load_expr_op = load_expr_op->next;
425 assert(load_expr_op);
426 assert(load_expr_op->type == IR_LOAD_EXPRESSION_GET_SYMBOL);
427 field_name = load_expr_op->u.symbol;
428 assert(field_name);
429
3363a4c3 430 event_expr = load_expr_child_type == IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT ?
20a01d15
SM
431 lttng_event_expr_event_payload_field_create(field_name) :
432 lttng_event_expr_channel_context_field_create(field_name);
433 if (!event_expr) {
434 ERR("Failed to create %s event expression: field name = `%s`.",
3363a4c3 435 load_expr_child_type == IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT ?
20a01d15
SM
436 "payload field" : "channel context",
437 field_name);
438 goto error;
439 }
440
441 break;
442 }
443 case IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT:
444 {
445 const char *colon;
446 const char *type_name;
447 const char *field_name;
448
449 load_expr_op = load_expr_op->next;
450 assert(load_expr_op);
451 assert(load_expr_op->type == IR_LOAD_EXPRESSION_GET_SYMBOL);
452 field_name = load_expr_op->u.symbol;
453 assert(field_name);
454
455 /*
456 * The field name needs to be of the form PROVIDER:TYPE. We
457 * split it here.
458 */
459 colon = strchr(field_name, ':');
460 if (!colon) {
461 ERR("Invalid app-specific context field name: missing colon in `%s`.",
462 field_name);
463 goto error;
464 }
465
466 type_name = colon + 1;
467 if (*type_name == '\0') {
468 ERR("Invalid app-specific context field name: missing type name after colon in `%s`.",
469 field_name);
470 goto error;
471 }
472
473 provider_name = strndup(field_name, colon - field_name);
474 if (!provider_name) {
475 PERROR("Failed to allocate field name string");
476 goto error;
477 }
478
479 event_expr = lttng_event_expr_app_specific_context_field_create(
480 provider_name, type_name);
481 if (!event_expr) {
482 ERR("Failed to create app-specific context field event expression: provider name = `%s`, type name = `%s`",
483 provider_name, type_name);
484 goto error;
485 }
486
487 break;
488 }
489 default:
490 ERR("%s: unexpected load expr type %d.", __func__,
491 load_expr_op->type);
492 abort();
493 }
494
495 load_expr_op = load_expr_op->next;
496
497 /* There may be a single array index after that. */
498 if (load_expr_op->type == IR_LOAD_EXPRESSION_GET_INDEX) {
499 struct lttng_event_expr *index_event_expr;
500 const uint64_t index = load_expr_op->u.index;
501
502 index_event_expr = lttng_event_expr_array_field_element_create(event_expr, index);
503 if (!index_event_expr) {
504 ERR("Failed to create array field element event expression.");
505 goto error;
506 }
507
508 event_expr = index_event_expr;
509 load_expr_op = load_expr_op->next;
510 }
511
512 switch (load_expr_op->type) {
513 case IR_LOAD_EXPRESSION_LOAD_FIELD:
514 /*
515 * This is what we expect, IR_LOAD_EXPRESSION_LOAD_FIELD is
516 * always found at the end of the chain.
517 */
518 break;
519 case IR_LOAD_EXPRESSION_GET_SYMBOL:
520 ERR("While parsing expression `%s`: Capturing subfields is not supported.",
521 capture_str);
522 goto error;
523
524 default:
525 ERR("%s: unexpected load expression operator %s.", __func__,
526 ir_load_expression_type_str(load_expr_op->type));
527 abort();
528 }
529
530 goto end;
531
532error:
533 lttng_event_expr_destroy(event_expr);
534 event_expr = NULL;
535
536end:
537 free(provider_name);
538
539 return event_expr;
540}
541
542static
543struct lttng_event_expr *ir_op_load_to_event_expr(
544 const struct ir_op *ir, const char *capture_str)
545{
546 struct lttng_event_expr *event_expr = NULL;
547
548 assert(ir->op == IR_OP_LOAD);
549
550 switch (ir->data_type) {
551 case IR_DATA_EXPRESSION:
552 {
553 const struct ir_load_expression *ir_load_expr =
554 ir->u.load.u.expression;
555
556 event_expr = ir_op_load_expr_to_event_expr(
557 ir_load_expr, capture_str);
558 break;
559 }
560 default:
561 ERR("%s: unexpected data type: %s.", __func__,
562 ir_data_type_str(ir->data_type));
563 abort();
564 }
565
566 return event_expr;
567}
568
569static
570const char *ir_operator_type_human_str(enum ir_op_type op)
571{
572 const char *name;
573
574 switch (op) {
575 case IR_OP_BINARY:
576 name = "Binary";
577 break;
578 case IR_OP_UNARY:
579 name = "Unary";
580 break;
581 case IR_OP_LOGICAL:
582 name = "Logical";
583 break;
584 default:
585 abort();
586 }
587
588 return name;
589}
590
591static
592struct lttng_event_expr *ir_op_root_to_event_expr(const struct ir_op *ir,
593 const char *capture_str)
594{
595 struct lttng_event_expr *event_expr = NULL;
596
597 assert(ir->op == IR_OP_ROOT);
598 ir = ir->u.root.child;
599
600 switch (ir->op) {
601 case IR_OP_LOAD:
602 event_expr = ir_op_load_to_event_expr(ir, capture_str);
603 break;
604 case IR_OP_BINARY:
605 case IR_OP_UNARY:
606 case IR_OP_LOGICAL:
607 ERR("While parsing expression `%s`: %s operators are not allowed in capture expressions.",
608 capture_str,
609 ir_operator_type_human_str(ir->op));
610 break;
611 default:
612 ERR("%s: unexpected IR op type: %s.", __func__,
613 ir_op_type_str(ir->op));
614 abort();
615 }
616
617 return event_expr;
618}
619
620static
621void destroy_event_expr(void *ptr)
622{
623 lttng_event_expr_destroy(ptr);
624}
625
626struct parse_event_rule_res {
627 /* Owned by this. */
628 struct lttng_event_rule *er;
629
630 /* Array of `struct lttng_event_expr *` */
631 struct lttng_dynamic_pointer_array capture_descriptors;
632};
633
634static
635struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv)
4624dad0 636{
4624dad0
SM
637 enum lttng_domain_type domain_type = LTTNG_DOMAIN_NONE;
638 enum lttng_event_rule_type event_rule_type =
639 LTTNG_EVENT_RULE_TYPE_UNKNOWN;
640 struct argpar_state *state;
641 struct argpar_item *item = NULL;
642 char *error = NULL;
643 int consumed_args = -1;
644 struct lttng_kernel_probe_location *kernel_probe_location = NULL;
ebdb334b 645 struct lttng_kernel_function_location *kernel_function_location = NULL;
4624dad0 646 struct lttng_userspace_probe_location *userspace_probe_location = NULL;
20a01d15
SM
647 struct parse_event_rule_res res = { 0 };
648 struct lttng_event_expr *event_expr = NULL;
649 struct filter_parser_ctx *parser_ctx = NULL;
ebdb334b 650 struct lttng_log_level_rule *log_level_rule = NULL;
4624dad0
SM
651
652 /* Was the -a/--all flag provided? */
653 bool all_events = false;
654
655 /* Tracepoint name (non-option argument). */
656 const char *tracepoint_name = NULL;
657
658 /* Holds the argument of --probe / --userspace-probe. */
659 char *source = NULL;
660
661 /* Filter. */
662 char *filter = NULL;
663
664 /* Exclude. */
665 char *exclude = NULL;
666 char **exclusion_list = NULL;
667
668 /* Log level. */
669 char *loglevel_str = NULL;
670 bool loglevel_only = false;
671
20a01d15
SM
672 lttng_dynamic_pointer_array_init(&res.capture_descriptors,
673 destroy_event_expr);
4624dad0
SM
674 state = argpar_state_create(*argc, *argv, event_rule_opt_descrs);
675 if (!state) {
676 ERR("Failed to allocate an argpar state.");
677 goto error;
678 }
679
680 while (true) {
681 enum argpar_state_parse_next_status status;
682
683 ARGPAR_ITEM_DESTROY_AND_RESET(item);
684 status = argpar_state_parse_next(state, &item, &error);
685 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
686 ERR("%s", error);
687 goto error;
688 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
689 /* Just stop parsing here. */
690 break;
691 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
692 break;
693 }
694
695 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
696
697 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
698 const struct argpar_item_opt *item_opt =
699 (const struct argpar_item_opt *) item;
700
701 switch (item_opt->descr->id) {
702 /* Domains. */
703 case OPT_USERSPACE:
704 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_UST)) {
705 goto error;
706 }
707
708 break;
709 case OPT_KERNEL:
710 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_KERNEL)) {
711 goto error;
712 }
713
714 break;
715 case OPT_LOG4J:
716 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_LOG4J)) {
717 goto error;
718 }
719
720 break;
721 case OPT_JUL:
722 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_JUL)) {
723 goto error;
724 }
725
726 break;
727 case OPT_PYTHON:
728 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_PYTHON)) {
729 goto error;
730 }
731
732 break;
733
734 /* Event rule types */
735 case OPT_FUNCTION:
736 if (!assign_event_rule_type(&event_rule_type,
ebdb334b
JR
737 LTTNG_EVENT_RULE_TYPE_KERNEL_FUNCTION)) {
738 goto error;
739 }
740
741 if (!assign_string(&source, item_opt->arg, "source")) {
4624dad0
SM
742 goto error;
743 }
744
745 break;
746 case OPT_PROBE:
747 if (!assign_event_rule_type(&event_rule_type,
ebdb334b 748 LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE)) {
4624dad0
SM
749 goto error;
750 }
751
752 if (!assign_string(&source, item_opt->arg, "source")) {
753 goto error;
754 }
755
756 break;
757 case OPT_USERSPACE_PROBE:
758 if (!assign_event_rule_type(&event_rule_type,
ebdb334b 759 LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE)) {
4624dad0
SM
760 goto error;
761 }
762
763 if (!assign_string(&source, item_opt->arg, "source")) {
764 goto error;
765 }
766
767 break;
768 case OPT_SYSCALL:
769 if (!assign_event_rule_type(&event_rule_type,
770 LTTNG_EVENT_RULE_TYPE_SYSCALL)) {
771 goto error;
772 }
773
774 break;
775 case OPT_TRACEPOINT:
776 if (!assign_event_rule_type(&event_rule_type,
777 LTTNG_EVENT_RULE_TYPE_TRACEPOINT)) {
778 goto error;
779 }
780
781 break;
782 case OPT_ALL:
783 all_events = true;
784 break;
785 case OPT_FILTER:
786 if (!assign_string(&filter, item_opt->arg,
787 "--filter/-f")) {
788 goto error;
789 }
790
791 break;
792 case OPT_EXCLUDE:
793 if (!assign_string(&exclude, item_opt->arg,
794 "--exclude/-x")) {
795 goto error;
796 }
797
798 break;
799 case OPT_LOGLEVEL:
800 case OPT_LOGLEVEL_ONLY:
801 if (!assign_string(&loglevel_str, item_opt->arg,
802 "--loglevel/--loglevel-only")) {
803 goto error;
804 }
805
806 loglevel_only = item_opt->descr->id ==
807 OPT_LOGLEVEL_ONLY;
808 break;
20a01d15
SM
809 case OPT_CAPTURE:
810 {
811 int ret;
812 const char *capture_str = item_opt->arg;
813
814 ret = filter_parser_ctx_create_from_filter_expression(
815 capture_str, &parser_ctx);
816 if (ret) {
817 ERR("Failed to parse capture expression `%s`.",
818 capture_str);
819 goto error;
820 }
821
822 event_expr = ir_op_root_to_event_expr(
823 parser_ctx->ir_root,
824 capture_str);
825 if (!event_expr) {
826 /*
827 * ir_op_root_to_event_expr has printed
828 * an error message.
829 */
830 goto error;
831 }
832
833 ret = lttng_dynamic_pointer_array_add_pointer(
834 &res.capture_descriptors,
835 event_expr);
836 if (ret) {
837 goto error;
838 }
839
840 /*
841 * The ownership of event expression was
842 * transferred to the dynamic array.
843 */
844 event_expr = NULL;
845
846 break;
847 }
4624dad0
SM
848 default:
849 abort();
850 }
851 } else {
852 const struct argpar_item_non_opt *item_non_opt =
853 (const struct argpar_item_non_opt *)
854 item;
855
856 /*
857 * Don't accept two non-option arguments/tracepoint
858 * names.
859 */
860 if (tracepoint_name) {
861 ERR("Unexpected argument '%s'",
862 item_non_opt->arg);
863 goto error;
864 }
865
866 tracepoint_name = item_non_opt->arg;
867 }
868 }
869
870 if (event_rule_type == LTTNG_EVENT_RULE_TYPE_UNKNOWN) {
871 event_rule_type = LTTNG_EVENT_RULE_TYPE_TRACEPOINT;
872 }
873
874 /*
875 * Option -a is applicable to event rules of type tracepoint and
876 * syscall, and it is equivalent to using "*" as the tracepoint name.
877 */
878 if (all_events) {
879 switch (event_rule_type) {
880 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
881 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
882 break;
883 default:
884 ERR("Can't use -a/--all with %s event rules.",
885 lttng_event_rule_type_str(event_rule_type));
886 goto error;
887 }
888
889 if (tracepoint_name) {
890 ERR("Can't provide a tracepoint name with -a/--all.");
891 goto error;
892 }
893
894 /* In which case, it's equivalent to tracepoint name "*". */
895 tracepoint_name = "*";
896 }
897
898 /*
899 * A tracepoint name (or -a, for the event rule types that accept it)
900 * is required.
901 */
902 if (!tracepoint_name) {
903 ERR("Need to provide either a tracepoint name or -a/--all.");
904 goto error;
905 }
906
907 /*
908 * We don't support multiple tracepoint names for now.
909 */
910 if (strchr(tracepoint_name, ',')) {
911 ERR("Comma separated tracepoint names are not supported.");
912 goto error;
913 }
914
915 /*
916 * Update *argc and *argv so our caller can keep parsing what follows.
917 */
918 consumed_args = argpar_state_get_ingested_orig_args(state);
919 assert(consumed_args >= 0);
920 *argc -= consumed_args;
921 *argv += consumed_args;
922
923 /* Need to specify a domain. */
924 if (domain_type == LTTNG_DOMAIN_NONE) {
925 ERR("Please specify a domain (--kernel/--userspace/--jul/--log4j/--python).");
926 goto error;
927 }
928
929 /* Validate event rule type against domain. */
930 switch (event_rule_type) {
ebdb334b
JR
931 case LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE:
932 case LTTNG_EVENT_RULE_TYPE_KERNEL_FUNCTION:
933 case LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE:
4624dad0
SM
934 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
935 if (domain_type != LTTNG_DOMAIN_KERNEL) {
936 ERR("Event type not available for user-space tracing.");
937 goto error;
938 }
939 break;
940
941 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
942 break;
943
944 default:
945 abort();
946 }
947
948 /*
949 * Adding a filter to a probe, function or userspace-probe would be
950 * denied by the kernel tracer as it's not supported at the moment. We
951 * do an early check here to warn the user.
952 */
953 if (filter && domain_type == LTTNG_DOMAIN_KERNEL) {
954 switch (event_rule_type) {
955 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
956 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
957 break;
958 default:
959 ERR("Filter expressions are not supported for %s event rules.",
960 lttng_event_rule_type_str(event_rule_type));
961 goto error;
962 }
963 }
964
965 /* If --exclude/-x was passed, split it into an exclusion list. */
966 if (exclude) {
967 if (domain_type != LTTNG_DOMAIN_UST) {
968 ERR("Event name exclusions are not yet implemented for %s event rules.",
969 get_domain_str(domain_type));
970 goto error;
971 }
972
973
974 if (create_exclusion_list_and_validate(tracepoint_name, exclude,
975 &exclusion_list) != 0) {
976 ERR("Failed to create exclusion list.");
977 goto error;
978 }
979 }
980
981 if (loglevel_str && event_rule_type != LTTNG_EVENT_RULE_TYPE_TRACEPOINT) {
982 ERR("Log levels are only applicable to tracepoint event rules.");
983 goto error;
984 }
985
986 /* Finally, create the event rule object. */
987 switch (event_rule_type) {
988 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
989 {
990 enum lttng_event_rule_status event_rule_status;
991
20a01d15
SM
992 res.er = lttng_event_rule_tracepoint_create(domain_type);
993 if (!res.er) {
4624dad0
SM
994 ERR("Failed to create tracepoint event rule.");
995 goto error;
996 }
997
998 /* Set pattern. */
999 event_rule_status = lttng_event_rule_tracepoint_set_pattern(
20a01d15 1000 res.er, tracepoint_name);
4624dad0
SM
1001 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1002 ERR("Failed to set tracepoint event rule's pattern to '%s'.",
1003 tracepoint_name);
1004 goto error;
1005 }
1006
1007 /* Set filter. */
1008 if (filter) {
1009 event_rule_status = lttng_event_rule_tracepoint_set_filter(
20a01d15 1010 res.er, filter);
4624dad0
SM
1011 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1012 ERR("Failed to set tracepoint event rule's filter to '%s'.",
1013 filter);
1014 goto error;
1015 }
1016 }
1017
1018 /* Set exclusion list. */
1019 if (exclusion_list) {
1020 int n;
1021
1022 for (n = 0; exclusion_list[n]; n++) {
1023 event_rule_status = lttng_event_rule_tracepoint_add_exclusion(
20a01d15 1024 res.er,
4624dad0
SM
1025 exclusion_list[n]);
1026 if (event_rule_status !=
1027 LTTNG_EVENT_RULE_STATUS_OK) {
1028 ERR("Failed to set tracepoint exclusion list element '%s'",
1029 exclusion_list[n]);
1030 goto error;
1031 }
1032 }
1033 }
1034
1035 if (loglevel_str) {
1036 int loglevel;
1037
1038 if (domain_type == LTTNG_DOMAIN_KERNEL) {
1039 ERR("Log levels are not supported by the kernel tracer.");
1040 goto error;
1041 }
1042
1043 loglevel = parse_loglevel_string(
1044 loglevel_str, domain_type);
1045 if (loglevel < 0) {
1046 ERR("Failed to parse `%s` as a log level.",
1047 loglevel_str);
1048 goto error;
1049 }
1050
1051 if (loglevel_only) {
ebdb334b 1052 log_level_rule = lttng_log_level_rule_exactly_create(loglevel);
4624dad0 1053 } else {
ebdb334b
JR
1054 log_level_rule = lttng_log_level_rule_at_least_as_severe_as_create(loglevel);
1055 }
1056
1057 if (log_level_rule == NULL) {
1058 ERR("Failed to create log level rule object.");
1059 goto error;
4624dad0
SM
1060 }
1061
ebdb334b
JR
1062 event_rule_status =
1063 lttng_event_rule_tracepoint_set_log_level_rule(
1064 res.er, log_level_rule);
1065
4624dad0
SM
1066 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1067 ERR("Failed to set log level on event fule.");
1068 goto error;
1069 }
1070 }
1071
1072 break;
1073 }
ebdb334b 1074 case LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE:
4624dad0
SM
1075 {
1076 int ret;
1077 enum lttng_event_rule_status event_rule_status;
1078
4624dad0
SM
1079
1080 ret = parse_kernel_probe_opts(source, &kernel_probe_location);
1081 if (ret) {
1082 ERR("Failed to parse kernel probe location.");
1083 goto error;
1084 }
1085
ebdb334b
JR
1086 assert(kernel_probe_location);
1087 res.er = lttng_event_rule_kernel_probe_create(kernel_probe_location);
1088 if (!res.er) {
1089 ERR("Failed to create kprobe event rule.");
1090 goto error;
1091 }
1092
1093 event_rule_status = lttng_event_rule_kernel_probe_set_event_name(res.er, tracepoint_name);
4624dad0
SM
1094 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1095 ERR("Failed to set kprobe event rule's name to '%s'.", tracepoint_name);
1096 goto error;
1097 }
1098
ebdb334b
JR
1099 break;
1100 }
1101 case LTTNG_EVENT_RULE_TYPE_KERNEL_FUNCTION:
1102 {
1103 int ret;
1104 enum lttng_event_rule_status event_rule_status;
1105
1106
1107 ret = parse_kernel_function_opts(source, &kernel_function_location);
1108 if (ret) {
1109 ERR("Failed to parse kernel function location.");
1110 goto error;
1111 }
1112
1113 assert(kernel_function_location);
1114 res.er = lttng_event_rule_kernel_function_create(kernel_function_location);
1115 if (!res.er) {
1116 ERR("Failed to create kfunction event rule.");
1117 goto error;
1118 }
1119
1120 event_rule_status = lttng_event_rule_kernel_function_set_event_name(res.er, tracepoint_name);
4624dad0 1121 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
ebdb334b 1122 ERR("Failed to set kfunction event rule's name to '%s'.", tracepoint_name);
4624dad0
SM
1123 goto error;
1124 }
1125
1126 break;
1127 }
ebdb334b 1128 case LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE:
4624dad0
SM
1129 {
1130 int ret;
1131 enum lttng_event_rule_status event_rule_status;
1132
1133 ret = parse_userspace_probe_opts(
1134 source, &userspace_probe_location);
1135 if (ret) {
1136 ERR("Failed to parse user space probe location.");
1137 goto error;
1138 }
1139
ebdb334b 1140 res.er = lttng_event_rule_userspace_probe_create(userspace_probe_location);
20a01d15
SM
1141 if (!res.er) {
1142 ERR("Failed to create userspace probe event rule.");
4624dad0
SM
1143 goto error;
1144 }
1145
ebdb334b 1146 event_rule_status = lttng_event_rule_userspace_probe_set_event_name(
20a01d15 1147 res.er, tracepoint_name);
4624dad0
SM
1148 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1149 ERR("Failed to set user space probe event rule's name to '%s'.",
1150 tracepoint_name);
1151 goto error;
1152 }
1153
1154 break;
1155 }
1156 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
1157 {
1158 enum lttng_event_rule_status event_rule_status;
1159
20a01d15
SM
1160 res.er = lttng_event_rule_syscall_create();
1161 if (!res.er) {
4624dad0
SM
1162 ERR("Failed to create syscall event rule.");
1163 goto error;
1164 }
1165
1166 event_rule_status = lttng_event_rule_syscall_set_pattern(
20a01d15 1167 res.er, tracepoint_name);
4624dad0
SM
1168 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1169 ERR("Failed to set syscall event rule's pattern to '%s'.",
1170 tracepoint_name);
1171 goto error;
1172 }
1173
1174 if (filter) {
1175 event_rule_status = lttng_event_rule_syscall_set_filter(
20a01d15 1176 res.er, filter);
4624dad0
SM
1177 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1178 ERR("Failed to set syscall event rule's filter to '%s'.",
1179 filter);
1180 goto error;
1181 }
1182 }
1183
1184 break;
1185 }
1186 default:
1187 abort();
1188 goto error;
1189 }
1190
1191 goto end;
1192
1193error:
20a01d15
SM
1194 lttng_event_rule_destroy(res.er);
1195 res.er = NULL;
1196 lttng_dynamic_pointer_array_reset(&res.capture_descriptors);
4624dad0
SM
1197
1198end:
20a01d15
SM
1199 if (parser_ctx) {
1200 filter_parser_ctx_free(parser_ctx);
1201 }
1202
1203 lttng_event_expr_destroy(event_expr);
4624dad0
SM
1204 argpar_item_destroy(item);
1205 free(error);
1206 argpar_state_destroy(state);
1207 free(filter);
1208 free(exclude);
1209 free(loglevel_str);
6e61d0fa 1210 free(source);
4624dad0
SM
1211 strutils_free_null_terminated_array_of_strings(exclusion_list);
1212 lttng_kernel_probe_location_destroy(kernel_probe_location);
1213 lttng_userspace_probe_location_destroy(userspace_probe_location);
ebdb334b 1214 lttng_log_level_rule_destroy(log_level_rule);
20a01d15 1215 return res;
4624dad0
SM
1216}
1217
1218static
1219struct lttng_condition *handle_condition_event(int *argc, const char ***argv)
1220{
20a01d15 1221 struct parse_event_rule_res res;
4624dad0 1222 struct lttng_condition *c;
20a01d15 1223 size_t i;
4624dad0 1224
20a01d15
SM
1225 res = parse_event_rule(argc, argv);
1226 if (!res.er) {
4624dad0 1227 c = NULL;
20a01d15 1228 goto error;
4624dad0
SM
1229 }
1230
ebdb334b 1231 c = lttng_condition_on_event_create(res.er);
20a01d15
SM
1232 lttng_event_rule_destroy(res.er);
1233 res.er = NULL;
4624dad0 1234 if (!c) {
20a01d15
SM
1235 goto error;
1236 }
1237
1238 for (i = 0; i < lttng_dynamic_pointer_array_get_count(&res.capture_descriptors);
1239 i++) {
1240 enum lttng_condition_status status;
1241 struct lttng_event_expr **expr =
1242 lttng_dynamic_array_get_element(
1243 &res.capture_descriptors.array, i);
1244
1245 assert(expr);
1246 assert(*expr);
ebdb334b 1247 status = lttng_condition_on_event_append_capture_descriptor(
20a01d15
SM
1248 c, *expr);
1249 if (status != LTTNG_CONDITION_STATUS_OK) {
ebdb334b
JR
1250 if (status == LTTNG_CONDITION_STATUS_UNSUPPORTED) {
1251 ERR("The capture feature is unsupported by the event-rule type");
1252 }
20a01d15
SM
1253 goto error;
1254 }
1255
1256 /* Ownership of event expression moved to `c` */
1257 *expr = NULL;
4624dad0
SM
1258 }
1259
20a01d15
SM
1260 goto end;
1261
1262error:
1263 lttng_condition_destroy(c);
1264 c = NULL;
1265
4624dad0 1266end:
20a01d15
SM
1267 lttng_dynamic_pointer_array_reset(&res.capture_descriptors);
1268 lttng_event_rule_destroy(res.er);
4624dad0
SM
1269 return c;
1270}
1271
1272static
1273struct lttng_condition *handle_condition_session_consumed_size(int *argc, const char ***argv)
1274{
1275 struct lttng_condition *cond = NULL;
1276 struct argpar_state *state = NULL;
1277 struct argpar_item *item = NULL;
1278 const char *threshold_arg = NULL;
1279 const char *session_name_arg = NULL;
1280 uint64_t threshold;
1281 char *error = NULL;
1282 enum lttng_condition_status condition_status;
1283
1284 state = argpar_state_create(*argc, *argv, event_rule_opt_descrs);
1285 if (!state) {
1286 ERR("Failed to allocate an argpar state.");
1287 goto error;
1288 }
1289
1290 while (true) {
1291 enum argpar_state_parse_next_status status;
1292
1293 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1294 status = argpar_state_parse_next(state, &item, &error);
1295 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1296 ERR("%s", error);
1297 goto error;
1298 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1299 /* Just stop parsing here. */
1300 break;
1301 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1302 break;
1303 }
1304
1305 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1306
1307 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
1308 const struct argpar_item_opt *item_opt =
1309 (const struct argpar_item_opt *) item;
1310
1311 switch (item_opt->descr->id) {
1312 default:
1313 abort();
1314 }
1315 } else {
1316 const struct argpar_item_non_opt *item_non_opt;
1317
1318 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
1319
1320 item_non_opt = (const struct argpar_item_non_opt *) item;
1321
1322 switch (item_non_opt->non_opt_index) {
1323 case 0:
1324 session_name_arg = item_non_opt->arg;
1325 break;
1326 case 1:
1327 threshold_arg = item_non_opt->arg;
1328 break;
1329 default:
1330 ERR("Unexpected argument `%s`.",
1331 item_non_opt->arg);
1332 goto error;
1333 }
1334 }
1335 }
1336
1337 *argc -= argpar_state_get_ingested_orig_args(state);
1338 *argv += argpar_state_get_ingested_orig_args(state);
1339
1340 if (!session_name_arg) {
1341 ERR("Missing session name argument.");
1342 goto error;
1343 }
1344
1345 if (!threshold_arg) {
1346 ERR("Missing threshold argument.");
1347 goto error;
1348 }
1349
1350 if (utils_parse_size_suffix(threshold_arg, &threshold) != 0) {
1351 ERR("Failed to parse `%s` as a size.", threshold_arg);
1352 goto error;
1353 }
1354
1355 cond = lttng_condition_session_consumed_size_create();
1356 if (!cond) {
1357 ERR("Failed to allocate a session consumed size condition.");
1358 goto error;
1359 }
1360
1361 condition_status = lttng_condition_session_consumed_size_set_session_name(
1362 cond, session_name_arg);
1363 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
1364 ERR("Failed to set session consumed size condition's session name to '%s'.",
1365 session_name_arg);
1366 goto error;
1367 }
1368
1369 condition_status = lttng_condition_session_consumed_size_set_threshold(
1370 cond, threshold);
1371 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
1372 ERR("Failed to set session consumed size condition threshold.");
1373 goto error;
1374 }
1375
1376 goto end;
1377
1378error:
1379 lttng_condition_destroy(cond);
1380 cond = NULL;
1381
1382end:
1383 argpar_state_destroy(state);
1384 argpar_item_destroy(item);
1385 free(error);
1386 return cond;
1387}
1388
1389static
1390struct lttng_condition *handle_condition_buffer_usage_high(int *argc, const char ***argv)
1391{
1392 ERR("High buffer usage threshold conditions are unsupported for the moment.");
1393 return NULL;
1394}
1395
1396static
1397struct lttng_condition *handle_condition_buffer_usage_low(int *argc, const char ***argv)
1398{
1399 ERR("Low buffer usage threshold conditions are unsupported for the moment.");
1400 return NULL;
1401}
1402
1403static
1404struct lttng_condition *handle_condition_session_rotation_ongoing(int *argc, const char ***argv)
1405{
1406 ERR("Session rotation ongoing conditions are unsupported for the moment.");
1407 return NULL;
1408}
1409
1410static
1411struct lttng_condition *handle_condition_session_rotation_completed(int *argc, const char ***argv)
1412{
1413 ERR("Session rotation completed conditions are unsupported for the moment.");
1414 return NULL;
1415}
1416
1417struct condition_descr {
1418 const char *name;
1419 struct lttng_condition *(*handler) (int *argc, const char ***argv);
1420};
1421
1422static const
1423struct condition_descr condition_descrs[] = {
1424 { "on-event", handle_condition_event },
1425 { "on-session-consumed-size", handle_condition_session_consumed_size },
1426 { "on-buffer-usage-high", handle_condition_buffer_usage_high },
1427 { "on-buffer-usage-low", handle_condition_buffer_usage_low },
1428 { "on-session-rotation-ongoing", handle_condition_session_rotation_ongoing },
1429 { "on-session-rotation-completed", handle_condition_session_rotation_completed },
1430};
1431
1432static
1433struct lttng_condition *parse_condition(int *argc, const char ***argv)
1434{
1435 int i;
1436 struct lttng_condition *cond;
1437 const char *condition_name;
1438 const struct condition_descr *descr = NULL;
1439
1440 if (*argc == 0) {
1441 ERR("Missing condition name.");
1442 goto error;
1443 }
1444
1445 condition_name = (*argv)[0];
1446
1447 (*argc)--;
1448 (*argv)++;
1449
1450 for (i = 0; i < ARRAY_SIZE(condition_descrs); i++) {
1451 if (strcmp(condition_name, condition_descrs[i].name) == 0) {
1452 descr = &condition_descrs[i];
1453 break;
1454 }
1455 }
1456
1457 if (!descr) {
1458 ERR("Unknown condition name '%s'", condition_name);
1459 goto error;
1460 }
1461
1462 cond = descr->handler(argc, argv);
1463 if (!cond) {
1464 /* The handler has already printed an error message. */
1465 goto error;
1466 }
1467
1468 goto end;
1469error:
1470 cond = NULL;
1471end:
1472 return cond;
1473}
1474
1475
1476static
1477struct lttng_action *handle_action_notify(int *argc, const char ***argv)
1478{
1479 return lttng_action_notify_create();
1480}
1481
1482static const struct argpar_opt_descr no_opt_descrs[] = {
1483 ARGPAR_OPT_DESCR_SENTINEL
1484};
1485
1486/*
1487 * Generic handler for a kind of action that takes a session name as its sole
1488 * argument.
1489 */
1490
1491static
1492struct lttng_action *handle_action_simple_session(
1493 int *argc, const char ***argv,
1494 struct lttng_action *(*create_action_cb)(void),
1495 enum lttng_action_status (*set_session_name_cb)(struct lttng_action *, const char *),
1496 const char *action_name)
1497{
1498 struct lttng_action *action = NULL;
1499 struct argpar_state *state = NULL;
1500 struct argpar_item *item = NULL;
1501 const char *session_name_arg = NULL;
1502 char *error = NULL;
1503 enum lttng_action_status action_status;
1504
1505 state = argpar_state_create(*argc, *argv, no_opt_descrs);
1506 if (!state) {
1507 ERR("Failed to allocate an argpar state.");
1508 goto error;
1509 }
1510
1511 while (true) {
1512 enum argpar_state_parse_next_status status;
1513 const struct argpar_item_non_opt *item_non_opt;
1514
1515 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1516 status = argpar_state_parse_next(state, &item, &error);
1517 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1518 ERR("%s", error);
1519 goto error;
1520 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1521 /* Just stop parsing here. */
1522 break;
1523 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1524 break;
1525 }
1526
1527 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1528 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
1529
1530 item_non_opt = (const struct argpar_item_non_opt *) item;
1531
1532 switch (item_non_opt->non_opt_index) {
1533 case 0:
1534 session_name_arg = item_non_opt->arg;
1535 break;
1536 default:
1537 ERR("Unexpected argument `%s`.", item_non_opt->arg);
1538 goto error;
1539 }
1540 }
1541
1542 *argc -= argpar_state_get_ingested_orig_args(state);
1543 *argv += argpar_state_get_ingested_orig_args(state);
1544
1545 if (!session_name_arg) {
1546 ERR("Missing session name.");
1547 goto error;
1548 }
1549
1550 action = create_action_cb();
1551 if (!action) {
1552 ERR("Failed to allocate %s session action.", action_name);
1553 goto error;
1554 }
1555
1556 action_status = set_session_name_cb(action, session_name_arg);
1557 if (action_status != LTTNG_ACTION_STATUS_OK) {
1558 ERR("Failed to set action %s session's session name to '%s'.",
1559 action_name, session_name_arg);
1560 goto error;
1561 }
1562
1563 goto end;
1564
1565error:
1566 lttng_action_destroy(action);
1567 action = NULL;
97abbc84 1568 argpar_item_destroy(item);
4624dad0 1569end:
cb1b81ea 1570 free(error);
b78ef509 1571 argpar_state_destroy(state);
4624dad0
SM
1572 return action;
1573}
1574
1575static
1576struct lttng_action *handle_action_start_session(int *argc,
1577 const char ***argv)
1578{
1579 return handle_action_simple_session(argc, argv,
1580 lttng_action_start_session_create,
1581 lttng_action_start_session_set_session_name,
1582 "start");
1583}
1584
1585static
1586struct lttng_action *handle_action_stop_session(int *argc,
1587 const char ***argv)
1588{
1589 return handle_action_simple_session(argc, argv,
1590 lttng_action_stop_session_create,
1591 lttng_action_stop_session_set_session_name,
1592 "stop");
1593}
1594
1595static
1596struct lttng_action *handle_action_rotate_session(int *argc,
1597 const char ***argv)
1598{
1599 return handle_action_simple_session(argc, argv,
1600 lttng_action_rotate_session_create,
1601 lttng_action_rotate_session_set_session_name,
1602 "rotate");
1603}
1604
1605static const struct argpar_opt_descr snapshot_action_opt_descrs[] = {
1606 { OPT_NAME, 'n', "name", true },
1607 { OPT_MAX_SIZE, 'm', "max-size", true },
1608 { OPT_CTRL_URL, '\0', "ctrl-url", true },
1609 { OPT_DATA_URL, '\0', "data-url", true },
1610 { OPT_URL, '\0', "url", true },
1611 { OPT_PATH, '\0', "path", true },
1612 ARGPAR_OPT_DESCR_SENTINEL
1613};
1614
1615static
1616struct lttng_action *handle_action_snapshot_session(int *argc,
1617 const char ***argv)
1618{
1619 struct lttng_action *action = NULL;
1620 struct argpar_state *state = NULL;
1621 struct argpar_item *item = NULL;
1622 const char *session_name_arg = NULL;
1623 char *snapshot_name_arg = NULL;
1624 char *ctrl_url_arg = NULL;
1625 char *data_url_arg = NULL;
1626 char *max_size_arg = NULL;
1627 char *url_arg = NULL;
1628 char *path_arg = NULL;
1629 char *error = NULL;
1630 enum lttng_action_status action_status;
1631 struct lttng_snapshot_output *snapshot_output = NULL;
1632 int ret;
1633 unsigned int locations_specified = 0;
1634
1635 state = argpar_state_create(*argc, *argv, snapshot_action_opt_descrs);
1636 if (!state) {
1637 ERR("Failed to allocate an argpar state.");
1638 goto error;
1639 }
1640
1641 while (true) {
1642 enum argpar_state_parse_next_status status;
1643
1644 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1645 status = argpar_state_parse_next(state, &item, &error);
1646 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1647 ERR("%s", error);
1648 goto error;
1649 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1650 /* Just stop parsing here. */
1651 break;
1652 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1653 break;
1654 }
1655
1656 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1657
1658 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
1659 const struct argpar_item_opt *item_opt =
1660 (const struct argpar_item_opt *) item;
1661
1662 switch (item_opt->descr->id) {
1663 case OPT_NAME:
1664 if (!assign_string(&snapshot_name_arg, item_opt->arg, "--name/-n")) {
1665 goto error;
1666 }
1667
1668 break;
1669 case OPT_MAX_SIZE:
1670 if (!assign_string(&max_size_arg, item_opt->arg, "--max-size/-m")) {
1671 goto error;
1672 }
1673
1674 break;
1675 case OPT_CTRL_URL:
1676 if (!assign_string(&ctrl_url_arg, item_opt->arg, "--ctrl-url")) {
1677 goto error;
1678 }
1679
1680 break;
1681 case OPT_DATA_URL:
1682 if (!assign_string(&data_url_arg, item_opt->arg, "--data-url")) {
1683 goto error;
1684 }
1685
1686 break;
1687 case OPT_URL:
1688 if (!assign_string(&url_arg, item_opt->arg, "--url")) {
1689 goto error;
1690 }
1691
1692 break;
1693 case OPT_PATH:
1694 if (!assign_string(&path_arg, item_opt->arg, "--path")) {
1695 goto error;
1696 }
1697
1698 break;
1699 default:
1700 abort();
1701 }
1702 } else {
1703 const struct argpar_item_non_opt *item_non_opt;
1704
1705 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
1706
1707 item_non_opt = (const struct argpar_item_non_opt *) item;
1708
1709 switch (item_non_opt->non_opt_index) {
1710 case 0:
1711 session_name_arg = item_non_opt->arg;
1712 break;
1713 default:
1714 ERR("Unexpected argument `%s`.",
1715 item_non_opt->arg);
1716 goto error;
1717 }
1718 }
1719 }
1720
1721 *argc -= argpar_state_get_ingested_orig_args(state);
1722 *argv += argpar_state_get_ingested_orig_args(state);
1723
1724 if (!session_name_arg) {
1725 ERR("Missing session name.");
1726 goto error;
1727 }
1728
1729 /* --ctrl-url and --data-url must come in pair. */
1730 if (ctrl_url_arg && !data_url_arg) {
1731 ERR("--ctrl-url is specified, but --data-url is missing.");
1732 goto error;
1733 }
1734
1735 if (!ctrl_url_arg && data_url_arg) {
1736 ERR("--data-url is specified, but --ctrl-url is missing.");
1737 goto error;
1738 }
1739
1740 locations_specified += !!(ctrl_url_arg || data_url_arg);
1741 locations_specified += !!url_arg;
1742 locations_specified += !!path_arg;
1743
1744 /* --ctrl-url/--data-url, --url and --path are mutually exclusive. */
1745 if (locations_specified > 1) {
1746 ERR("The --ctrl-url/--data-url, --url, and --path options can't be used together.");
1747 goto error;
1748 }
1749
1750 /*
1751 * Did the user specify an option that implies using a
1752 * custom/unregistered output?
1753 */
1754 if (url_arg || ctrl_url_arg || path_arg) {
1755 snapshot_output = lttng_snapshot_output_create();
1756 if (!snapshot_output) {
1757 ERR("Failed to allocate a snapshot output.");
1758 goto error;
1759 }
1760 }
1761
1762 action = lttng_action_snapshot_session_create();
1763 if (!action) {
1764 ERR("Failed to allocate snapshot session action.");
1765 goto error;
1766 }
1767
1768 action_status = lttng_action_snapshot_session_set_session_name(
1769 action, session_name_arg);
1770 if (action_status != LTTNG_ACTION_STATUS_OK) {
1771 ERR("Failed to set action snapshot session's session name to '%s'.",
1772 session_name_arg);
1773 goto error;
1774 }
1775
1776 if (snapshot_name_arg) {
1777 if (!snapshot_output) {
1778 ERR("Can't provide a snapshot output name without a snapshot output destination.");
1779 goto error;
1780 }
1781
1782 ret = lttng_snapshot_output_set_name(
1783 snapshot_name_arg, snapshot_output);
1784 if (ret != 0) {
1785 ERR("Failed to set name of snapshot output.");
1786 goto error;
1787 }
1788 }
1789
1790 if (max_size_arg) {
1791 uint64_t max_size;
1792
1793 if (!snapshot_output) {
1794 ERR("Can't provide a snapshot output max size without a snapshot output destination.");
1795 goto error;
1796 }
1797
1798 ret = utils_parse_size_suffix(max_size_arg, &max_size);
1799 if (ret != 0) {
1800 ERR("Failed to parse `%s` as a size.", max_size_arg);
1801 goto error;
1802 }
1803
1804 ret = lttng_snapshot_output_set_size(max_size, snapshot_output);
1805 if (ret != 0) {
1806 ERR("Failed to set snapshot output's max size to %" PRIu64 " bytes.",
1807 max_size);
1808 goto error;
1809 }
1810 }
1811
1812 if (url_arg) {
1813 int num_uris;
1814 struct lttng_uri *uris;
1815
1816 if (!strstr(url_arg, "://")) {
1817 ERR("Failed to parse '%s' as an URL.", url_arg);
1818 goto error;
1819 }
1820
1821 num_uris = uri_parse_str_urls(url_arg, NULL, &uris);
1822 if (num_uris < 1) {
1823 ERR("Failed to parse '%s' as an URL.", url_arg);
1824 goto error;
1825 }
1826
1827 if (uris[0].dtype == LTTNG_DST_PATH) {
1828 ret = lttng_snapshot_output_set_local_path(
1829 uris[0].dst.path, snapshot_output);
1830 free(uris);
1831 if (ret != 0) {
1832 ERR("Failed to assign '%s' as a local destination.",
1833 url_arg);
1834 goto error;
1835 }
1836 } else {
1837 ret = lttng_snapshot_output_set_network_url(
1838 url_arg, snapshot_output);
1839 free(uris);
1840 if (ret != 0) {
1841 ERR("Failed to assign '%s' as a network URL.",
1842 url_arg);
1843 goto error;
1844 }
1845 }
1846 }
1847
1848 if (path_arg) {
1849 ret = lttng_snapshot_output_set_local_path(
1850 path_arg, snapshot_output);
1851 if (ret != 0) {
1852 ERR("Failed to parse '%s' as a local path.", path_arg);
1853 goto error;
1854 }
1855 }
1856
1857 if (ctrl_url_arg) {
1858 /*
1859 * Two argument form, network output with separate control and
1860 * data URLs.
1861 */
1862 ret = lttng_snapshot_output_set_network_urls(
1863 ctrl_url_arg, data_url_arg, snapshot_output);
1864 if (ret != 0) {
1865 ERR("Failed to parse `%s` and `%s` as control and data URLs.",
1866 ctrl_url_arg, data_url_arg);
1867 goto error;
1868 }
1869 }
1870
1871 if (snapshot_output) {
1872 action_status = lttng_action_snapshot_session_set_output(
1873 action, snapshot_output);
1874 if (action_status != LTTNG_ACTION_STATUS_OK) {
1875 ERR("Failed to set snapshot session action's output.");
1876 goto error;
1877 }
1878
1879 /* Ownership of `snapshot_output` has been transferred to the action. */
1880 snapshot_output = NULL;
1881 }
1882
1883 goto end;
1884
1885error:
1886 lttng_action_destroy(action);
1887 action = NULL;
1888 free(error);
1889end:
1890 free(snapshot_name_arg);
1891 free(path_arg);
1892 free(url_arg);
1893 free(ctrl_url_arg);
1894 free(data_url_arg);
1895 free(snapshot_output);
f6b73530 1896 free(max_size_arg);
4624dad0 1897 argpar_state_destroy(state);
97abbc84 1898 argpar_item_destroy(item);
4624dad0
SM
1899 return action;
1900}
1901
ebdb334b
JR
1902static const struct argpar_opt_descr incr_value_action_opt_descrs[] = {
1903 { OPT_SESSION_NAME, 's', "session", true },
1904 { OPT_MAP_NAME, 'm', "map", true },
1905 { OPT_KEY, '\0', "key", true },
1906 ARGPAR_OPT_DESCR_SENTINEL
1907};
1908
1909static
1910struct lttng_action *handle_action_incr_value(int *argc,
1911 const char ***argv)
1912{
1913 struct lttng_action *action = NULL;
1914 struct argpar_state *state = NULL;
1915 struct argpar_item *item = NULL;
1916 struct lttng_map_key *key = NULL;
1917 char *session_name_arg = NULL, *map_name_arg = NULL;
1918 char *key_arg = NULL;
1919 char *error = NULL;
1920 enum lttng_action_status action_status;
1921
1922 state = argpar_state_create(*argc, *argv, incr_value_action_opt_descrs);
1923 if (!state) {
1924 ERR("Failed to allocate an argpar state.");
1925 goto error;
1926 }
1927
1928 while (true) {
1929 enum argpar_state_parse_next_status status;
1930
1931 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1932 status = argpar_state_parse_next(state, &item, &error);
1933 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1934 ERR("%s", error);
1935 goto error;
1936 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1937 /* Just stop parsing here. */
1938 break;
1939 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1940 break;
1941 }
1942
1943 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1944
1945 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
1946 struct argpar_item_opt *item_opt =
1947 (struct argpar_item_opt *) item;
1948
1949 switch (item_opt->descr->id) {
1950 case OPT_SESSION_NAME:
1951 if (!assign_string(&session_name_arg, item_opt->arg, "--session/-s")) {
1952 goto error;
1953 }
1954 break;
1955 case OPT_MAP_NAME:
1956 if (!assign_string(&map_name_arg, item_opt->arg, "--map/-m")) {
1957 goto error;
1958 }
1959 break;
1960 case OPT_KEY:
1961 if (!assign_string(&key_arg, item_opt->arg, "--key")) {
1962 goto error;
1963 }
1964 break;
1965 default:
1966 abort();
1967 }
1968 }
1969 }
1970
1971 *argc -= argpar_state_get_ingested_orig_args(state);
1972 *argv += argpar_state_get_ingested_orig_args(state);
1973
1974 if (!session_name_arg) {
1975 ERR("Missing session name.");
1976 goto error;
1977 }
1978
1979 if (!map_name_arg) {
1980 ERR("Missing map name.");
1981 goto error;
1982 }
1983
1984 if (!key_arg) {
1985 ERR("Missing key");
1986 goto error;
1987 }
1988
1989 key = lttng_map_key_parse_from_string(key_arg);
1990 if (!key) {
1991 ERR("Error parsing key argument");
1992 goto error;
1993 }
1994
1995 action = lttng_action_incr_value_create();
1996 if (!action) {
1997 ERR("Failed to allocate incr-value action.");
1998 goto error;
1999 }
2000
2001 action_status = lttng_action_incr_value_set_session_name(action,
2002 session_name_arg);
2003 if (action_status != LTTNG_ACTION_STATUS_OK) {
2004 ERR("Failed to set action incr-value's session name.");
2005 goto error;
2006 }
2007
2008 action_status = lttng_action_incr_value_set_map_name(action,
2009 map_name_arg);
2010 if (action_status != LTTNG_ACTION_STATUS_OK) {
2011 ERR("Failed to set action incr-value's map name.");
2012 goto error;
2013 }
2014
2015 action_status = lttng_action_incr_value_set_key(action, key);
2016 if (action_status != LTTNG_ACTION_STATUS_OK) {
2017 ERR("Failed to set action incr-value's key");
2018 goto error;
2019 }
2020
2021 goto end;
2022
2023error:
2024 lttng_action_destroy(action);
2025 action = NULL;
2026
2027end:
2028 lttng_map_key_destroy(key);
2029 free(session_name_arg);
2030 free(map_name_arg);
2031 free(key_arg);
2032 return action;
2033}
2034
4624dad0
SM
2035struct action_descr {
2036 const char *name;
2037 struct lttng_action *(*handler) (int *argc, const char ***argv);
2038};
2039
2040static const
2041struct action_descr action_descrs[] = {
2042 { "notify", handle_action_notify },
2043 { "start-session", handle_action_start_session },
2044 { "stop-session", handle_action_stop_session },
2045 { "rotate-session", handle_action_rotate_session },
2046 { "snapshot-session", handle_action_snapshot_session },
ebdb334b 2047 { "incr-value", handle_action_incr_value },
4624dad0
SM
2048};
2049
2050static
2051struct lttng_action *parse_action(int *argc, const char ***argv)
2052{
2053 int i;
2054 struct lttng_action *action;
2055 const char *action_name;
2056 const struct action_descr *descr = NULL;
2057
2058 if (*argc == 0) {
2059 ERR("Missing action name.");
2060 goto error;
2061 }
2062
2063 action_name = (*argv)[0];
2064
2065 (*argc)--;
2066 (*argv)++;
2067
2068 for (i = 0; i < ARRAY_SIZE(action_descrs); i++) {
2069 if (strcmp(action_name, action_descrs[i].name) == 0) {
2070 descr = &action_descrs[i];
2071 break;
2072 }
2073 }
2074
2075 if (!descr) {
2076 ERR("Unknown action name: %s", action_name);
2077 goto error;
2078 }
2079
2080 action = descr->handler(argc, argv);
2081 if (!action) {
2082 /* The handler has already printed an error message. */
2083 goto error;
2084 }
2085
2086 goto end;
2087error:
2088 action = NULL;
2089end:
2090 return action;
2091}
2092
2093static const
2094struct argpar_opt_descr add_trigger_options[] = {
2095 { OPT_HELP, 'h', "help", false },
2096 { OPT_LIST_OPTIONS, '\0', "list-options", false },
2097 { OPT_CONDITION, '\0', "condition", false },
2098 { OPT_ACTION, '\0', "action", false },
2099 { OPT_ID, '\0', "id", true },
2100 { OPT_FIRE_ONCE_AFTER, '\0', "fire-once-after", true },
2101 { OPT_FIRE_EVERY, '\0', "fire-every", true },
2102 { OPT_USER_ID, '\0', "user-id", true },
2103 ARGPAR_OPT_DESCR_SENTINEL,
2104};
2105
ebdb334b
JR
2106static
2107bool action_is_tracer_executed(const struct lttng_action *action)
2108{
2109 bool is_tracer_executed;
2110 switch (lttng_action_get_type(action)) {
2111 case LTTNG_ACTION_TYPE_NOTIFY:
2112 case LTTNG_ACTION_TYPE_START_SESSION:
2113 case LTTNG_ACTION_TYPE_STOP_SESSION:
2114 case LTTNG_ACTION_TYPE_ROTATE_SESSION:
2115 case LTTNG_ACTION_TYPE_SNAPSHOT_SESSION:
2116 is_tracer_executed = false;
2117 goto end;
2118 case LTTNG_ACTION_TYPE_INCREMENT_VALUE:
2119 is_tracer_executed = true;
2120 goto end;
2121 case LTTNG_ACTION_TYPE_GROUP:
2122 default:
2123 abort();
2124 }
2125
2126end:
2127 return is_tracer_executed;
2128}
2129
4624dad0
SM
2130static
2131void lttng_actions_destructor(void *p)
2132{
2133 struct lttng_action *action = p;
2134
2135 lttng_action_destroy(action);
2136}
2137
2138int cmd_add_trigger(int argc, const char **argv)
2139{
2140 int ret;
2141 int my_argc = argc - 1;
2142 const char **my_argv = argv + 1;
2143 struct lttng_condition *condition = NULL;
2144 struct lttng_dynamic_pointer_array actions;
2145 struct argpar_state *argpar_state = NULL;
2146 struct argpar_item *argpar_item = NULL;
2147 struct lttng_action *action_group = NULL;
2148 struct lttng_action *action = NULL;
2149 struct lttng_trigger *trigger = NULL;
2150 char *error = NULL;
2151 char *id = NULL;
2152 int i;
2153 char *fire_once_after_str = NULL;
2154 char *fire_every_str = NULL;
2155 char *user_id = NULL;
2156
2157 lttng_dynamic_pointer_array_init(&actions, lttng_actions_destructor);
2158
2159 while (true) {
2160 enum argpar_state_parse_next_status status;
2161 const struct argpar_item_opt *item_opt;
2162 int ingested_args;
2163
2164 argpar_state_destroy(argpar_state);
2165 argpar_state = argpar_state_create(my_argc, my_argv,
2166 add_trigger_options);
2167 if (!argpar_state) {
2168 ERR("Failed to create argpar state.");
2169 goto error;
2170 }
2171
2172 ARGPAR_ITEM_DESTROY_AND_RESET(argpar_item);
2173 status = argpar_state_parse_next(argpar_state, &argpar_item, &error);
2174 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
2175 ERR("%s", error);
2176 goto error;
2177 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
2178 ERR("%s", error);
2179 goto error;
2180 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
2181 break;
2182 }
2183
2184 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
2185
2186 if (argpar_item->type == ARGPAR_ITEM_TYPE_NON_OPT) {
2187 const struct argpar_item_non_opt *item_non_opt =
2188 (const struct argpar_item_non_opt *)
2189 argpar_item;
2190
2191 ERR("Unexpected argument `%s`.", item_non_opt->arg);
2192 goto error;
2193 }
2194
2195 item_opt = (const struct argpar_item_opt *) argpar_item;
2196
2197 ingested_args = argpar_state_get_ingested_orig_args(
2198 argpar_state);
2199
2200 my_argc -= ingested_args;
2201 my_argv += ingested_args;
2202
2203 switch (item_opt->descr->id) {
2204 case OPT_HELP:
2205 SHOW_HELP();
2206 ret = 0;
2207 goto end;
2208 case OPT_LIST_OPTIONS:
2209 list_cmd_options_argpar(stdout, add_trigger_options);
2210 ret = 0;
2211 goto end;
2212 case OPT_CONDITION:
2213 {
2214 if (condition) {
2215 ERR("A --condition was already given.");
2216 goto error;
2217 }
2218
2219 condition = parse_condition(&my_argc, &my_argv);
2220 if (!condition) {
2221 /*
2222 * An error message was already printed by
2223 * parse_condition.
2224 */
2225 goto error;
2226 }
2227
2228 break;
2229 }
2230 case OPT_ACTION:
2231 {
2232 action = parse_action(&my_argc, &my_argv);
2233 if (!action) {
2234 /*
2235 * An error message was already printed by
2236 * parse_condition.
2237 */
2238 goto error;
2239 }
2240
2241 ret = lttng_dynamic_pointer_array_add_pointer(
2242 &actions, action);
2243 if (ret) {
2244 ERR("Failed to add pointer to pointer array.");
2245 goto error;
2246 }
2247
2248 /* Ownership of the action was transferred to the group. */
2249 action = NULL;
2250
2251 break;
2252 }
2253 case OPT_ID:
2254 {
2255 if (!assign_string(&id, item_opt->arg, "--id")) {
2256 goto error;
2257 }
2258
2259 break;
2260 }
2261 case OPT_FIRE_ONCE_AFTER:
2262 {
2263 if (!assign_string(&fire_once_after_str, item_opt->arg,
2264 "--fire-once-after")) {
2265 goto error;
2266 }
2267
2268 break;
2269 }
2270 case OPT_FIRE_EVERY:
2271 {
2272 if (!assign_string(&fire_every_str, item_opt->arg,
2273 "--fire-every")) {
2274 goto error;
2275 }
2276
2277 break;
2278 }
2279 case OPT_USER_ID:
2280 {
2281 if (!assign_string(&user_id, item_opt->arg,
2282 "--user-id")) {
2283 goto error;
2284 }
2285
2286 break;
2287 }
2288 default:
2289 abort();
2290 }
2291 }
2292
2293 if (!condition) {
2294 ERR("Missing --condition.");
2295 goto error;
2296 }
2297
2298 if (lttng_dynamic_pointer_array_get_count(&actions) == 0) {
2299 ERR("Need at least one --action.");
2300 goto error;
2301 }
2302
2303 if (fire_every_str && fire_once_after_str) {
2304 ERR("Can't specify both --fire-once-after and --fire-every.");
2305 goto error;
2306 }
2307
2308 action_group = lttng_action_group_create();
2309 if (!action_group) {
2310 goto error;
2311 }
2312
2313 for (i = 0; i < lttng_dynamic_pointer_array_get_count(&actions); i++) {
2314 enum lttng_action_status status;
2315
2316 action = lttng_dynamic_pointer_array_steal_pointer(&actions, i);
ebdb334b
JR
2317 if (action_is_tracer_executed(action)) {
2318 if (fire_every_str || fire_once_after_str) {
2319 /*
2320 * Firing policy with tracer-executed actions
2321 * (`incr-value`) is not supported at the
2322 * moment. It's not clear how the tracers will
2323 * handle the different policies efficiently.
2324 */
2325 ERR("Can't use --fire-once-after or --fire-every with tracer executed action (incr-value)");
2326 goto error;
2327 }
2328 }
4624dad0
SM
2329
2330 status = lttng_action_group_add_action(action_group, action);
2331 if (status != LTTNG_ACTION_STATUS_OK) {
2332 goto error;
2333 }
2334
2335 /*
2336 * The `lttng_action_group_add_action()` takes a reference to
2337 * the action. We can destroy ours.
2338 */
2339 lttng_action_destroy(action);
2340 action = NULL;
2341 }
2342
2343 trigger = lttng_trigger_create(condition, action_group);
2344 if (!trigger) {
2345 goto error;
2346 }
2347
2348 if (id) {
2349 enum lttng_trigger_status trigger_status =
2350 lttng_trigger_set_name(trigger, id);
2351
2352 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2353 ERR("Failed to set trigger id.");
2354 goto error;
2355 }
2356 }
2357
2358 if (fire_once_after_str) {
2359 unsigned long long threshold;
2360 enum lttng_trigger_status trigger_status;
2361
2362 if (utils_parse_unsigned_long_long(fire_once_after_str, &threshold) != 0) {
2363 ERR("Failed to parse `%s` as an integer.", fire_once_after_str);
2364 goto error;
2365 }
2366
2367 trigger_status = lttng_trigger_set_firing_policy(trigger,
2368 LTTNG_TRIGGER_FIRING_POLICY_ONCE_AFTER_N,
2369 threshold);
2370 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2371 ERR("Failed to set trigger's policy to `fire once after N`.");
2372 goto error;
2373 }
2374 }
2375
2376 if (fire_every_str) {
2377 unsigned long long threshold;
2378 enum lttng_trigger_status trigger_status;
2379
2380 if (utils_parse_unsigned_long_long(fire_every_str, &threshold) != 0) {
2381 ERR("Failed to parse `%s` as an integer.", fire_every_str);
2382 goto error;
2383 }
2384
2385 trigger_status = lttng_trigger_set_firing_policy(trigger,
2386 LTTNG_TRIGGER_FIRING_POLICY_EVERY_N, threshold);
2387 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2388 ERR("Failed to set trigger's policy to `fire every N`.");
2389 goto error;
2390 }
2391 }
2392
2393 if (user_id) {
2394 enum lttng_trigger_status trigger_status;
2395 char *end;
2396 long long uid;
2397
2398 errno = 0;
2399 uid = strtol(user_id, &end, 10);
2400 if (end == user_id || *end != '\0' || errno != 0) {
2401 ERR("Failed to parse `%s` as a user id.", user_id);
2402 }
2403
2404 trigger_status = lttng_trigger_set_owner_uid(trigger, uid);
2405 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2406 ERR("Failed to set trigger's user identity.");
2407 goto error;
2408 }
2409 }
2410
2411 ret = lttng_register_trigger(trigger);
2412 if (ret) {
2413 ERR("Failed to register trigger: %s.", lttng_strerror(ret));
2414 goto error;
2415 }
2416
2417 MSG("Trigger registered successfully.");
2418
2419 goto end;
2420
2421error:
2422 ret = 1;
2423
2424end:
2425 argpar_state_destroy(argpar_state);
2426 argpar_item_destroy(argpar_item);
2427 lttng_dynamic_pointer_array_reset(&actions);
2428 lttng_condition_destroy(condition);
2429 lttng_action_destroy(action_group);
2430 lttng_action_destroy(action);
2431 lttng_trigger_destroy(trigger);
2432 free(error);
2433 free(id);
2434 free(fire_once_after_str);
2435 free(fire_every_str);
2436 free(user_id);
2437 return ret;
2438}
This page took 0.117165 seconds and 5 git commands to generate.