X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng%2Fcommands%2Flist_triggers.c;h=da94f7e9881120e59168190eb1a64cf7abf2d774;hb=074060e8e7d729d94e69ced71ed52b4a40c982c2;hp=26dc201ec892d435c4214570043581611cd52b76;hpb=bc16a30da2af295c9bd3d07e163b24e7c96c40c6;p=lttng-tools.git diff --git a/src/bin/lttng/commands/list_triggers.c b/src/bin/lttng/commands/list_triggers.c index 26dc201ec..da94f7e98 100644 --- a/src/bin/lttng/commands/list_triggers.c +++ b/src/bin/lttng/commands/list_triggers.c @@ -10,6 +10,7 @@ #include "../command.h" #include "common/argpar/argpar.h" +#include "common/argpar-utils/argpar-utils.h" #include "common/dynamic-array.h" #include "common/mi-lttng.h" /* For lttng_condition_type_str(). */ @@ -18,8 +19,8 @@ #include "lttng/condition/event-rule-matches-internal.h" /* For lttng_domain_type_str(). */ #include "lttng/domain-internal.h" -/* For lttng_event_rule_syscall_emission_site_str() */ -#include "lttng/event-rule/syscall-internal.h" +/* For lttng_event_rule_kernel_syscall_emission_site_str() */ +#include "lttng/event-rule/kernel-syscall-internal.h" #include "../loglevel.h" #include @@ -29,6 +30,16 @@ static const char help_msg[] = ; #endif +#define INDENTATION_LEVEL_STR " " + +typedef enum lttng_event_rule_status (*event_rule_logging_get_name_pattern)( + const struct lttng_event_rule *rule, const char **pattern); +typedef enum lttng_event_rule_status (*event_rule_logging_get_filter)( + const struct lttng_event_rule *rule, const char **expression); +typedef enum lttng_event_rule_status (*event_rule_logging_get_log_level_rule)( + const struct lttng_event_rule *rule, + const struct lttng_log_level_rule **log_level_rule); + enum { OPT_HELP, OPT_LIST_OPTIONS, @@ -118,26 +129,26 @@ static void print_condition_session_rotation( /* * Returns the human-readable log level name associated with a numerical value - * if there is one. The Log4j and JUL domains have discontinuous log level + * if there is one. The Log4j and JUL event rule have discontinuous log level * values (a value can fall between two labels). In those cases, NULL is * returned. */ static const char *get_pretty_loglevel_name( - enum lttng_domain_type domain, int loglevel) + enum lttng_event_rule_type event_rule_type, int loglevel) { const char *name = NULL; - switch (domain) { - case LTTNG_DOMAIN_UST: + switch (event_rule_type) { + case LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT: name = loglevel_value_to_name(loglevel); break; - case LTTNG_DOMAIN_LOG4J: + case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING: name = loglevel_log4j_value_to_name(loglevel); break; - case LTTNG_DOMAIN_JUL: + case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING: name = loglevel_jul_value_to_name(loglevel); break; - case LTTNG_DOMAIN_PYTHON: + case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING: name = loglevel_python_value_to_name(loglevel); break; default: @@ -148,10 +159,9 @@ static const char *get_pretty_loglevel_name( } static -void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule) +void print_event_rule_user_tracepoint(const struct lttng_event_rule *event_rule) { enum lttng_event_rule_status event_rule_status; - enum lttng_domain_type domain_type; const char *pattern; const char *filter; int log_level; @@ -159,18 +169,13 @@ void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule) unsigned int exclusions_count; int i; - event_rule_status = lttng_event_rule_tracepoint_get_name_pattern( + event_rule_status = lttng_event_rule_user_tracepoint_get_name_pattern( event_rule, &pattern); assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK); - event_rule_status = lttng_event_rule_tracepoint_get_domain_type( - event_rule, &domain_type); - assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK); - - _MSG(" rule: %s (type: tracepoint, domain: %s", pattern, - lttng_domain_type_str(domain_type)); + _MSG(" rule: %s (type: user tracepoint", pattern); - event_rule_status = lttng_event_rule_tracepoint_get_filter( + event_rule_status = lttng_event_rule_user_tracepoint_get_filter( event_rule, &filter); if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) { _MSG(", filter: %s", filter); @@ -178,7 +183,7 @@ void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule) assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET); } - event_rule_status = lttng_event_rule_tracepoint_get_log_level_rule( + event_rule_status = lttng_event_rule_user_tracepoint_get_log_level_rule( event_rule, &log_level_rule); if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) { enum lttng_log_level_rule_status llr_status; @@ -203,7 +208,7 @@ void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule) assert(llr_status == LTTNG_LOG_LEVEL_RULE_STATUS_OK); pretty_loglevel_name = get_pretty_loglevel_name( - domain_type, log_level); + LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT, log_level); if (pretty_loglevel_name) { _MSG(", log level %s %s", log_level_op, pretty_loglevel_name); @@ -214,7 +219,7 @@ void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule) assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET); } - event_rule_status = lttng_event_rule_tracepoint_get_name_pattern_exclusion_count( + event_rule_status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count( event_rule, &exclusions_count); assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK); if (exclusions_count > 0) { @@ -222,7 +227,7 @@ void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule) for (i = 0; i < exclusions_count; i++) { const char *exclusion; - event_rule_status = lttng_event_rule_tracepoint_get_name_pattern_exclusion_at_index( + event_rule_status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index( event_rule, i, &exclusion); assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK); @@ -233,6 +238,128 @@ void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule) MSG(")"); } +static +void print_event_rule_kernel_tracepoint(const struct lttng_event_rule *event_rule) +{ + enum lttng_event_rule_status event_rule_status; + const char *pattern; + const char *filter; + + event_rule_status = lttng_event_rule_kernel_tracepoint_get_name_pattern( + event_rule, &pattern); + assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK); + + _MSG(" rule: %s (type: kernel tracepoint", pattern); + + event_rule_status = lttng_event_rule_kernel_tracepoint_get_filter( + event_rule, &filter); + if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) { + _MSG(", filter: %s", filter); + } else { + assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET); + } + + MSG(")"); +} + +static +void print_event_rule_logging(const struct lttng_event_rule *event_rule) +{ + enum lttng_event_rule_status event_rule_status; + enum lttng_event_rule_type event_rule_type = lttng_event_rule_get_type(event_rule); + const char *pattern; + const char *filter; + int log_level; + const struct lttng_log_level_rule *log_level_rule = NULL; + const char *type_str = NULL; + + event_rule_logging_get_name_pattern logging_get_name_pattern; + event_rule_logging_get_filter logging_get_filter; + event_rule_logging_get_log_level_rule logging_get_log_level_rule; + + switch (event_rule_type) { + case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING: + logging_get_name_pattern = + lttng_event_rule_jul_logging_get_name_pattern; + logging_get_filter = lttng_event_rule_jul_logging_get_filter; + logging_get_log_level_rule = + lttng_event_rule_jul_logging_get_log_level_rule; + type_str = "jul"; + break; + case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING: + logging_get_name_pattern = + lttng_event_rule_log4j_logging_get_name_pattern; + logging_get_filter = lttng_event_rule_log4j_logging_get_filter; + logging_get_log_level_rule = + lttng_event_rule_log4j_logging_get_log_level_rule; + type_str = "log4j"; + break; + case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING: + logging_get_name_pattern = + lttng_event_rule_python_logging_get_name_pattern; + logging_get_filter = lttng_event_rule_python_logging_get_filter; + logging_get_log_level_rule = + lttng_event_rule_python_logging_get_log_level_rule; + type_str = "python"; + break; + default: + abort(); + break; + } + + event_rule_status = logging_get_name_pattern( + event_rule, &pattern); + assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK); + + _MSG(" rule: %s (type: %s:logging", pattern, type_str); + + event_rule_status = logging_get_filter( + event_rule, &filter); + if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) { + _MSG(", filter: %s", filter); + } else { + assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET); + } + + event_rule_status = logging_get_log_level_rule( + event_rule, &log_level_rule); + if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) { + enum lttng_log_level_rule_status llr_status; + const char *log_level_op; + const char *pretty_loglevel_name; + + switch (lttng_log_level_rule_get_type(log_level_rule)) { + case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY: + log_level_op = "is"; + llr_status = lttng_log_level_rule_exactly_get_level( + log_level_rule, &log_level); + break; + case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS: + log_level_op = "at least"; + llr_status = lttng_log_level_rule_at_least_as_severe_as_get_level( + log_level_rule, &log_level); + break; + default: + abort(); + } + + assert(llr_status == LTTNG_LOG_LEVEL_RULE_STATUS_OK); + + pretty_loglevel_name = get_pretty_loglevel_name( + event_rule_type, log_level); + if (pretty_loglevel_name) { + _MSG(", log level %s %s", log_level_op, + pretty_loglevel_name); + } else { + _MSG(", log level %s %d", log_level_op, log_level); + } + } else { + assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET); + } + + MSG(")"); +} + static void print_kernel_probe_location( const struct lttng_kernel_probe_location *location) { @@ -294,22 +421,22 @@ void print_event_rule_kernel_probe(const struct lttng_event_rule *event_rule) const char *name; const struct lttng_kernel_probe_location *location; - assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE); + assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_KPROBE); - event_rule_status = lttng_event_rule_kernel_probe_get_event_name(event_rule, &name); + event_rule_status = lttng_event_rule_kernel_kprobe_get_event_name(event_rule, &name); if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) { ERR("Failed to get kprobe event rule's name."); goto end; } - event_rule_status = lttng_event_rule_kernel_probe_get_location( + event_rule_status = lttng_event_rule_kernel_kprobe_get_location( event_rule, &location); if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) { ERR("Failed to get kprobe event rule's location."); goto end; } - _MSG(" rule: %s (type: probe, location: ", name); + _MSG(" rule: %s (type: kernel:kprobe, location: ", name); print_kernel_probe_location(location); @@ -327,23 +454,23 @@ void print_event_rule_userspace_probe(const struct lttng_event_rule *event_rule) const struct lttng_userspace_probe_location *location; enum lttng_userspace_probe_location_type userspace_probe_location_type; - assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE); + assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_UPROBE); - event_rule_status = lttng_event_rule_userspace_probe_get_event_name( + event_rule_status = lttng_event_rule_kernel_uprobe_get_event_name( event_rule, &name); if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) { ERR("Failed to get uprobe event rule's name."); goto end; } - event_rule_status = lttng_event_rule_userspace_probe_get_location( + event_rule_status = lttng_event_rule_kernel_uprobe_get_location( event_rule, &location); if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) { ERR("Failed to get uprobe event rule's location."); goto end; } - _MSG(" rule: %s (type: userspace probe, ", name); + _MSG(" rule: %s (type: kernel:uprobe, ", name); userspace_probe_location_type = lttng_userspace_probe_location_get_type(location); @@ -389,22 +516,22 @@ void print_event_rule_syscall(const struct lttng_event_rule *event_rule) { const char *pattern, *filter; enum lttng_event_rule_status event_rule_status; - enum lttng_event_rule_syscall_emission_site emission_site; + enum lttng_event_rule_kernel_syscall_emission_site emission_site; - assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_SYSCALL); + assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL); emission_site = - lttng_event_rule_syscall_get_emission_site(event_rule); + lttng_event_rule_kernel_syscall_get_emission_site(event_rule); - event_rule_status = lttng_event_rule_syscall_get_name_pattern( + event_rule_status = lttng_event_rule_kernel_syscall_get_name_pattern( event_rule, &pattern); assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK); - _MSG(" rule: %s (type: syscall:%s", pattern, - lttng_event_rule_syscall_emission_site_str( + _MSG(" rule: %s (type: kernel:syscall:%s", pattern, + lttng_event_rule_kernel_syscall_emission_site_str( emission_site)); - event_rule_status = lttng_event_rule_syscall_get_filter( + event_rule_status = lttng_event_rule_kernel_syscall_get_filter( event_rule, &filter); if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) { _MSG(", filter: %s", filter); @@ -422,16 +549,24 @@ void print_event_rule(const struct lttng_event_rule *event_rule) lttng_event_rule_get_type(event_rule); switch (event_rule_type) { - case LTTNG_EVENT_RULE_TYPE_TRACEPOINT: - print_event_rule_tracepoint(event_rule); + case LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT: + print_event_rule_user_tracepoint(event_rule); break; - case LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE: + case LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT: + print_event_rule_kernel_tracepoint(event_rule); + break; + case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING: + case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING: + case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING: + print_event_rule_logging(event_rule); + break; + case LTTNG_EVENT_RULE_TYPE_KERNEL_KPROBE: print_event_rule_kernel_probe(event_rule); break; - case LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE: + case LTTNG_EVENT_RULE_TYPE_KERNEL_UPROBE: print_event_rule_userspace_probe(event_rule); break; - case LTTNG_EVENT_RULE_TYPE_SYSCALL: + case LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL: print_event_rule_syscall(event_rule); break; default: @@ -506,6 +641,79 @@ void print_one_event_expr(const struct lttng_event_expr *event_expr) } } +static +void print_indentation(unsigned int indentation_level) +{ + unsigned int i; + + for (i = 0; i < indentation_level; i++) { + _MSG(INDENTATION_LEVEL_STR); + } +} + +static +void print_error_query_results(struct lttng_error_query_results *results, + unsigned int base_indentation_level) +{ + unsigned int i, count, printed_errors_count = 0; + enum lttng_error_query_results_status results_status; + + results_status = lttng_error_query_results_get_count(results, &count); + assert(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK); + + assert(results); + + print_indentation(base_indentation_level); + _MSG("errors:"); + + for (i = 0; i < count; i++) { + const struct lttng_error_query_result *result; + enum lttng_error_query_result_status result_status; + const char *result_name; + const char *result_description; + uint64_t result_value; + + results_status = lttng_error_query_results_get_result( + results, &result, i); + assert(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK); + + result_status = lttng_error_query_result_get_name( + result, &result_name); + assert(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); + result_status = lttng_error_query_result_get_description( + result, &result_description); + assert(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); + + + if (lttng_error_query_result_get_type(result) == + LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER) { + result_status = lttng_error_query_result_counter_get_value( + result, &result_value); + assert(result_status == + LTTNG_ERROR_QUERY_RESULT_STATUS_OK); + if (result_value == 0) { + continue; + } + + MSG(""); + print_indentation(base_indentation_level + 1); + + _MSG("%s: %" PRIu64, result_name, result_value); + printed_errors_count++; + } else { + MSG(""); + print_indentation(base_indentation_level + 1); + _MSG("Unknown error query result type for result '%s' (%s)", + result_name, result_description); + continue; + } + } + + if (printed_errors_count == 0) { + _MSG(" none"); + } +} + static void print_condition_event_rule_matches( const struct lttng_condition *condition) { @@ -544,9 +752,7 @@ static void print_action_errors(const struct lttng_trigger *trigger, const uint64_t *action_path_indexes, size_t action_path_length) { - unsigned int i, count, printed_errors_count = 0; enum lttng_error_code error_query_ret; - enum lttng_error_query_results_status results_status; struct lttng_error_query_results *results = NULL; const char *trigger_name; uid_t trigger_uid; @@ -578,53 +784,7 @@ static void print_action_errors(const struct lttng_trigger *trigger, goto end; } - results_status = lttng_error_query_results_get_count(results, &count); - assert(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK); - - _MSG(" errors:"); - - for (i = 0; i < count; i++) { - const struct lttng_error_query_result *result; - enum lttng_error_query_result_status result_status; - const char *result_name; - const char *result_description; - uint64_t result_value; - - results_status = lttng_error_query_results_get_result( - results, &result, i); - assert(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK); - - result_status = lttng_error_query_result_get_name( - result, &result_name); - assert(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); - result_status = lttng_error_query_result_get_description( - result, &result_description); - assert(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); - - if (lttng_error_query_result_get_type(result) == - LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER) { - result_status = lttng_error_query_result_counter_get_value( - result, &result_value); - assert(result_status == - LTTNG_ERROR_QUERY_RESULT_STATUS_OK); - if (result_value == 0) { - continue; - } - - MSG(""); - _MSG(" %s: %" PRIu64, result_name, - result_value); - printed_errors_count++; - } else { - _MSG(" Unknown error query result type for result '%s' (%s)", - result_name, result_description); - continue; - } - } - - if (printed_errors_count == 0) { - _MSG(" none"); - } + print_error_query_results(results, 3); end: MSG(""); @@ -813,9 +973,7 @@ end: static void print_trigger_errors(const struct lttng_trigger *trigger) { - unsigned int i, count, printed_errors_count = 0; enum lttng_error_code error_query_ret; - enum lttng_error_query_results_status results_status; struct lttng_error_query_results *results = NULL; enum lttng_trigger_status trigger_status; const char *trigger_name; @@ -842,53 +1000,45 @@ void print_trigger_errors(const struct lttng_trigger *trigger) goto end; } - results_status = lttng_error_query_results_get_count(results, &count); - assert(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK); + print_error_query_results(results, 1); - _MSG(" errors:"); - - for (i = 0; i < count; i++) { - const struct lttng_error_query_result *result; - enum lttng_error_query_result_status result_status; - const char *result_name; - const char *result_description; - uint64_t result_value; +end: + MSG(""); + lttng_error_query_destroy(query); + lttng_error_query_results_destroy(results); +} - results_status = lttng_error_query_results_get_result( - results, &result, i); - assert(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK); +static +void print_condition_errors(const struct lttng_trigger *trigger) +{ + enum lttng_error_code error_query_ret; + struct lttng_error_query_results *results = NULL; + enum lttng_trigger_status trigger_status; + const char *trigger_name; + uid_t trigger_uid; + struct lttng_error_query *query = + lttng_error_query_condition_create(trigger); - result_status = lttng_error_query_result_get_name( - result, &result_name); - assert(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); - result_status = lttng_error_query_result_get_description( - result, &result_description); - assert(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); + assert(query); + /* + * Anonymous triggers are not listed; this would be an internal error. + */ + trigger_status = lttng_trigger_get_name(trigger, &trigger_name); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); - if (lttng_error_query_result_get_type(result) == - LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER) { - result_status = lttng_error_query_result_counter_get_value( - result, &result_value); - assert(result_status == - LTTNG_ERROR_QUERY_RESULT_STATUS_OK); - if (result_value == 0) { - continue; - } + trigger_status = lttng_trigger_get_owner_uid(trigger, &trigger_uid); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); - MSG(""); - _MSG(" %s: %" PRIu64, result_name, - result_value); - printed_errors_count++; - } else { - _MSG(" Unknown error query result type for result '%s' (%s)", - result_name, result_description); - continue; - } + error_query_ret = lttng_error_query_execute( + query, lttng_session_daemon_command_endpoint, &results); + if (error_query_ret != LTTNG_OK) { + ERR("Failed to query errors of condition of trigger '%s' (owner uid: %d): %s", + trigger_name, (int) trigger_uid, + lttng_strerror(-error_query_ret)); + goto end; } - if (printed_errors_count == 0) { - _MSG(" none"); - } + print_error_query_results(results, 2); end: MSG(""); @@ -946,6 +1096,8 @@ void print_one_trigger(const struct lttng_trigger *trigger) abort(); } + print_condition_errors(trigger); + action = lttng_trigger_get_const_action(trigger); action_type = lttng_action_get_type(action); if (action_type == LTTNG_ACTION_TYPE_LIST) { @@ -995,11 +1147,9 @@ int compare_triggers_by_name(const void *a, const void *b) return strcmp(name_a, name_b); } -int cmd_list_triggers(int argc, const char **argv) +static int print_sorted_triggers(const struct lttng_triggers *triggers) { int ret; - struct argpar_parse_ret argpar_parse_ret = {}; - struct lttng_triggers *triggers = NULL; int i; struct lttng_dynamic_pointer_array sorted_triggers; enum lttng_trigger_status trigger_status; @@ -1007,51 +1157,6 @@ int cmd_list_triggers(int argc, const char **argv) lttng_dynamic_pointer_array_init(&sorted_triggers, NULL); - argpar_parse_ret = argpar_parse( - argc - 1, argv + 1, list_trigger_options, true); - if (!argpar_parse_ret.items) { - ERR("%s", argpar_parse_ret.error); - goto error; - } - - for (i = 0; i < argpar_parse_ret.items->n_items; i++) { - const struct argpar_item *item = - argpar_parse_ret.items->items[i]; - - if (item->type == ARGPAR_ITEM_TYPE_OPT) { - const struct argpar_item_opt *item_opt = - (const struct argpar_item_opt *) item; - - switch (item_opt->descr->id) { - case OPT_HELP: - SHOW_HELP(); - ret = 0; - goto end; - - case OPT_LIST_OPTIONS: - list_cmd_options_argpar(stdout, - list_trigger_options); - ret = 0; - goto end; - - default: - abort(); - } - - } else { - const struct argpar_item_non_opt *item_non_opt = - (const struct argpar_item_non_opt *) item; - - ERR("Unexpected argument: %s", item_non_opt->arg); - } - } - - ret = lttng_list_triggers(&triggers); - if (ret != LTTNG_OK) { - ERR("Error listing triggers: %s.", lttng_strerror(-ret)); - goto error; - } - trigger_status = lttng_triggers_get_count(triggers, &num_triggers); if (trigger_status != LTTNG_TRIGGER_STATUS_OK) { ERR("Failed to get trigger count."); @@ -1077,7 +1182,6 @@ int cmd_list_triggers(int argc, const char **argv) add_ret = lttng_dynamic_pointer_array_add_pointer( &sorted_triggers, (void *) trigger); - if (add_ret) { ERR("Failed to allocate array of struct lttng_trigger *."); goto error; @@ -1088,9 +1192,10 @@ int cmd_list_triggers(int argc, const char **argv) sizeof(struct lttng_trigger *), compare_triggers_by_name); - for (i = 0; i < num_triggers; i++) { - const struct lttng_trigger *trigger_to_print = - (const struct lttng_trigger *) + for (i = 0; i < lttng_dynamic_pointer_array_get_count(&sorted_triggers); + i++) { + const struct lttng_trigger *trigger_to_print = (const struct lttng_trigger + *) lttng_dynamic_pointer_array_get_pointer( &sorted_triggers, i); @@ -1099,14 +1204,258 @@ int cmd_list_triggers(int argc, const char **argv) ret = 0; goto end; - error: ret = 1; end: - argpar_parse_ret_fini(&argpar_parse_ret); - lttng_triggers_destroy(triggers); lttng_dynamic_pointer_array_reset(&sorted_triggers); + return ret; +} + +static enum lttng_error_code mi_error_query_trigger_callback( + const struct lttng_trigger *trigger, + struct lttng_error_query_results **results) +{ + enum lttng_error_code ret_code; + struct lttng_error_query *query = + lttng_error_query_trigger_create(trigger); + + assert(results); + assert(query); + ret_code = lttng_error_query_execute( + query, lttng_session_daemon_command_endpoint, results); + if (ret_code != LTTNG_OK) { + enum lttng_trigger_status trigger_status; + const char *trigger_name; + uid_t trigger_uid; + + trigger_status = lttng_trigger_get_name(trigger, &trigger_name); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + + trigger_status = lttng_trigger_get_owner_uid( + trigger, &trigger_uid); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + + ERR("Failed to query errors of trigger '%s' (owner uid: %d): %s", + trigger_name, (int) trigger_uid, + lttng_strerror(-ret_code)); + } + + lttng_error_query_destroy(query); + return ret_code; +} + +static enum lttng_error_code mi_error_query_action_callback( + const struct lttng_trigger *trigger, + const struct lttng_action_path *action_path, + struct lttng_error_query_results **results) +{ + enum lttng_error_code ret_code; + struct lttng_error_query *query = + lttng_error_query_action_create(trigger, action_path); + + assert(results); + assert(query); + + ret_code = lttng_error_query_execute( + query, lttng_session_daemon_command_endpoint, results); + if (ret_code != LTTNG_OK) { + enum lttng_trigger_status trigger_status; + const char *trigger_name; + uid_t trigger_uid; + + trigger_status = lttng_trigger_get_name(trigger, &trigger_name); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + + trigger_status = lttng_trigger_get_owner_uid( + trigger, &trigger_uid); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + + ERR("Failed to query errors of an action for trigger '%s' (owner uid: %d): %s", + trigger_name, (int) trigger_uid, + lttng_strerror(-ret_code)); + } + + lttng_error_query_destroy(query); + return ret_code; +} + +static enum lttng_error_code mi_error_query_condition_callback( + const struct lttng_trigger *trigger, + struct lttng_error_query_results **results) +{ + enum lttng_error_code ret_code; + struct lttng_error_query *query = + lttng_error_query_condition_create(trigger); + + assert(results); + assert(query); + + ret_code = lttng_error_query_execute( + query, lttng_session_daemon_command_endpoint, results); + if (ret_code != LTTNG_OK) { + enum lttng_trigger_status trigger_status; + const char *trigger_name; + uid_t trigger_uid; + + trigger_status = lttng_trigger_get_name(trigger, &trigger_name); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + + trigger_status = lttng_trigger_get_owner_uid( + trigger, &trigger_uid); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + + ERR("Failed to query errors of of condition for condition of trigger '%s' (owner uid: %d): %s", + trigger_name, (int) trigger_uid, + lttng_strerror(-ret_code)); + } + + lttng_error_query_destroy(query); + return ret_code; +} + +int cmd_list_triggers(int argc, const char **argv) +{ + int ret; + struct argpar_iter *argpar_iter = NULL; + const struct argpar_item *argpar_item = NULL; + struct lttng_triggers *triggers = NULL; + struct mi_writer *mi_writer = NULL; + + argc--; + argv++; + + argpar_iter = argpar_iter_create(argc, argv, list_trigger_options); + if (!argpar_iter) { + ERR("Failed to allocate an argpar iter."); + goto error; + } + + while (true) { + enum parse_next_item_status status; + + status = parse_next_item(argpar_iter, &argpar_item, 1, argv, + true, NULL, NULL); + if (status == PARSE_NEXT_ITEM_STATUS_ERROR || + status == PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY) { + goto error; + } else if (status == PARSE_NEXT_ITEM_STATUS_END) { + break; + } + + assert(status == PARSE_NEXT_ITEM_STATUS_OK); + + if (argpar_item_type(argpar_item) == ARGPAR_ITEM_TYPE_OPT) { + const struct argpar_opt_descr *descr = + argpar_item_opt_descr(argpar_item); + + switch (descr->id) { + case OPT_HELP: + SHOW_HELP(); + ret = 0; + goto end; + + case OPT_LIST_OPTIONS: + list_cmd_options_argpar( + stdout, list_trigger_options); + ret = 0; + goto end; + + default: + abort(); + } + + } else { + ERR("Unexpected argument: %s", + argpar_item_non_opt_arg(argpar_item)); + } + } + + ret = lttng_list_triggers(&triggers); + if (ret != LTTNG_OK) { + ERR("Error listing triggers: %s.", lttng_strerror(-ret)); + goto error; + } + + if (lttng_opt_mi) { + mi_writer = mi_lttng_writer_create( + fileno(stdout), lttng_opt_mi); + if (!mi_writer) { + ret = CMD_ERROR; + goto end; + } + + /* Open command element. */ + ret = mi_lttng_writer_command_open(mi_writer, + mi_lttng_element_command_list_trigger); + if (ret) { + ret = CMD_ERROR; + goto end; + } + + /* Open output element. */ + ret = mi_lttng_writer_open_element( + mi_writer, mi_lttng_element_command_output); + if (ret) { + ret = CMD_ERROR; + goto end; + } + } + + if (lttng_opt_mi) { + const struct mi_lttng_error_query_callbacks callbacks = { + .trigger_cb = mi_error_query_trigger_callback, + .action_cb = mi_error_query_action_callback, + .condition_cb = mi_error_query_condition_callback, + }; + + ret = lttng_triggers_mi_serialize( + triggers, mi_writer, &callbacks); + if (ret != LTTNG_OK) { + ERR("Error printing MI triggers: %s.", + lttng_strerror(-ret)); + goto error; + } + } else { + ret = print_sorted_triggers(triggers); + if (ret) { + ERR("Error printing triggers"); + goto error; + } + } + + /* Mi closing. */ + if (lttng_opt_mi) { + /* Close output element. */ + ret = mi_lttng_writer_close_element(mi_writer); + if (ret) { + ret = CMD_ERROR; + goto end; + } + + /* Command element close. */ + ret = mi_lttng_writer_command_close(mi_writer); + if (ret) { + ret = CMD_ERROR; + goto end; + } + } + + ret = 0; + goto end; + +error: + ret = 1; + +end: + argpar_item_destroy(argpar_item); + argpar_iter_destroy(argpar_iter); + lttng_triggers_destroy(triggers); + /* Mi clean-up. */ + if (mi_writer && mi_lttng_writer_destroy(mi_writer)) { + /* Preserve original error code. */ + ret = ret ? ret : CMD_ERROR; + } return ret; }