3 #include "../command.h"
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"
18 #ifdef LTTNG_EMBED_HELP
19 static const char help_msg
[] =
20 #include <lttng-add-trigger.1.h>
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 },
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 },
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" },
79 ARGPAR_OPT_DESCR_SENTINEL
83 bool assign_domain_type(enum lttng_domain_type
*dest
,
84 enum lttng_domain_type src
)
88 if (*dest
== LTTNG_DOMAIN_NONE
|| *dest
== src
) {
92 fprintf(stderr
, "Error: Multiple domains specified.\n");
100 bool assign_event_rule_type(enum lttng_event_rule_type
*dest
,
101 enum lttng_event_rule_type src
)
105 if (*dest
== LTTNG_EVENT_RULE_TYPE_UNKNOWN
|| *dest
== src
) {
109 fprintf(stderr
, "Error: Multiple event type not supported.\n");
117 bool assign_string(char **dest
, const char *src
, const char *opt_name
)
123 "Duplicate %s given.\n", opt_name
);
129 fprintf(stderr
, "Failed to allocate %s string.\n", opt_name
);
143 /* This is defined in enable_events.c. */
145 int create_exclusion_list_and_validate(const char *event_name
,
146 const char *exclusions_arg
,
147 char ***exclusion_list
);
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.
154 int parse_loglevel_string(const char *str
, enum lttng_domain_type domain_type
)
157 switch (domain_type
) {
158 case LTTNG_DOMAIN_UST
:
159 return loglevel_str_to_value(str
);
161 case LTTNG_DOMAIN_LOG4J
:
162 return loglevel_log4j_str_to_value(str
);
164 case LTTNG_DOMAIN_JUL
:
165 return loglevel_jul_str_to_value(str
);
167 case LTTNG_DOMAIN_PYTHON
:
168 return loglevel_python_str_to_value(str
);
171 /* Invalid domain type. */
177 struct lttng_event_rule
*parse_event_rule(int *argc
, const char ***argv
)
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
;
185 int consumed_args
= -1;
186 struct lttng_userspace_probe_location
*userspace_probe_location
= NULL
;
188 /* Was the -a/--all flag provided? */
189 bool all_events
= false;
191 /* Tracepoint name (non-option argument) */
192 const char *tracepoint_name
= NULL
;
194 /* Holds the argument of --probe / --userspace-probe. */
201 char *exclude
= NULL
;
202 char **exclusion_list
= NULL
;
205 char *loglevel_str
= NULL
;
206 bool loglevel_only
= false;
208 state
= argpar_state_create(*argc
, *argv
, event_rule_opt_descrs
);
210 fprintf(stderr
, "Failed to allocate an argpar state.\n");
215 enum argpar_state_parse_next_status status
;
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
);
222 } else if (status
== ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT
) {
223 /* Just stop parsing here. */
225 } else if (status
== ARGPAR_STATE_PARSE_NEXT_STATUS_END
) {
229 assert(status
== ARGPAR_STATE_PARSE_NEXT_STATUS_OK
);
231 if (item
->type
== ARGPAR_ITEM_TYPE_OPT
) {
232 struct argpar_item_opt
*item_opt
=
233 (struct argpar_item_opt
*) item
;
235 switch (item_opt
->descr
->id
) {
238 if (!assign_domain_type(&domain_type
, LTTNG_DOMAIN_UST
)) {
244 if (!assign_domain_type(&domain_type
, LTTNG_DOMAIN_KERNEL
)) {
250 if (!assign_domain_type(&domain_type
, LTTNG_DOMAIN_LOG4J
)) {
256 if (!assign_domain_type(&domain_type
, LTTNG_DOMAIN_JUL
)) {
262 if (!assign_domain_type(&domain_type
, LTTNG_DOMAIN_PYTHON
)) {
267 /* Event rule types */
269 if (!assign_event_rule_type(&event_rule_type
,
270 LTTNG_EVENT_RULE_TYPE_KRETPROBE
)) {
276 if (!assign_event_rule_type(&event_rule_type
,
277 LTTNG_EVENT_RULE_TYPE_KPROBE
)) {
281 if (!assign_string(&source
, item_opt
->arg
, "source")) {
287 case OPT_USERSPACE_PROBE
:
288 if (!assign_event_rule_type(&event_rule_type
,
289 LTTNG_EVENT_RULE_TYPE_UPROBE
)) {
293 if (!assign_string(&source
, item_opt
->arg
, "source")) {
299 if (!assign_event_rule_type(&event_rule_type
,
300 LTTNG_EVENT_RULE_TYPE_SYSCALL
)) {
306 if (!assign_event_rule_type(&event_rule_type
,
307 LTTNG_EVENT_RULE_TYPE_TRACEPOINT
)) {
317 if (!assign_string(&filter
, item_opt
->arg
, "--filter/-f")) {
323 if (!assign_string(&exclude
, item_opt
->arg
, "--exclude/-x")) {
329 case OPT_LOGLEVEL_ONLY
:
330 if (!assign_string(&loglevel_str
, item_opt
->arg
, "--loglevel/--loglevel-only")) {
334 loglevel_only
= item_opt
->descr
->id
== OPT_LOGLEVEL_ONLY
;
341 struct argpar_item_non_opt
*item_non_opt
=
342 (struct argpar_item_non_opt
*) item
;
345 * Don't accept two non-option arguments/tracepoint
348 if (tracepoint_name
) {
350 "Error: Unexpected argument: %s\n",
355 tracepoint_name
= item_non_opt
->arg
;
359 if (event_rule_type
== LTTNG_EVENT_RULE_TYPE_UNKNOWN
) {
360 event_rule_type
= LTTNG_EVENT_RULE_TYPE_TRACEPOINT
;
364 * Option -a is applicable to event rules of type tracepoint and
365 * syscall, and it is equivalent to using "*" as the tracepoint name.
368 switch (event_rule_type
) {
369 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT
:
370 case LTTNG_EVENT_RULE_TYPE_SYSCALL
:
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
));
378 if (tracepoint_name
) {
379 fprintf(stderr
, "Error: Can't provide a tracepoint name with -a/--all.\n");
383 /* In which case, it's equivalent to tracepoint name "*". */
384 tracepoint_name
= "*";
388 * A tracepoint name (or -a, for the event rule types that accept it)
391 if (!tracepoint_name
) {
392 fprintf(stderr
, "Error: Need to provide either a tracepoint name or -a/--all.\n");
397 * We don't support multiple tracepoint names for now.
399 if (strchr(tracepoint_name
, ',')) {
400 fprintf(stderr
, "Error: multiple tracepoint names are not supported at the moment.\n");
405 * Update *argc and *argv so our caller can keep parsing what follows.
407 consumed_args
= argpar_state_get_ingested_orig_args(state
);
408 assert(consumed_args
>= 0);
409 *argc
-= consumed_args
;
410 *argv
+= consumed_args
;
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");
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");
430 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT
:
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.
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
:
448 ERR("Filter expressions are not supported for %s events",
449 lttng_event_rule_type_str(event_rule_type
));
454 /* If --exclude/-x was passed, split it into an exclusion list. */
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
));
463 if (create_exclusion_list_and_validate(tracepoint_name
, exclude
,
464 &exclusion_list
) != 0) {
465 fprintf(stderr
, "Failed to create exclusion list.\n");
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");
475 /* Finally, create the event rule object. */
476 switch (event_rule_type
) {
477 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT
:
479 enum lttng_event_rule_status event_rule_status
;
481 er
= lttng_event_rule_tracepoint_create(domain_type
);
483 fprintf(stderr
, "Failed to create tracepoint event rule.\n");
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");
498 lttng_event_rule_tracepoint_set_filter(
500 if (event_rule_status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
501 fprintf(stderr
, "Failed to set tracepoint filter expression.\n");
506 /* Set exclusion list. */
507 if (exclusion_list
) {
510 /* Count number of items in exclusion list. */
511 for (n
= 0; exclusion_list
[n
]; n
++);
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");
525 if (domain_type
== LTTNG_DOMAIN_KERNEL
) {
526 fprintf(stderr
, "Log levels are not supported by the kernel tracer.\n");
530 loglevel
= parse_loglevel_string(
531 loglevel_str
, domain_type
);
533 fprintf(stderr
, "Failed to parse `%s` as a log level.\n", loglevel_str
);
539 lttng_event_rule_tracepoint_set_loglevel(
543 lttng_event_rule_tracepoint_set_loglevel_range(
547 if (event_rule_status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
548 fprintf(stderr
, "Failed to set log level.\n");
556 case LTTNG_EVENT_RULE_TYPE_KPROBE
:
558 enum lttng_event_rule_status event_rule_status
;
560 er
= lttng_event_rule_kprobe_create();
562 fprintf(stderr
, "Failed to create kprobe event rule.\n");
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");
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");
582 case LTTNG_EVENT_RULE_TYPE_UPROBE
:
585 enum lttng_event_rule_status event_rule_status
;
587 ret
= parse_userspace_probe_opts(source
, &userspace_probe_location
);
589 fprintf(stderr
, "Failed to parse userspace probe location.\n");
593 er
= lttng_event_rule_uprobe_create();
595 fprintf(stderr
, "Failed to create userspace probe event rule.\n");
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");
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");
614 case LTTNG_EVENT_RULE_TYPE_SYSCALL
:
616 enum lttng_event_rule_status event_rule_status
;
618 er
= lttng_event_rule_syscall_create();
620 fprintf(stderr
, "Failed to create syscall event rule.\n");
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");
631 event_rule_status
= lttng_event_rule_syscall_set_filter(
633 if (event_rule_status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
634 fprintf(stderr
, "Failed to set syscall event rule's filter expression.\n");
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
));
651 lttng_event_rule_destroy(er
);
655 argpar_item_destroy(item
);
657 argpar_state_destroy(state
);
661 strutils_free_null_terminated_array_of_strings(exclusion_list
);
662 lttng_userspace_probe_location_destroy(userspace_probe_location
);
667 struct lttng_condition
*handle_condition_event(int *argc
, const char ***argv
)
669 struct lttng_event_rule
*er
;
670 struct lttng_condition
*c
;
672 er
= parse_event_rule(argc
, argv
);
678 c
= lttng_condition_event_rule_create(er
);
688 struct lttng_condition
*handle_condition_session_consumed_size(int *argc
, const char ***argv
)
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
;
697 enum lttng_condition_status condition_status
;
699 state
= argpar_state_create(*argc
, *argv
, event_rule_opt_descrs
);
701 fprintf(stderr
, "Failed to allocate an argpar state.\n");
706 enum argpar_state_parse_next_status status
;
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
);
713 } else if (status
== ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT
) {
714 /* Just stop parsing here. */
716 } else if (status
== ARGPAR_STATE_PARSE_NEXT_STATUS_END
) {
720 assert(status
== ARGPAR_STATE_PARSE_NEXT_STATUS_OK
);
722 if (item
->type
== ARGPAR_ITEM_TYPE_OPT
) {
723 struct argpar_item_opt
*item_opt
=
724 (struct argpar_item_opt
*) item
;
726 switch (item_opt
->descr
->id
) {
731 struct argpar_item_non_opt
*item_non_opt
;
733 assert(item
->type
== ARGPAR_ITEM_TYPE_NON_OPT
);
735 item_non_opt
= (struct argpar_item_non_opt
*) item
;
737 switch (item_non_opt
->non_opt_index
) {
739 session_name_arg
= item_non_opt
->arg
;
742 threshold_arg
= item_non_opt
->arg
;
745 fprintf(stderr
, "Unexpected argument `%s`.\n",
752 *argc
-= argpar_state_get_ingested_orig_args(state
);
753 *argv
+= argpar_state_get_ingested_orig_args(state
);
755 if (!session_name_arg
) {
756 fprintf(stderr
, "Missing session name argument.\n");
760 if (!threshold_arg
) {
761 fprintf(stderr
, "Missing threshold argument.\n");
765 if (utils_parse_size_suffix(threshold_arg
, &threshold
) != 0) {
766 fprintf(stderr
, "Failed to parse `%s` as a size.\n", threshold_arg
);
770 cond
= lttng_condition_session_consumed_size_create();
772 fprintf(stderr
, "Failed to allocate a session consumed size condition.\n");
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");
784 condition_status
= lttng_condition_session_consumed_size_set_threshold(
786 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
787 fprintf(stderr
, "Failed to set session consumed size condition threshold.\n");
794 lttng_condition_destroy(cond
);
798 argpar_state_destroy(state
);
799 argpar_item_destroy(item
);
805 struct lttng_condition
*handle_condition_buffer_usage_high(int *argc
, const char ***argv
)
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
;
814 enum lttng_condition_status condition_status
;
816 state
= argpar_state_create(*argc
, *argv
, event_rule_opt_descrs
);
818 fprintf(stderr
, "Failed to allocate an argpar state.\n");
823 enum argpar_state_parse_next_status status
;
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
);
830 } else if (status
== ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT
) {
831 /* Just stop parsing here. */
833 } else if (status
== ARGPAR_STATE_PARSE_NEXT_STATUS_END
) {
837 assert(status
== ARGPAR_STATE_PARSE_NEXT_STATUS_OK
);
839 if (item
->type
== ARGPAR_ITEM_TYPE_OPT
) {
840 struct argpar_item_opt
*item_opt
=
841 (struct argpar_item_opt
*) item
;
843 switch (item_opt
->descr
->id
) {
848 struct argpar_item_non_opt
*item_non_opt
;
850 assert(item
->type
== ARGPAR_ITEM_TYPE_NON_OPT
);
852 item_non_opt
= (struct argpar_item_non_opt
*) item
;
854 switch (item_non_opt
->non_opt_index
) {
856 session_name_arg
= item_non_opt
->arg
;
859 threshold_arg
= item_non_opt
->arg
;
862 fprintf(stderr
, "Unexpected argument `%s`.\n",
869 *argc
-= argpar_state_get_ingested_orig_args(state
);
870 *argv
+= argpar_state_get_ingested_orig_args(state
);
872 if (!session_name_arg
) {
873 fprintf(stderr
, "Missing session name argument.\n");
877 if (!threshold_arg
) {
878 fprintf(stderr
, "Missing threshold argument.\n");
882 if (utils_parse_size_suffix(threshold_arg
, &threshold
) != 0) {
883 fprintf(stderr
, "Failed to parse `%s` as a size.\n", threshold_arg
);
887 cond
= lttng_condition_session_consumed_size_create();
889 fprintf(stderr
, "Failed to allocate a session consumed size condition.\n");
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");
900 condition_status
= lttng_condition_session_consumed_size_set_threshold(
902 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
903 fprintf(stderr
, "Failed to set session consumed size condition threshold.\n");
910 lttng_condition_destroy(cond
);
914 argpar_state_destroy(state
);
915 argpar_item_destroy(item
);
921 struct lttng_condition
*handle_condition_buffer_usage_low(int *argc
, const char ***argv
)
927 struct lttng_condition
*handle_condition_session_rotation_ongoing(int *argc
, const char ***argv
)
933 struct lttng_condition
*handle_condition_session_rotation_completed(int *argc
, const char ***argv
)
938 struct condition_descr
{
940 struct lttng_condition
*(*handler
) (int *argc
, const char ***argv
);
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
},
954 struct lttng_condition
*parse_condition(int *argc
, const char ***argv
)
957 struct lttng_condition
*cond
;
958 const char *condition_name
;
959 const struct condition_descr
*descr
= NULL
;
962 fprintf(stderr
, "Missing condition name.\n");
966 condition_name
= (*argv
)[0];
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
];
979 fprintf(stderr
, "Unknown condition name: %s\n", condition_name
);
983 cond
= descr
->handler(argc
, argv
);
985 /* The handler has already printed an error message. */
998 struct lttng_action
*handle_action_notify(int *argc
, const char ***argv
)
1000 return lttng_action_notify_create();
1003 static const struct argpar_opt_descr no_opt_descrs
[] = {
1004 ARGPAR_OPT_DESCR_SENTINEL
1008 * Generic handler for a kind of action that takes a session name as its sole
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
)
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
;
1024 enum lttng_action_status action_status
;
1026 state
= argpar_state_create(*argc
, *argv
, no_opt_descrs
);
1028 fprintf(stderr
, "Failed to allocate an argpar state.\n");
1033 enum argpar_state_parse_next_status status
;
1034 struct argpar_item_non_opt
*item_non_opt
;
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
);
1041 } else if (status
== ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT
) {
1042 /* Just stop parsing here. */
1044 } else if (status
== ARGPAR_STATE_PARSE_NEXT_STATUS_END
) {
1048 assert(status
== ARGPAR_STATE_PARSE_NEXT_STATUS_OK
);
1049 assert(item
->type
== ARGPAR_ITEM_TYPE_NON_OPT
);
1051 item_non_opt
= (struct argpar_item_non_opt
*) item
;
1053 switch (item_non_opt
->non_opt_index
) {
1055 session_name_arg
= item_non_opt
->arg
;
1058 fprintf(stderr
, "Unexpected argument `%s`.\n",
1064 *argc
-= argpar_state_get_ingested_orig_args(state
);
1065 *argv
+= argpar_state_get_ingested_orig_args(state
);
1067 if (!session_name_arg
) {
1068 fprintf(stderr
, "Missing session name.\n");
1072 action
= create_action_cb();
1075 "Failed to allocate %s session action.\n", action_name
);
1079 action_status
= set_session_name_cb(action
, session_name_arg
);
1080 if (action_status
!= LTTNG_ACTION_STATUS_OK
) {
1082 "Failed to set action %s session's session name.\n",
1090 lttng_action_destroy(action
);
1098 struct lttng_action
*handle_action_start_session(int *argc
,
1101 return handle_action_simple_session(argc
, argv
,
1102 lttng_action_start_session_create
,
1103 lttng_action_start_session_set_session_name
,
1108 struct lttng_action
*handle_action_stop_session(int *argc
,
1111 return handle_action_simple_session(argc
, argv
,
1112 lttng_action_stop_session_create
,
1113 lttng_action_stop_session_set_session_name
,
1118 struct lttng_action
*handle_action_rotate_session(int *argc
,
1121 return handle_action_simple_session(argc
, argv
,
1122 lttng_action_rotate_session_create
,
1123 lttng_action_rotate_session_set_session_name
,
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
1136 struct lttng_action
*handle_action_snapshot_session(int *argc
,
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
;
1149 enum lttng_action_status action_status
;
1150 struct lttng_snapshot_output
*snapshot_output
= NULL
;
1153 state
= argpar_state_create(*argc
, *argv
, snapshot_action_opt_descrs
);
1155 fprintf(stderr
, "Failed to allocate an argpar state.\n");
1160 enum argpar_state_parse_next_status status
;
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
);
1167 } else if (status
== ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT
) {
1168 /* Just stop parsing here. */
1170 } else if (status
== ARGPAR_STATE_PARSE_NEXT_STATUS_END
) {
1174 assert(status
== ARGPAR_STATE_PARSE_NEXT_STATUS_OK
);
1176 if (item
->type
== ARGPAR_ITEM_TYPE_OPT
) {
1177 struct argpar_item_opt
*item_opt
=
1178 (struct argpar_item_opt
*) item
;
1180 switch (item_opt
->descr
->id
) {
1182 if (!assign_string(&snapshot_name_arg
, item_opt
->arg
, "--name/-n")) {
1188 if (!assign_string(&max_size_arg
, item_opt
->arg
, "--max-size/-m")) {
1194 if (!assign_string(&ctrl_url_arg
, item_opt
->arg
, "--ctrl-url")) {
1200 if (!assign_string(&data_url_arg
, item_opt
->arg
, "--data-url")) {
1209 struct argpar_item_non_opt
*item_non_opt
;
1211 assert(item
->type
== ARGPAR_ITEM_TYPE_NON_OPT
);
1213 item_non_opt
= (struct argpar_item_non_opt
*) item
;
1215 switch (item_non_opt
->non_opt_index
) {
1217 session_name_arg
= item_non_opt
->arg
;
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.
1224 url_arg
= item_non_opt
->arg
;
1228 fprintf(stderr
, "Unexpected argument `%s`.\n",
1235 *argc
-= argpar_state_get_ingested_orig_args(state
);
1236 *argv
+= argpar_state_get_ingested_orig_args(state
);
1238 if (!session_name_arg
) {
1239 fprintf(stderr
, "Missing session name.\n");
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");
1249 if (!ctrl_url_arg
&& data_url_arg
) {
1250 fprintf(stderr
, "--data-url is specified, but --ctrl-url is missing.\n");
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");
1262 * Did the user specify an option that implies using a
1263 * custom/unregistered output?
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");
1273 action
= lttng_action_snapshot_session_create();
1276 "Failed to allocate snapshot session action.\n");
1280 action_status
= lttng_action_snapshot_session_set_session_name(
1281 action
, session_name_arg
);
1282 if (action_status
!= LTTNG_ACTION_STATUS_OK
) {
1284 "Failed to set action snapshot session's session name.\n");
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");
1294 ret
= lttng_snapshot_output_set_name(snapshot_name_arg
, snapshot_output
);
1296 fprintf(stderr
, "Failed to set name of snapshot output.\n");
1304 if (!snapshot_output
) {
1305 fprintf(stderr
, "Can't provide a snapshot output max size without a snapshot output destination.\n");
1309 ret
= utils_parse_size_suffix(max_size_arg
, &max_size
);
1311 fprintf(stderr
, "Failed to parse `%s` as a size.\n", max_size_arg
);
1315 ret
= lttng_snapshot_output_set_size(max_size
, snapshot_output
);
1317 fprintf(stderr
, "Failed to set snapshot output's max size.\n");
1323 /* One argument form, either net:// / net6:// or a local file path. */
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
);
1330 fprintf(stderr
, "Failed to parse %s as a network URL.\n", url_arg
);
1334 ret
= lttng_snapshot_output_set_local_path(
1335 url_arg
, snapshot_output
);
1337 fprintf(stderr
, "Failed to parse %s as a local path.\n", url_arg
);
1345 * Two argument form, network output with separate control and
1348 ret
= lttng_snapshot_output_set_network_urls(
1349 ctrl_url_arg
, data_url_arg
, snapshot_output
);
1351 fprintf(stderr
, "Failed to parse `%s` and `%s` as control and data URLs.\n",
1352 ctrl_url_arg
, data_url_arg
);
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");
1365 /* Ownership of `snapshot_output` has been transferred to the action. */
1366 snapshot_output
= NULL
;
1372 lttng_action_destroy(action
);
1376 free(snapshot_name_arg
);
1379 free(snapshot_output
);
1383 struct action_descr
{
1385 struct lttng_action
*(*handler
) (int *argc
, const char ***argv
);
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
},
1398 struct lttng_action
*parse_action(int *argc
, const char ***argv
)
1401 struct lttng_action
*action
;
1402 const char *action_name
;
1403 const struct action_descr
*descr
= NULL
;
1406 fprintf(stderr
, "Missing action name.\n");
1410 action_name
= (*argv
)[0];
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
];
1423 fprintf(stderr
, "Unknown action name: %s\n", action_name
);
1427 action
= descr
->handler(argc
, argv
);
1429 /* The handler has already printed an error message. */
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
,
1453 void lttng_actions_destructor(void *p
)
1455 struct lttng_action
*action
= p
;
1457 lttng_action_destroy(action
);
1460 int cmd_add_trigger(int argc
, const char **argv
)
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
;
1475 char *fire_once_after_str
= NULL
;
1476 char *fire_every_str
= NULL
;
1478 lttng_dynamic_pointer_array_init(&actions
, lttng_actions_destructor
);
1481 enum argpar_state_parse_next_status status
;
1482 struct argpar_item_opt
*item_opt
;
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");
1493 status
= argpar_state_parse_next(argpar_state
, &argpar_item
, &error
);
1495 if (status
== ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR
) {
1496 fprintf(stderr
, "Error: %s\n", error
);
1498 } else if (status
== ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT
) {
1499 fprintf(stderr
, "%s\n", error
);
1501 } else if (status
== ARGPAR_STATE_PARSE_NEXT_STATUS_END
) {
1505 assert(status
== ARGPAR_STATE_PARSE_NEXT_STATUS_OK
);
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
;
1511 fprintf(stderr
, "Unexpected argument `%s`.\n",
1516 item_opt
= (struct argpar_item_opt
*) argpar_item
;
1518 ingested_args
= argpar_state_get_ingested_orig_args(
1521 my_argc
-= ingested_args
;
1522 my_argv
+= ingested_args
;
1524 switch (item_opt
->descr
->id
) {
1530 case OPT_LIST_OPTIONS
:
1531 list_cmd_options_argpar(stdout
, add_trigger_options
);
1538 fprintf(stderr
, "A --condition was already given.\n");
1542 condition
= parse_condition(&my_argc
, &my_argv
);
1545 * An error message was already printed by
1556 action
= parse_action(&my_argc
, &my_argv
);
1559 * An error message was already printed by
1565 ret
= lttng_dynamic_pointer_array_add_pointer(
1568 fprintf(stderr
, "Failed to add pointer to pointer array.\n");
1572 /* Ownership of the action was transferred to the group. */
1580 if (!assign_string(&id
, item_opt
->arg
, "--id")) {
1587 case OPT_FIRE_ONCE_AFTER
:
1589 if (!assign_string(&fire_once_after_str
, item_opt
->arg
,
1590 "--fire-once-after")) {
1596 case OPT_FIRE_EVERY
:
1598 if (!assign_string(&fire_every_str
, item_opt
->arg
,
1611 fprintf(stderr
, "Missing --condition.\n");
1615 if (lttng_dynamic_pointer_array_get_count(&actions
) == 0) {
1616 fprintf(stderr
, "Need at least one --action.\n");
1620 if (fire_every_str
&& fire_once_after_str
) {
1621 fprintf(stderr
, "Can't specify both --fire-once-after and --fire-every.\n");
1625 action_group
= lttng_action_group_create();
1626 if (!action_group
) {
1630 for (i
= 0; i
< lttng_dynamic_pointer_array_get_count(&actions
); i
++) {
1631 enum lttng_action_status status
;
1633 action
= lttng_dynamic_pointer_array_steal_pointer(&actions
, i
);
1635 status
= lttng_action_group_add_action(
1636 action_group
, action
);
1637 if (status
!= LTTNG_ACTION_STATUS_OK
) {
1641 /* Ownership of the action was transferred to the group. */
1646 trigger
= lttng_trigger_create(condition
, action_group
);
1652 * Ownership of the condition and action group was transferred to the
1656 action_group
= NULL
;
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");
1667 if (fire_once_after_str
) {
1668 unsigned long long threshold
;
1669 enum lttng_trigger_status trigger_status
;
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
);
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");
1684 if (fire_every_str
) {
1685 unsigned long long threshold
;
1686 enum lttng_trigger_status trigger_status
;
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
);
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");
1701 ret
= lttng_register_trigger(trigger
);
1703 fprintf(stderr
, "Failed to register trigger: %s.\n",
1704 lttng_strerror(ret
));
1708 printf("Trigger registered successfully.\n");
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
);
1722 free(fire_once_after_str
);
1723 free(fire_every_str
);
1724 // TODO: check what else to free