SoW-2019-0002: Dynamic Snapshot
[lttng-tools.git] / src / bin / lttng / commands / add_trigger.c
1 #include <stdio.h>
2
3 #include "../command.h"
4 #include "../uprobe.h"
5
6 #include "common/argpar/argpar.h"
7 #include "common/dynamic-array.h"
8 #include "common/string-utils/string-utils.h"
9 #include "common/utils.h"
10 #include "lttng/condition/event-rule.h"
11 #include "lttng/event-internal.h"
12 #include <lttng/event-rule/event-rule-internal.h>
13 #include "lttng/event-rule/kprobe.h"
14 #include "lttng/event-rule/syscall.h"
15 #include <lttng/event-rule/tracepoint.h>
16 #include "lttng/event-rule/uprobe.h"
17
18 #ifdef LTTNG_EMBED_HELP
19 static const char help_msg[] =
20 #include <lttng-add-trigger.1.h>
21 ;
22 #endif
23
24 enum {
25 OPT_HELP,
26 OPT_LIST_OPTIONS,
27
28 OPT_CONDITION,
29 OPT_ACTION,
30 OPT_ID,
31 OPT_FIRE_ONCE_AFTER,
32 OPT_FIRE_EVERY,
33
34 OPT_ALL,
35 OPT_FILTER,
36 OPT_EXCLUDE,
37 OPT_LOGLEVEL,
38 OPT_LOGLEVEL_ONLY,
39
40 OPT_USERSPACE,
41 OPT_KERNEL,
42 OPT_LOG4J,
43 OPT_JUL,
44 OPT_PYTHON,
45
46 OPT_FUNCTION,
47 OPT_PROBE,
48 OPT_USERSPACE_PROBE,
49 OPT_SYSCALL,
50 OPT_TRACEPOINT,
51
52 OPT_NAME,
53 OPT_MAX_SIZE,
54 OPT_DATA_URL,
55 OPT_CTRL_URL,
56 };
57
58 static const struct argpar_opt_descr event_rule_opt_descrs[] = {
59 { OPT_ALL, 'a', "all", false },
60 { OPT_FILTER, 'f', "filter", true },
61 { OPT_EXCLUDE, 'x', "exclude", true },
62 { OPT_LOGLEVEL, '\0', "loglevel", true },
63 { OPT_LOGLEVEL_ONLY, '\0', "loglevel-only", true },
64
65 /* Domains */
66 { OPT_USERSPACE, 'u', "userspace", false },
67 { OPT_KERNEL, 'k', "kernel", false },
68 { OPT_LOG4J, 'l', "log4j", false },
69 { OPT_JUL, 'j', "jul", false },
70 { OPT_PYTHON, 'p', "python", false },
71
72 /* Event rule types */
73 { OPT_FUNCTION, '\0', "function", true },
74 { OPT_PROBE, '\0', "probe", true },
75 { OPT_USERSPACE_PROBE, '\0', "userspace-probe", true },
76 { OPT_SYSCALL, '\0', "syscall" },
77 { OPT_TRACEPOINT, '\0', "tracepoint" },
78
79 ARGPAR_OPT_DESCR_SENTINEL
80 };
81
82 static
83 bool assign_domain_type(enum lttng_domain_type *dest,
84 enum lttng_domain_type src)
85 {
86 bool ret;
87
88 if (*dest == LTTNG_DOMAIN_NONE || *dest == src) {
89 *dest = src;
90 ret = true;
91 } else {
92 fprintf(stderr, "Error: Multiple domains specified.\n");
93 ret = false;
94 }
95
96 return ret;
97 }
98
99 static
100 bool assign_event_rule_type(enum lttng_event_rule_type *dest,
101 enum lttng_event_rule_type src)
102 {
103 bool ret;
104
105 if (*dest == LTTNG_EVENT_RULE_TYPE_UNKNOWN || *dest == src) {
106 *dest = src;
107 ret = true;
108 } else {
109 fprintf(stderr, "Error: Multiple event type not supported.\n");
110 ret = false;
111 }
112
113 return ret;
114 }
115
116 static
117 bool assign_string(char **dest, const char *src, const char *opt_name)
118 {
119 bool ret;
120
121 if (*dest) {
122 fprintf(stderr,
123 "Duplicate %s given.\n", opt_name);
124 goto error;
125 }
126
127 *dest = strdup(src);
128 if (!*dest) {
129 fprintf(stderr, "Failed to allocate %s string.\n", opt_name);
130 goto error;
131 }
132
133 ret = true;
134 goto end;
135
136 error:
137 ret = false;
138
139 end:
140 return ret;
141 }
142
143 /* This is defined in enable_events.c. */
144 LTTNG_HIDDEN
145 int create_exclusion_list_and_validate(const char *event_name,
146 const char *exclusions_arg,
147 char ***exclusion_list);
148
149 /*
150 * Parse `str` as a log level in domain `domain_type`. Return -1 if the string
151 * is not recognized as a valid log level.
152 */
153 static
154 int parse_loglevel_string(const char *str, enum lttng_domain_type domain_type)
155 {
156
157 switch (domain_type) {
158 case LTTNG_DOMAIN_UST:
159 return loglevel_str_to_value(str);
160
161 case LTTNG_DOMAIN_LOG4J:
162 return loglevel_log4j_str_to_value(str);
163
164 case LTTNG_DOMAIN_JUL:
165 return loglevel_jul_str_to_value(str);
166
167 case LTTNG_DOMAIN_PYTHON:
168 return loglevel_python_str_to_value(str);
169
170 default:
171 /* Invalid domain type. */
172 abort();
173 }
174 }
175
176 static
177 struct lttng_event_rule *parse_event_rule(int *argc, const char ***argv)
178 {
179 struct lttng_event_rule *er = NULL;
180 enum lttng_domain_type domain_type = LTTNG_DOMAIN_NONE;
181 enum lttng_event_rule_type event_rule_type = LTTNG_EVENT_RULE_TYPE_UNKNOWN;
182 struct argpar_state *state;
183 struct argpar_item *item = NULL;
184 char *error = NULL;
185 int consumed_args = -1;
186 struct lttng_userspace_probe_location *userspace_probe_location = NULL;
187
188 /* Was the -a/--all flag provided? */
189 bool all_events = false;
190
191 /* Tracepoint name (non-option argument) */
192 const char *tracepoint_name = NULL;
193
194 /* Holds the argument of --probe / --userspace-probe. */
195 char *source = NULL;
196
197 /* Filter */
198 char *filter = NULL;
199
200 /* Exclude */
201 char *exclude = NULL;
202 char **exclusion_list = NULL;
203
204 /* Log level */
205 char *loglevel_str = NULL;
206 bool loglevel_only = false;
207
208 state = argpar_state_create(*argc, *argv, event_rule_opt_descrs);
209 if (!state) {
210 fprintf(stderr, "Failed to allocate an argpar state.\n");
211 goto error;
212 }
213
214 while (true) {
215 enum argpar_state_parse_next_status status;
216
217 ARGPAR_ITEM_DESTROY_AND_RESET(item);
218 status = argpar_state_parse_next(state, &item, &error);
219 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
220 fprintf(stderr, "Error: %s\n", error);
221 goto error;
222 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
223 /* Just stop parsing here. */
224 break;
225 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
226 break;
227 }
228
229 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
230
231 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
232 struct argpar_item_opt *item_opt =
233 (struct argpar_item_opt *) item;
234
235 switch (item_opt->descr->id) {
236 /* Domains */
237 case OPT_USERSPACE:
238 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_UST)) {
239 goto error;
240 }
241 break;
242
243 case OPT_KERNEL:
244 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_KERNEL)) {
245 goto error;
246 }
247 break;
248
249 case OPT_LOG4J:
250 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_LOG4J)) {
251 goto error;
252 }
253 break;
254
255 case OPT_JUL:
256 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_JUL)) {
257 goto error;
258 }
259 break;
260
261 case OPT_PYTHON:
262 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_PYTHON)) {
263 goto error;
264 }
265 break;
266
267 /* Event rule types */
268 case OPT_FUNCTION:
269 if (!assign_event_rule_type(&event_rule_type,
270 LTTNG_EVENT_RULE_TYPE_KRETPROBE)) {
271 goto error;
272 }
273 break;
274
275 case OPT_PROBE:
276 if (!assign_event_rule_type(&event_rule_type,
277 LTTNG_EVENT_RULE_TYPE_KPROBE)) {
278 goto error;
279 }
280
281 if (!assign_string(&source, item_opt->arg, "source")) {
282 goto error;
283 }
284
285 break;
286
287 case OPT_USERSPACE_PROBE:
288 if (!assign_event_rule_type(&event_rule_type,
289 LTTNG_EVENT_RULE_TYPE_UPROBE)) {
290 goto error;
291 }
292
293 if (!assign_string(&source, item_opt->arg, "source")) {
294 goto error;
295 }
296 break;
297
298 case OPT_SYSCALL:
299 if (!assign_event_rule_type(&event_rule_type,
300 LTTNG_EVENT_RULE_TYPE_SYSCALL)) {
301 goto error;
302 }
303 break;
304
305 case OPT_TRACEPOINT:
306 if (!assign_event_rule_type(&event_rule_type,
307 LTTNG_EVENT_RULE_TYPE_TRACEPOINT)) {
308 goto error;
309 }
310 break;
311
312 case OPT_ALL:
313 all_events = true;
314 break;
315
316 case OPT_FILTER:
317 if (!assign_string(&filter, item_opt->arg, "--filter/-f")) {
318 goto error;
319 }
320 break;
321
322 case OPT_EXCLUDE:
323 if (!assign_string(&exclude, item_opt->arg, "--exclude/-x")) {
324 goto error;
325 }
326 break;
327
328 case OPT_LOGLEVEL:
329 case OPT_LOGLEVEL_ONLY:
330 if (!assign_string(&loglevel_str, item_opt->arg, "--loglevel/--loglevel-only")) {
331 goto error;
332 }
333
334 loglevel_only = item_opt->descr->id == OPT_LOGLEVEL_ONLY;
335 break;
336
337 default:
338 abort();
339 }
340 } else {
341 struct argpar_item_non_opt *item_non_opt =
342 (struct argpar_item_non_opt *) item;
343
344 /*
345 * Don't accept two non-option arguments/tracepoint
346 * names.
347 */
348 if (tracepoint_name) {
349 fprintf(stderr,
350 "Error: Unexpected argument: %s\n",
351 item_non_opt->arg);
352 goto error;
353 }
354
355 tracepoint_name = item_non_opt->arg;
356 }
357 }
358
359 if (event_rule_type == LTTNG_EVENT_RULE_TYPE_UNKNOWN) {
360 event_rule_type = LTTNG_EVENT_RULE_TYPE_TRACEPOINT;
361 }
362
363 /*
364 * Option -a is applicable to event rules of type tracepoint and
365 * syscall, and it is equivalent to using "*" as the tracepoint name.
366 */
367 if (all_events) {
368 switch (event_rule_type) {
369 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
370 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
371 break;
372 default:
373 fprintf(stderr, "Error: Can't use -a/--all with event rule of type %s.\n",
374 lttng_event_rule_type_str(event_rule_type));
375 goto error;
376 }
377
378 if (tracepoint_name) {
379 fprintf(stderr, "Error: Can't provide a tracepoint name with -a/--all.\n");
380 goto error;
381 }
382
383 /* In which case, it's equivalent to tracepoint name "*". */
384 tracepoint_name = "*";
385 }
386
387 /*
388 * A tracepoint name (or -a, for the event rule types that accept it)
389 * is required.
390 */
391 if (!tracepoint_name) {
392 fprintf(stderr, "Error: Need to provide either a tracepoint name or -a/--all.\n");
393 goto error;
394 }
395
396 /*
397 * We don't support multiple tracepoint names for now.
398 */
399 if (strchr(tracepoint_name, ',')) {
400 fprintf(stderr, "Error: multiple tracepoint names are not supported at the moment.\n");
401 goto error;
402 }
403
404 /*
405 * Update *argc and *argv so our caller can keep parsing what follows.
406 */
407 consumed_args = argpar_state_get_ingested_orig_args(state);
408 assert(consumed_args >= 0);
409 *argc -= consumed_args;
410 *argv += consumed_args;
411
412 /* Need to specify a domain. */
413 if (domain_type == LTTNG_DOMAIN_NONE) {
414 fprintf(stderr, "Error: Please specify a domain (-k/-u/-j).\n");
415 goto error;
416 }
417
418 /* Validate event rule type against domain. */
419 switch (event_rule_type) {
420 case LTTNG_EVENT_RULE_TYPE_KPROBE:
421 case LTTNG_EVENT_RULE_TYPE_KRETPROBE:
422 case LTTNG_EVENT_RULE_TYPE_UPROBE:
423 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
424 if (domain_type != LTTNG_DOMAIN_KERNEL) {
425 fprintf(stderr, "Error: Event type not available for user-space tracing\n");
426 goto error;
427 }
428 break;
429
430 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
431 break;
432
433 default:
434 abort();
435 }
436
437 /*
438 * Adding a filter to a probe, function or userspace-probe would be
439 * denied by the kernel tracer as it's not supported at the moment. We
440 * do an early check here to warn the user.
441 */
442 if (filter && domain_type == LTTNG_DOMAIN_KERNEL) {
443 switch (event_rule_type) {
444 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
445 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
446 break;
447 default:
448 ERR("Filter expressions are not supported for %s events",
449 lttng_event_rule_type_str(event_rule_type));
450 goto error;
451 }
452 }
453
454 /* If --exclude/-x was passed, split it into an exclusion list. */
455 if (exclude) {
456 if (domain_type != LTTNG_DOMAIN_UST) {
457 fprintf(stderr, "Event name exclusions are not yet implemented for %s events",
458 get_domain_str(domain_type));
459 goto error;
460 }
461
462
463 if (create_exclusion_list_and_validate(tracepoint_name, exclude,
464 &exclusion_list) != 0) {
465 fprintf(stderr, "Failed to create exclusion list.\n");
466 goto error;
467 }
468 }
469
470 if (loglevel_str && event_rule_type != LTTNG_EVENT_RULE_TYPE_TRACEPOINT) {
471 fprintf(stderr, "Log levels are only application to tracepoint event rules.\n");
472 goto error;
473 }
474
475 /* Finally, create the event rule object. */
476 switch (event_rule_type) {
477 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
478 {
479 enum lttng_event_rule_status event_rule_status;
480
481 er = lttng_event_rule_tracepoint_create(domain_type);
482 if (!er) {
483 fprintf(stderr, "Failed to create tracepoint event rule.\n");
484 goto error;
485 }
486
487 /* Set pattern. */
488 event_rule_status =
489 lttng_event_rule_tracepoint_set_pattern(er, tracepoint_name);
490 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
491 fprintf(stderr, "Failed to set tracepoint pattern.\n");
492 goto error;
493 }
494
495 /* Set filter. */
496 if (filter) {
497 event_rule_status =
498 lttng_event_rule_tracepoint_set_filter(
499 er, filter);
500 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
501 fprintf(stderr, "Failed to set tracepoint filter expression.\n");
502 goto error;
503 }
504 }
505
506 /* Set exclusion list. */
507 if (exclusion_list) {
508 int n;
509
510 /* Count number of items in exclusion list. */
511 for (n = 0; exclusion_list[n]; n++);
512
513 event_rule_status =
514 lttng_event_rule_tracepoint_set_exclusions(er,
515 n, (const char **) exclusion_list);
516 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
517 fprintf(stderr, "Failed to set tracepoint exclusion list.\n");
518 goto error;
519 }
520 }
521
522 if (loglevel_str) {
523 int loglevel;
524
525 if (domain_type == LTTNG_DOMAIN_KERNEL) {
526 fprintf(stderr, "Log levels are not supported by the kernel tracer.\n");
527 goto error;
528 }
529
530 loglevel = parse_loglevel_string(
531 loglevel_str, domain_type);
532 if (loglevel < 0) {
533 fprintf(stderr, "Failed to parse `%s` as a log level.\n", loglevel_str);
534 goto error;
535 }
536
537 if (loglevel_only) {
538 event_rule_status =
539 lttng_event_rule_tracepoint_set_loglevel(
540 er, loglevel);
541 } else {
542 event_rule_status =
543 lttng_event_rule_tracepoint_set_loglevel_range(
544 er, loglevel);
545 }
546
547 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
548 fprintf(stderr, "Failed to set log level.\n");
549 goto error;
550 }
551 }
552
553 break;
554 }
555
556 case LTTNG_EVENT_RULE_TYPE_KPROBE:
557 {
558 enum lttng_event_rule_status event_rule_status;
559
560 er = lttng_event_rule_kprobe_create();
561 if (!er) {
562 fprintf(stderr, "Failed to create kprobe event rule.\n");
563 goto error;
564 }
565
566 event_rule_status = lttng_event_rule_kprobe_set_name(er, tracepoint_name);
567 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
568 fprintf(stderr, "Failed to set kprobe event rule's name.\n");
569 goto error;
570 }
571
572 assert(source);
573 event_rule_status = lttng_event_rule_kprobe_set_source(er, source);
574 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
575 fprintf(stderr, "Failed to set kprobe event rule's source.\n");
576 goto error;
577 }
578
579 break;
580 }
581
582 case LTTNG_EVENT_RULE_TYPE_UPROBE:
583 {
584 int ret;
585 enum lttng_event_rule_status event_rule_status;
586
587 ret = parse_userspace_probe_opts(source, &userspace_probe_location);
588 if (ret) {
589 fprintf(stderr, "Failed to parse userspace probe location.\n");
590 goto error;
591 }
592
593 er = lttng_event_rule_uprobe_create();
594 if (!er) {
595 fprintf(stderr, "Failed to create userspace probe event rule.\n");
596 goto error;
597 }
598
599 event_rule_status = lttng_event_rule_uprobe_set_location(er, userspace_probe_location);
600 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
601 fprintf(stderr, "Failed to set userspace probe event rule's location.\n");
602 goto error;
603 }
604
605 event_rule_status = lttng_event_rule_uprobe_set_name(er, tracepoint_name);
606 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
607 fprintf(stderr, "Failed to set userspace probe event rule's name.\n");
608 goto error;
609 }
610
611 break;
612 }
613
614 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
615 {
616 enum lttng_event_rule_status event_rule_status;
617
618 er = lttng_event_rule_syscall_create();
619 if (!er) {
620 fprintf(stderr, "Failed to create syscall event rule.\n");
621 goto error;
622 }
623
624 event_rule_status = lttng_event_rule_syscall_set_pattern(er, tracepoint_name);
625 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
626 fprintf(stderr, "Failed to set syscall event rule's pattern.\n");
627 goto error;
628 }
629
630 if (filter) {
631 event_rule_status = lttng_event_rule_syscall_set_filter(
632 er, filter);
633 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
634 fprintf(stderr, "Failed to set syscall event rule's filter expression.\n");
635 goto error;
636 }
637 }
638
639 break;
640 }
641
642 default:
643 fprintf(stderr, "%s: I don't support event rules of type `%s` at the moment.\n", __func__,
644 lttng_event_rule_type_str(event_rule_type));
645 goto error;
646 }
647
648 goto end;
649
650 error:
651 lttng_event_rule_destroy(er);
652 er = NULL;
653
654 end:
655 argpar_item_destroy(item);
656 free(error);
657 argpar_state_destroy(state);
658 free(filter);
659 free(exclude);
660 free(loglevel_str);
661 strutils_free_null_terminated_array_of_strings(exclusion_list);
662 lttng_userspace_probe_location_destroy(userspace_probe_location);
663 return er;
664 }
665
666 static
667 struct lttng_condition *handle_condition_event(int *argc, const char ***argv)
668 {
669 struct lttng_event_rule *er;
670 struct lttng_condition *c;
671
672 er = parse_event_rule(argc, argv);
673 if (!er) {
674 c = NULL;
675 goto end;
676 }
677
678 c = lttng_condition_event_rule_create(er);
679 if (!c) {
680 goto end;
681 }
682
683 end:
684 return c;
685 }
686
687 static
688 struct lttng_condition *handle_condition_session_consumed_size(int *argc, const char ***argv)
689 {
690 struct lttng_condition *cond = NULL;
691 struct argpar_state *state = NULL;
692 struct argpar_item *item = NULL;
693 const char *threshold_arg = NULL;
694 const char *session_name_arg = NULL;
695 uint64_t threshold;
696 char *error = NULL;
697 enum lttng_condition_status condition_status;
698
699 state = argpar_state_create(*argc, *argv, event_rule_opt_descrs);
700 if (!state) {
701 fprintf(stderr, "Failed to allocate an argpar state.\n");
702 goto error;
703 }
704
705 while (true) {
706 enum argpar_state_parse_next_status status;
707
708 ARGPAR_ITEM_DESTROY_AND_RESET(item);
709 status = argpar_state_parse_next(state, &item, &error);
710 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
711 fprintf(stderr, "Error: %s\n", error);
712 goto error;
713 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
714 /* Just stop parsing here. */
715 break;
716 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
717 break;
718 }
719
720 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
721
722 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
723 struct argpar_item_opt *item_opt =
724 (struct argpar_item_opt *) item;
725
726 switch (item_opt->descr->id) {
727 default:
728 abort();
729 }
730 } else {
731 struct argpar_item_non_opt *item_non_opt;
732
733 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
734
735 item_non_opt = (struct argpar_item_non_opt *) item;
736
737 switch (item_non_opt->non_opt_index) {
738 case 0:
739 session_name_arg = item_non_opt->arg;
740 break;
741 case 1:
742 threshold_arg = item_non_opt->arg;
743 break;
744 default:
745 fprintf(stderr, "Unexpected argument `%s`.\n",
746 item_non_opt->arg);
747 goto error;
748 }
749 }
750 }
751
752 *argc -= argpar_state_get_ingested_orig_args(state);
753 *argv += argpar_state_get_ingested_orig_args(state);
754
755 if (!session_name_arg) {
756 fprintf(stderr, "Missing session name argument.\n");
757 goto error;
758 }
759
760 if (!threshold_arg) {
761 fprintf(stderr, "Missing threshold argument.\n");
762 goto error;
763 }
764
765 if (utils_parse_size_suffix(threshold_arg, &threshold) != 0) {
766 fprintf(stderr, "Failed to parse `%s` as a size.\n", threshold_arg);
767 goto error;
768 }
769
770 cond = lttng_condition_session_consumed_size_create();
771 if (!cond) {
772 fprintf(stderr, "Failed to allocate a session consumed size condition.\n");
773 goto error;
774 }
775
776 condition_status = lttng_condition_session_consumed_size_set_session_name(
777 cond, session_name_arg);
778 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
779 fprintf(stderr, "Failed to set session consumed size condition session name.\n");
780 goto error;
781 }
782
783
784 condition_status = lttng_condition_session_consumed_size_set_threshold(
785 cond, threshold);
786 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
787 fprintf(stderr, "Failed to set session consumed size condition threshold.\n");
788 goto error;
789 }
790
791 goto end;
792
793 error:
794 lttng_condition_destroy(cond);
795 cond = NULL;
796
797 end:
798 argpar_state_destroy(state);
799 argpar_item_destroy(item);
800 free(error);
801 return cond;
802 }
803
804 static
805 struct lttng_condition *handle_condition_buffer_usage_high(int *argc, const char ***argv)
806 {
807 struct lttng_condition *cond = NULL;
808 struct argpar_state *state = NULL;
809 struct argpar_item *item = NULL;
810 const char *threshold_arg = NULL;
811 const char *session_name_arg = NULL;
812 uint64_t threshold;
813 char *error = NULL;
814 enum lttng_condition_status condition_status;
815
816 state = argpar_state_create(*argc, *argv, event_rule_opt_descrs);
817 if (!state) {
818 fprintf(stderr, "Failed to allocate an argpar state.\n");
819 goto error;
820 }
821
822 while (true) {
823 enum argpar_state_parse_next_status status;
824
825 ARGPAR_ITEM_DESTROY_AND_RESET(item);
826 status = argpar_state_parse_next(state, &item, &error);
827 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
828 fprintf(stderr, "Error: %s\n", error);
829 goto error;
830 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
831 /* Just stop parsing here. */
832 break;
833 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
834 break;
835 }
836
837 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
838
839 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
840 struct argpar_item_opt *item_opt =
841 (struct argpar_item_opt *) item;
842
843 switch (item_opt->descr->id) {
844 default:
845 abort();
846 }
847 } else {
848 struct argpar_item_non_opt *item_non_opt;
849
850 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
851
852 item_non_opt = (struct argpar_item_non_opt *) item;
853
854 switch (item_non_opt->non_opt_index) {
855 case 0:
856 session_name_arg = item_non_opt->arg;
857 break;
858 case 1:
859 threshold_arg = item_non_opt->arg;
860 break;
861 default:
862 fprintf(stderr, "Unexpected argument `%s`.\n",
863 item_non_opt->arg);
864 goto error;
865 }
866 }
867 }
868
869 *argc -= argpar_state_get_ingested_orig_args(state);
870 *argv += argpar_state_get_ingested_orig_args(state);
871
872 if (!session_name_arg) {
873 fprintf(stderr, "Missing session name argument.\n");
874 goto error;
875 }
876
877 if (!threshold_arg) {
878 fprintf(stderr, "Missing threshold argument.\n");
879 goto error;
880 }
881
882 if (utils_parse_size_suffix(threshold_arg, &threshold) != 0) {
883 fprintf(stderr, "Failed to parse `%s` as a size.\n", threshold_arg);
884 goto error;
885 }
886
887 cond = lttng_condition_session_consumed_size_create();
888 if (!cond) {
889 fprintf(stderr, "Failed to allocate a session consumed size condition.\n");
890 goto error;
891 }
892
893 condition_status = lttng_condition_session_consumed_size_set_session_name(
894 cond, session_name_arg);
895 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
896 fprintf(stderr, "Failed to set session consumed size condition session name.\n");
897 goto error;
898 }
899
900 condition_status = lttng_condition_session_consumed_size_set_threshold(
901 cond, threshold);
902 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
903 fprintf(stderr, "Failed to set session consumed size condition threshold.\n");
904 goto error;
905 }
906
907 goto end;
908
909 error:
910 lttng_condition_destroy(cond);
911 cond = NULL;
912
913 end:
914 argpar_state_destroy(state);
915 argpar_item_destroy(item);
916 free(error);
917 return cond;
918 }
919
920 static
921 struct lttng_condition *handle_condition_buffer_usage_low(int *argc, const char ***argv)
922 {
923 return NULL;
924 }
925
926 static
927 struct lttng_condition *handle_condition_session_rotation_ongoing(int *argc, const char ***argv)
928 {
929 return NULL;
930 }
931
932 static
933 struct lttng_condition *handle_condition_session_rotation_completed(int *argc, const char ***argv)
934 {
935 return NULL;
936 }
937
938 struct condition_descr {
939 const char *name;
940 struct lttng_condition *(*handler) (int *argc, const char ***argv);
941 };
942
943 static const
944 struct condition_descr condition_descrs[] = {
945 { "on-event", handle_condition_event },
946 { "on-session-consumed-size", handle_condition_session_consumed_size },
947 { "on-buffer-usage-high", handle_condition_buffer_usage_high },
948 { "on-buffer-usage-low", handle_condition_buffer_usage_low },
949 { "on-session-rotation-ongoing", handle_condition_session_rotation_ongoing },
950 { "on-session-rotation-completed", handle_condition_session_rotation_completed },
951 };
952
953 static
954 struct lttng_condition *parse_condition(int *argc, const char ***argv)
955 {
956 int i;
957 struct lttng_condition *cond;
958 const char *condition_name;
959 const struct condition_descr *descr = NULL;
960
961 if (*argc == 0) {
962 fprintf(stderr, "Missing condition name.\n");
963 goto error;
964 }
965
966 condition_name = (*argv)[0];
967
968 (*argc)--;
969 (*argv)++;
970
971 for (i = 0; i < ARRAY_SIZE(condition_descrs); i++) {
972 if (strcmp(condition_name, condition_descrs[i].name) == 0) {
973 descr = &condition_descrs[i];
974 break;
975 }
976 }
977
978 if (!descr) {
979 fprintf(stderr, "Unknown condition name: %s\n", condition_name);
980 goto error;
981 }
982
983 cond = descr->handler(argc, argv);
984 if (!cond) {
985 /* The handler has already printed an error message. */
986 goto error;
987 }
988
989 goto end;
990 error:
991 cond = NULL;
992 end:
993 return cond;
994 }
995
996
997 static
998 struct lttng_action *handle_action_notify(int *argc, const char ***argv)
999 {
1000 return lttng_action_notify_create();
1001 }
1002
1003 static const struct argpar_opt_descr no_opt_descrs[] = {
1004 ARGPAR_OPT_DESCR_SENTINEL
1005 };
1006
1007 /*
1008 * Generic handler for a kind of action that takes a session name as its sole
1009 * argument.
1010 */
1011
1012 static
1013 struct lttng_action *handle_action_simple_session(
1014 int *argc, const char ***argv,
1015 struct lttng_action *(*create_action_cb)(void),
1016 enum lttng_action_status (*set_session_name_cb)(struct lttng_action *, const char *),
1017 const char *action_name)
1018 {
1019 struct lttng_action *action = NULL;
1020 struct argpar_state *state = NULL;
1021 struct argpar_item *item = NULL;
1022 const char *session_name_arg = NULL;
1023 char *error = NULL;
1024 enum lttng_action_status action_status;
1025
1026 state = argpar_state_create(*argc, *argv, no_opt_descrs);
1027 if (!state) {
1028 fprintf(stderr, "Failed to allocate an argpar state.\n");
1029 goto error;
1030 }
1031
1032 while (true) {
1033 enum argpar_state_parse_next_status status;
1034 struct argpar_item_non_opt *item_non_opt;
1035
1036 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1037 status = argpar_state_parse_next(state, &item, &error);
1038 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1039 fprintf(stderr, "Error: %s\n", error);
1040 goto error;
1041 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1042 /* Just stop parsing here. */
1043 break;
1044 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1045 break;
1046 }
1047
1048 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1049 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
1050
1051 item_non_opt = (struct argpar_item_non_opt *) item;
1052
1053 switch (item_non_opt->non_opt_index) {
1054 case 0:
1055 session_name_arg = item_non_opt->arg;
1056 break;
1057 default:
1058 fprintf(stderr, "Unexpected argument `%s`.\n",
1059 item_non_opt->arg);
1060 goto error;
1061 }
1062 }
1063
1064 *argc -= argpar_state_get_ingested_orig_args(state);
1065 *argv += argpar_state_get_ingested_orig_args(state);
1066
1067 if (!session_name_arg) {
1068 fprintf(stderr, "Missing session name.\n");
1069 goto error;
1070 }
1071
1072 action = create_action_cb();
1073 if (!action) {
1074 fprintf(stderr,
1075 "Failed to allocate %s session action.\n", action_name);
1076 goto error;
1077 }
1078
1079 action_status = set_session_name_cb(action, session_name_arg);
1080 if (action_status != LTTNG_ACTION_STATUS_OK) {
1081 fprintf(stderr,
1082 "Failed to set action %s session's session name.\n",
1083 action_name);
1084 goto error;
1085 }
1086
1087 goto end;
1088
1089 error:
1090 lttng_action_destroy(action);
1091 action = NULL;
1092
1093 end:
1094 return action;
1095 }
1096
1097 static
1098 struct lttng_action *handle_action_start_session(int *argc,
1099 const char ***argv)
1100 {
1101 return handle_action_simple_session(argc, argv,
1102 lttng_action_start_session_create,
1103 lttng_action_start_session_set_session_name,
1104 "start");
1105 }
1106
1107 static
1108 struct lttng_action *handle_action_stop_session(int *argc,
1109 const char ***argv)
1110 {
1111 return handle_action_simple_session(argc, argv,
1112 lttng_action_stop_session_create,
1113 lttng_action_stop_session_set_session_name,
1114 "stop");
1115 }
1116
1117 static
1118 struct lttng_action *handle_action_rotate_session(int *argc,
1119 const char ***argv)
1120 {
1121 return handle_action_simple_session(argc, argv,
1122 lttng_action_rotate_session_create,
1123 lttng_action_rotate_session_set_session_name,
1124 "rotate");
1125 }
1126
1127 static const struct argpar_opt_descr snapshot_action_opt_descrs[] = {
1128 { OPT_NAME, 'n', "name", true },
1129 { OPT_MAX_SIZE, 'm', "max-size", true },
1130 { OPT_CTRL_URL, '\0', "ctrl-url", true },
1131 { OPT_DATA_URL, '\0', "data-url", true },
1132 ARGPAR_OPT_DESCR_SENTINEL
1133 };
1134
1135 static
1136 struct lttng_action *handle_action_snapshot_session(int *argc,
1137 const char ***argv)
1138 {
1139 struct lttng_action *action = NULL;
1140 struct argpar_state *state = NULL;
1141 struct argpar_item *item = NULL;
1142 const char *session_name_arg = NULL;
1143 char *snapshot_name_arg = NULL;
1144 char *ctrl_url_arg = NULL;
1145 char *data_url_arg = NULL;
1146 char *max_size_arg = NULL;
1147 const char *url_arg = NULL;
1148 char *error = NULL;
1149 enum lttng_action_status action_status;
1150 struct lttng_snapshot_output *snapshot_output = NULL;
1151 int ret;
1152
1153 state = argpar_state_create(*argc, *argv, snapshot_action_opt_descrs);
1154 if (!state) {
1155 fprintf(stderr, "Failed to allocate an argpar state.\n");
1156 goto error;
1157 }
1158
1159 while (true) {
1160 enum argpar_state_parse_next_status status;
1161
1162 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1163 status = argpar_state_parse_next(state, &item, &error);
1164 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1165 fprintf(stderr, "Error: %s\n", error);
1166 goto error;
1167 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1168 /* Just stop parsing here. */
1169 break;
1170 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1171 break;
1172 }
1173
1174 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1175
1176 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
1177 struct argpar_item_opt *item_opt =
1178 (struct argpar_item_opt *) item;
1179
1180 switch (item_opt->descr->id) {
1181 case OPT_NAME:
1182 if (!assign_string(&snapshot_name_arg, item_opt->arg, "--name/-n")) {
1183 goto error;
1184 }
1185 break;
1186
1187 case OPT_MAX_SIZE:
1188 if (!assign_string(&max_size_arg, item_opt->arg, "--max-size/-m")) {
1189 goto error;
1190 }
1191 break;
1192
1193 case OPT_CTRL_URL:
1194 if (!assign_string(&ctrl_url_arg, item_opt->arg, "--ctrl-url")) {
1195 goto error;
1196 }
1197 break;
1198
1199 case OPT_DATA_URL:
1200 if (!assign_string(&data_url_arg, item_opt->arg, "--data-url")) {
1201 goto error;
1202 }
1203 break;
1204
1205 default:
1206 abort();
1207 }
1208 } else {
1209 struct argpar_item_non_opt *item_non_opt;
1210
1211 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
1212
1213 item_non_opt = (struct argpar_item_non_opt *) item;
1214
1215 switch (item_non_opt->non_opt_index) {
1216 case 0:
1217 session_name_arg = item_non_opt->arg;
1218 break;
1219
1220 // FIXME: the use of a non-option argument for this is to
1221 // follow the syntax of `lttng snapshot record`. But otherwise,
1222 // I think an option argument would be best.
1223 case 1:
1224 url_arg = item_non_opt->arg;
1225 break;
1226
1227 default:
1228 fprintf(stderr, "Unexpected argument `%s`.\n",
1229 item_non_opt->arg);
1230 goto error;
1231 }
1232 }
1233 }
1234
1235 *argc -= argpar_state_get_ingested_orig_args(state);
1236 *argv += argpar_state_get_ingested_orig_args(state);
1237
1238 if (!session_name_arg) {
1239 fprintf(stderr, "Missing session name.\n");
1240 goto error;
1241 }
1242
1243 /* --ctrl-url and --data-url must come in pair. */
1244 if (ctrl_url_arg && !data_url_arg) {
1245 fprintf(stderr, "--ctrl-url is specified, but --data-url is missing.\n");
1246 goto error;
1247 }
1248
1249 if (!ctrl_url_arg && data_url_arg) {
1250 fprintf(stderr, "--data-url is specified, but --ctrl-url is missing.\n");
1251 goto error;
1252 }
1253
1254 /* --ctrl-url/--data-url and the non-option URL are mutually exclusive. */
1255 if (ctrl_url_arg && url_arg) {
1256 fprintf(stderr, "Both --ctrl-url/--data-url and the non-option URL argument "
1257 "can't be used together.\n");
1258 goto error;
1259 }
1260
1261 /*
1262 * Did the user specify an option that implies using a
1263 * custom/unregistered output?
1264 */
1265 if (url_arg || ctrl_url_arg) {
1266 snapshot_output = lttng_snapshot_output_create();
1267 if (!snapshot_output) {
1268 fprintf(stderr, "Failed to allocate a snapshot output.\n");
1269 goto error;
1270 }
1271 }
1272
1273 action = lttng_action_snapshot_session_create();
1274 if (!action) {
1275 fprintf(stderr,
1276 "Failed to allocate snapshot session action.\n");
1277 goto error;
1278 }
1279
1280 action_status = lttng_action_snapshot_session_set_session_name(
1281 action, session_name_arg);
1282 if (action_status != LTTNG_ACTION_STATUS_OK) {
1283 fprintf(stderr,
1284 "Failed to set action snapshot session's session name.\n");
1285 goto error;
1286 }
1287
1288 if (snapshot_name_arg) {
1289 if (!snapshot_output) {
1290 fprintf(stderr, "Can't provide a snapshot output name without a snapshot output destination.\n");
1291 goto error;
1292 }
1293
1294 ret = lttng_snapshot_output_set_name(snapshot_name_arg, snapshot_output);
1295 if (ret != 0) {
1296 fprintf(stderr, "Failed to set name of snapshot output.\n");
1297 goto error;
1298 }
1299 }
1300
1301 if (max_size_arg) {
1302 uint64_t max_size;
1303
1304 if (!snapshot_output) {
1305 fprintf(stderr, "Can't provide a snapshot output max size without a snapshot output destination.\n");
1306 goto error;
1307 }
1308
1309 ret = utils_parse_size_suffix(max_size_arg, &max_size);
1310 if (ret != 0) {
1311 fprintf(stderr, "Failed to parse `%s` as a size.\n", max_size_arg);
1312 goto error;
1313 }
1314
1315 ret = lttng_snapshot_output_set_size(max_size, snapshot_output);
1316 if (ret != 0) {
1317 fprintf(stderr, "Failed to set snapshot output's max size.\n");
1318 goto error;
1319 }
1320 }
1321
1322 if (url_arg) {
1323 /* One argument form, either net:// / net6:// or a local file path. */
1324
1325 if (strncmp(url_arg, "net://", strlen("net://")) == 0 ||
1326 strncmp(url_arg, "net6://", strlen("net6://")) == 0) {
1327 ret = lttng_snapshot_output_set_network_url(
1328 url_arg, snapshot_output);
1329 if (ret != 0) {
1330 fprintf(stderr, "Failed to parse %s as a network URL.\n", url_arg);
1331 goto error;
1332 }
1333 } else {
1334 ret = lttng_snapshot_output_set_local_path(
1335 url_arg, snapshot_output);
1336 if (ret != 0) {
1337 fprintf(stderr, "Failed to parse %s as a local path.\n", url_arg);
1338 goto error;
1339 }
1340 }
1341 }
1342
1343 if (ctrl_url_arg) {
1344 /*
1345 * Two argument form, network output with separate control and
1346 * data URLs.
1347 */
1348 ret = lttng_snapshot_output_set_network_urls(
1349 ctrl_url_arg, data_url_arg, snapshot_output);
1350 if (ret != 0) {
1351 fprintf(stderr, "Failed to parse `%s` and `%s` as control and data URLs.\n",
1352 ctrl_url_arg, data_url_arg);
1353 goto error;
1354 }
1355 }
1356
1357 if (snapshot_output) {
1358 action_status = lttng_action_snapshot_session_set_output(
1359 action, snapshot_output);
1360 if (action_status != LTTNG_ACTION_STATUS_OK) {
1361 fprintf(stderr, "Failed to set snapshot session action's output.\n");
1362 goto error;
1363 }
1364
1365 /* Ownership of `snapshot_output` has been transferred to the action. */
1366 snapshot_output = NULL;
1367 }
1368
1369 goto end;
1370
1371 error:
1372 lttng_action_destroy(action);
1373 action = NULL;
1374
1375 end:
1376 free(snapshot_name_arg);
1377 free(ctrl_url_arg);
1378 free(data_url_arg);
1379 free(snapshot_output);
1380 return action;
1381 }
1382
1383 struct action_descr {
1384 const char *name;
1385 struct lttng_action *(*handler) (int *argc, const char ***argv);
1386 };
1387
1388 static const
1389 struct action_descr action_descrs[] = {
1390 { "notify", handle_action_notify },
1391 { "start-session", handle_action_start_session },
1392 { "stop-session", handle_action_stop_session },
1393 { "rotate-session", handle_action_rotate_session },
1394 { "snapshot-session", handle_action_snapshot_session },
1395 };
1396
1397 static
1398 struct lttng_action *parse_action(int *argc, const char ***argv)
1399 {
1400 int i;
1401 struct lttng_action *action;
1402 const char *action_name;
1403 const struct action_descr *descr = NULL;
1404
1405 if (*argc == 0) {
1406 fprintf(stderr, "Missing action name.\n");
1407 goto error;
1408 }
1409
1410 action_name = (*argv)[0];
1411
1412 (*argc)--;
1413 (*argv)++;
1414
1415 for (i = 0; i < ARRAY_SIZE(action_descrs); i++) {
1416 if (strcmp(action_name, action_descrs[i].name) == 0) {
1417 descr = &action_descrs[i];
1418 break;
1419 }
1420 }
1421
1422 if (!descr) {
1423 fprintf(stderr, "Unknown action name: %s\n", action_name);
1424 goto error;
1425 }
1426
1427 action = descr->handler(argc, argv);
1428 if (!action) {
1429 /* The handler has already printed an error message. */
1430 goto error;
1431 }
1432
1433 goto end;
1434 error:
1435 action = NULL;
1436 end:
1437 return action;
1438 }
1439
1440 static const
1441 struct argpar_opt_descr add_trigger_options[] = {
1442 { OPT_HELP, 'h', "help", false },
1443 { OPT_LIST_OPTIONS, '\0', "list-options", false },
1444 { OPT_CONDITION, '\0', "condition", false },
1445 { OPT_ACTION, '\0', "action", false },
1446 { OPT_ID, '\0', "id", true },
1447 { OPT_FIRE_ONCE_AFTER, '\0', "fire-once-after", true },
1448 { OPT_FIRE_EVERY, '\0', "fire-every", true },
1449 ARGPAR_OPT_DESCR_SENTINEL,
1450 };
1451
1452 static
1453 void lttng_actions_destructor(void *p)
1454 {
1455 struct lttng_action *action = p;
1456
1457 lttng_action_destroy(action);
1458 }
1459
1460 int cmd_add_trigger(int argc, const char **argv)
1461 {
1462 int ret;
1463 int my_argc = argc - 1;
1464 const char **my_argv = argv + 1;
1465 struct lttng_condition *condition = NULL;
1466 struct lttng_dynamic_pointer_array actions;
1467 struct argpar_state *argpar_state = NULL;
1468 struct argpar_item *argpar_item = NULL;
1469 struct lttng_action *action_group = NULL;
1470 struct lttng_action *action = NULL;
1471 struct lttng_trigger *trigger = NULL;
1472 char *error = NULL;
1473 char *id = NULL;
1474 int i;
1475 char *fire_once_after_str = NULL;
1476 char *fire_every_str = NULL;
1477
1478 lttng_dynamic_pointer_array_init(&actions, lttng_actions_destructor);
1479
1480 while (true) {
1481 enum argpar_state_parse_next_status status;
1482 struct argpar_item_opt *item_opt;
1483 int ingested_args;
1484
1485 argpar_state_destroy(argpar_state);
1486 argpar_state = argpar_state_create(my_argc, my_argv,
1487 add_trigger_options);
1488 if (!argpar_state) {
1489 fprintf(stderr, "Failed to create argpar state.\n");
1490 goto error;
1491 }
1492
1493 status = argpar_state_parse_next(argpar_state, &argpar_item, &error);
1494
1495 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1496 fprintf(stderr, "Error: %s\n", error);
1497 goto error;
1498 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1499 fprintf(stderr, "%s\n", error);
1500 goto error;
1501 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1502 break;
1503 }
1504
1505 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1506
1507 if (argpar_item->type == ARGPAR_ITEM_TYPE_NON_OPT) {
1508 struct argpar_item_non_opt *item_non_opt =
1509 (struct argpar_item_non_opt *) argpar_item;
1510
1511 fprintf(stderr, "Unexpected argument `%s`.\n",
1512 item_non_opt->arg);
1513 goto error;
1514 }
1515
1516 item_opt = (struct argpar_item_opt *) argpar_item;
1517
1518 ingested_args = argpar_state_get_ingested_orig_args(
1519 argpar_state);
1520
1521 my_argc -= ingested_args;
1522 my_argv += ingested_args;
1523
1524 switch (item_opt->descr->id) {
1525 case OPT_HELP:
1526 SHOW_HELP();
1527 ret = 0;
1528 goto end;
1529
1530 case OPT_LIST_OPTIONS:
1531 list_cmd_options_argpar(stdout, add_trigger_options);
1532 ret = 0;
1533 goto end;
1534
1535 case OPT_CONDITION:
1536 {
1537 if (condition) {
1538 fprintf(stderr, "A --condition was already given.\n");
1539 goto error;
1540 }
1541
1542 condition = parse_condition(&my_argc, &my_argv);
1543 if (!condition) {
1544 /*
1545 * An error message was already printed by
1546 * parse_condition.
1547 */
1548 goto error;
1549 }
1550
1551 break;
1552 }
1553
1554 case OPT_ACTION:
1555 {
1556 action = parse_action(&my_argc, &my_argv);
1557 if (!action) {
1558 /*
1559 * An error message was already printed by
1560 * parse_condition.
1561 */
1562 goto error;
1563 }
1564
1565 ret = lttng_dynamic_pointer_array_add_pointer(
1566 &actions, action);
1567 if (ret) {
1568 fprintf(stderr, "Failed to add pointer to pointer array.\n");
1569 goto error;
1570 }
1571
1572 /* Ownership of the action was transferred to the group. */
1573 action = NULL;
1574
1575 break;
1576 }
1577
1578 case OPT_ID:
1579 {
1580 if (!assign_string(&id, item_opt->arg, "--id")) {
1581 goto error;
1582 }
1583
1584 break;
1585 }
1586
1587 case OPT_FIRE_ONCE_AFTER:
1588 {
1589 if (!assign_string(&fire_once_after_str, item_opt->arg,
1590 "--fire-once-after")) {
1591 goto error;
1592 }
1593 break;
1594 }
1595
1596 case OPT_FIRE_EVERY:
1597 {
1598 if (!assign_string(&fire_every_str, item_opt->arg,
1599 "--fire-every")) {
1600 goto error;
1601 }
1602 break;
1603 }
1604
1605 default:
1606 abort();
1607 }
1608 }
1609
1610 if (!condition) {
1611 fprintf(stderr, "Missing --condition.\n");
1612 goto error;
1613 }
1614
1615 if (lttng_dynamic_pointer_array_get_count(&actions) == 0) {
1616 fprintf(stderr, "Need at least one --action.\n");
1617 goto error;
1618 }
1619
1620 if (fire_every_str && fire_once_after_str) {
1621 fprintf(stderr, "Can't specify both --fire-once-after and --fire-every.\n");
1622 goto error;
1623 }
1624
1625 action_group = lttng_action_group_create();
1626 if (!action_group) {
1627 goto error;
1628 }
1629
1630 for (i = 0; i < lttng_dynamic_pointer_array_get_count(&actions); i++) {
1631 enum lttng_action_status status;
1632
1633 action = lttng_dynamic_pointer_array_steal_pointer(&actions, i);
1634
1635 status = lttng_action_group_add_action(
1636 action_group, action);
1637 if (status != LTTNG_ACTION_STATUS_OK) {
1638 goto error;
1639 }
1640
1641 /* Ownership of the action was transferred to the group. */
1642 action = NULL;
1643 }
1644
1645
1646 trigger = lttng_trigger_create(condition, action_group);
1647 if (!trigger) {
1648 goto error;
1649 }
1650
1651 /*
1652 * Ownership of the condition and action group was transferred to the
1653 * trigger.
1654 */
1655 condition = NULL;
1656 action_group = NULL;
1657
1658 if (id) {
1659 enum lttng_trigger_status trigger_status =
1660 lttng_trigger_set_name(trigger, id);
1661 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
1662 fprintf(stderr, "Failed to set trigger id.\n");
1663 goto error;
1664 }
1665 }
1666
1667 if (fire_once_after_str) {
1668 unsigned long long threshold;
1669 enum lttng_trigger_status trigger_status;
1670
1671 if (utils_parse_unsigned_long_long(fire_once_after_str, &threshold) != 0) {
1672 fprintf(stderr, "Failed to parse `%s` as an integer.\n", fire_once_after_str);
1673 goto error;
1674 }
1675
1676 trigger_status = lttng_trigger_set_firing_policy(trigger,
1677 LTTNG_TRIGGER_FIRE_ONCE_AFTER_N, threshold);
1678 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
1679 fprintf(stderr, "Failed to set trigger's firing policy.\n");
1680 goto error;
1681 }
1682 }
1683
1684 if (fire_every_str) {
1685 unsigned long long threshold;
1686 enum lttng_trigger_status trigger_status;
1687
1688 if (utils_parse_unsigned_long_long(fire_every_str, &threshold) != 0) {
1689 fprintf(stderr, "Failed to parse `%s` as an integer.\n", fire_every_str);
1690 goto error;
1691 }
1692
1693 trigger_status = lttng_trigger_set_firing_policy(trigger,
1694 LTTNG_TRIGGER_FIRE_EVERY_N, threshold);
1695 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
1696 fprintf(stderr, "Failed to set trigger's firing policy.\n");
1697 goto error;
1698 }
1699 }
1700
1701 ret = lttng_register_trigger(trigger);
1702 if (ret) {
1703 fprintf(stderr, "Failed to register trigger: %s.\n",
1704 lttng_strerror(ret));
1705 goto error;
1706 }
1707
1708 printf("Trigger registered successfully.\n");
1709
1710 goto end;
1711
1712 error:
1713 ret = 1;
1714
1715 end:
1716 argpar_state_destroy(argpar_state);
1717 lttng_dynamic_pointer_array_reset(&actions);
1718 lttng_condition_destroy(condition);
1719 lttng_action_destroy(action_group);
1720 lttng_trigger_destroy(trigger);
1721 free(id);
1722 free(fire_once_after_str);
1723 free(fire_every_str);
1724 // TODO: check what else to free
1725
1726 return ret;
1727 }
This page took 0.11378 seconds and 5 git commands to generate.