X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fnotification-thread-events.c;h=99b6642d67f972b25860f8a9acf72df4b032f9b2;hp=fe3975dfe4640011fd0d227845858367dedd95ea;hb=90aa04a116a8be510b9d256b47de6bbb4144fb8b;hpb=93ac2c445f462912a4060d8343755c6de130ce8e diff --git a/src/bin/lttng-sessiond/notification-thread-events.c b/src/bin/lttng-sessiond/notification-thread-events.c index fe3975dfe..99b6642d6 100644 --- a/src/bin/lttng-sessiond/notification-thread-events.c +++ b/src/bin/lttng-sessiond/notification-thread-events.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -41,6 +41,7 @@ #include #include "condition-internal.h" +#include "event-notifier-error-accounting.h" #include "notification-thread.h" #include "notification-thread-events.h" #include "notification-thread-commands.h" @@ -467,7 +468,7 @@ enum lttng_object_type get_condition_binding_object( case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING: case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED: return LTTNG_OBJECT_TYPE_SESSION; - case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT: + case LTTNG_CONDITION_TYPE_ON_EVENT: return LTTNG_OBJECT_TYPE_NONE; default: return LTTNG_OBJECT_TYPE_UNKNOWN; @@ -2123,6 +2124,40 @@ end: return ret; } +static +int condition_on_event_update_error_count(struct lttng_trigger *trigger) +{ + int ret = 0; + uint64_t error_count = 0; + struct lttng_condition *condition; + enum event_notifier_error_accounting_status status; + + condition = lttng_trigger_get_condition(trigger); + assert(lttng_condition_get_type(condition) == + LTTNG_CONDITION_TYPE_ON_EVENT); + + status = event_notifier_error_accounting_get_count(trigger, &error_count); + if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) { + uid_t trigger_owner_uid; + const char *trigger_name; + const enum lttng_trigger_status trigger_status = + lttng_trigger_get_owner_uid( + trigger, &trigger_owner_uid); + + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + if (lttng_trigger_get_name(trigger, &trigger_name) != LTTNG_TRIGGER_STATUS_OK) { + trigger_name = "(unnamed)"; + } + + ERR("Failed to get event notifier error count of trigger for update: trigger owner = %d, trigger name = '%s'", + trigger_owner_uid, trigger_name); + ret = -1; + } + + lttng_condition_on_event_set_error_count(condition, error_count); + return ret; +} + int handle_notification_thread_remove_tracer_event_source_no_result( struct notification_thread_state *state, int tracer_event_source_fd) @@ -2136,6 +2171,94 @@ int handle_notification_thread_remove_tracer_event_source_no_result( return ret; } +static +bool action_type_needs_tracer_notifier(enum lttng_action_type action_type) +{ + switch (action_type) { + case LTTNG_ACTION_TYPE_NOTIFY: + case LTTNG_ACTION_TYPE_START_SESSION: + case LTTNG_ACTION_TYPE_STOP_SESSION: + case LTTNG_ACTION_TYPE_SNAPSHOT_SESSION: + case LTTNG_ACTION_TYPE_ROTATE_SESSION: + return true; + case LTTNG_ACTION_TYPE_GROUP: + case LTTNG_ACTION_TYPE_UNKNOWN: + default: + abort(); + } +} + +static +bool action_needs_tracer_notifier(const struct lttng_action *action) +{ + bool needs_tracer_notifier = false; + unsigned int i, count; + enum lttng_action_status action_status; + enum lttng_action_type action_type; + + assert(action); + /* If there is only one action. Check if it needs a tracer notifier. */ + action_type = lttng_action_get_type(action); + if (action_type != LTTNG_ACTION_TYPE_GROUP) { + needs_tracer_notifier = action_type_needs_tracer_notifier( + action_type); + goto end; + } + + /* + * Iterate over all the actions of the action group and check if any of + * them needs a tracer notifier. + */ + action_status = lttng_action_group_get_count(action, &count); + assert(action_status == LTTNG_ACTION_STATUS_OK); + for (i = 0; i < count; i++) { + const struct lttng_action *inner_action = + lttng_action_group_get_at_index(action, i); + + action_type = lttng_action_get_type(inner_action); + if (action_type_needs_tracer_notifier(action_type)) { + needs_tracer_notifier = true; + goto end; + } + } + +end: + return needs_tracer_notifier; +} + +/* + * A given trigger needs a tracer notifier if + * it has an event-rule condition, + * AND + * it has one or more sessiond-execution action. + */ +static +bool trigger_needs_tracer_notifier(const struct lttng_trigger *trigger) +{ + bool needs_tracer_notifier = false; + const struct lttng_condition *condition = + lttng_trigger_get_const_condition(trigger); + const struct lttng_action *action = + lttng_trigger_get_const_action(trigger); + + switch (lttng_condition_get_type(condition)) { + case LTTNG_CONDITION_TYPE_ON_EVENT: + needs_tracer_notifier = action_needs_tracer_notifier(action); + goto end; + case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE: + case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH: + case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW: + case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING: + case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED: + goto end; + case LTTNG_CONDITION_TYPE_UNKNOWN: + default: + abort(); + } +end: + return needs_tracer_notifier; +} + static int handle_notification_thread_command_list_triggers( struct notification_thread_handle *handle, struct notification_thread_state *state, @@ -2170,6 +2293,12 @@ static int handle_notification_thread_command_list_triggers( continue; } + if (trigger_needs_tracer_notifier(trigger_ht_element->trigger)) { + ret = condition_on_event_update_error_count( + trigger_ht_element->trigger); + assert(!ret); + } + ret = lttng_triggers_add(local_triggers, trigger_ht_element->trigger); if (ret < 0) { @@ -2222,12 +2351,12 @@ bool condition_is_supported(struct lttng_condition *condition) is_supported = kernel_supports_ring_buffer_snapshot_sample_positions() == 1; break; } - case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT: + case LTTNG_CONDITION_TYPE_ON_EVENT: { const struct lttng_event_rule *event_rule; enum lttng_domain_type domain; const enum lttng_condition_status status = - lttng_condition_event_rule_get_rule( + lttng_condition_on_event_get_rule( condition, &event_rule); assert(status == LTTNG_CONDITION_STATUS_OK); @@ -2535,7 +2664,7 @@ int handle_notification_thread_command_register_trigger( goto error_free_ht_element; } - if (lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT) { + if (lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_ON_EVENT) { trigger_tokens_ht_element = zmalloc(sizeof(*trigger_tokens_ht_element)); if (!trigger_tokens_ht_element) { /* Fatal error. */ @@ -2569,6 +2698,32 @@ int handle_notification_thread_command_register_trigger( &trigger_ht_element->node_by_name_uid); goto error_free_ht_element; } + + if (trigger_needs_tracer_notifier(trigger)) { + uint64_t error_counter_index = 0; + enum event_notifier_error_accounting_status error_accounting_status; + + error_accounting_status = event_notifier_error_accounting_register_event_notifier( + trigger, &error_counter_index); + if (error_accounting_status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) { + if (error_accounting_status == EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NO_INDEX_AVAILABLE) { + DBG("Event notifier group error accounting map is full"); + *cmd_result = LTTNG_ERR_EVENT_NOTIFIER_ERROR_ACCOUNTING_FULL; + } else { + ERR("Failed to register event notifier for error accounting"); + *cmd_result = LTTNG_ERR_EVENT_NOTIFIER_REGISTRATION; + } + + cds_lfht_del(state->triggers_ht, &trigger_ht_element->node); + cds_lfht_del(state->triggers_by_name_uid_ht, &trigger_ht_element->node_by_name_uid); + cds_lfht_del(state->trigger_tokens_ht, &trigger_tokens_ht_element->node); + goto error_free_ht_element; + } + + lttng_condition_on_event_set_error_counter_index( + condition, error_counter_index); + } + } /* @@ -2830,7 +2985,7 @@ int handle_notification_thread_command_unregister_trigger( } if (lttng_condition_get_type(condition) == - LTTNG_CONDITION_TYPE_EVENT_RULE_HIT) { + LTTNG_CONDITION_TYPE_ON_EVENT) { struct notification_trigger_tokens_ht_element *trigger_tokens_ht_element; @@ -2841,6 +2996,11 @@ int handle_notification_thread_command_unregister_trigger( continue; } + if (trigger_needs_tracer_notifier(trigger_tokens_ht_element->trigger)) { + event_notifier_error_accounting_unregister_event_notifier( + trigger_tokens_ht_element->trigger); + } + DBG("[notification-thread] Removed trigger from tokens_ht"); cds_lfht_del(state->trigger_tokens_ht, &trigger_tokens_ht_element->node); @@ -4291,7 +4451,7 @@ struct lttng_event_notifier_notification *recv_one_event_notifier_notification( break; case LTTNG_DOMAIN_KERNEL: token = kernel_notification.token; - capture_buffer_size = 0; + capture_buffer_size = kernel_notification.capture_buf_size; break; default: abort(); @@ -4385,7 +4545,7 @@ int dispatch_one_event_notifier_notification(struct notification_thread_state *s trigger_status = lttng_trigger_get_name(element->trigger, &trigger_name); assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); - if (lttng_condition_event_rule_get_capture_descriptor_count( + if (lttng_condition_on_event_get_capture_descriptor_count( lttng_trigger_get_const_condition(element->trigger), &capture_count) != LTTNG_CONDITION_STATUS_OK) { ERR("Failed to get capture count"); @@ -4399,10 +4559,10 @@ int dispatch_one_event_notifier_notification(struct notification_thread_state *s goto end; } - evaluation = lttng_evaluation_event_rule_create( + evaluation = lttng_evaluation_on_event_create( container_of(lttng_trigger_get_const_condition( element->trigger), - struct lttng_condition_event_rule, + struct lttng_condition_on_event, parent), trigger_name, notification->capture_buffer, @@ -4470,6 +4630,7 @@ next_client: pthread_mutex_unlock(&client_list->lock); break; } + case ACTION_EXECUTOR_STATUS_INVALID: case ACTION_EXECUTOR_STATUS_ERROR: /* Fatal error, shut down everything. */ ERR("Fatal error encoutered while enqueuing action to the action executor");