X-Git-Url: http://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fnotification-thread-events.c;h=93363c708e6712bd26105bf57b2a2323cfc5b1da;hp=d620159246a54368d44fa9b9391f4007212c54f6;hb=f14461318ba4a0c44bb7ed7a9c320c7d7b903052;hpb=940786035bcaf18b6b19a6a98f928ad4f52375f4 diff --git a/src/bin/lttng-sessiond/notification-thread-events.c b/src/bin/lttng-sessiond/notification-thread-events.c index d62015924..93363c708 100644 --- a/src/bin/lttng-sessiond/notification-thread-events.c +++ b/src/bin/lttng-sessiond/notification-thread-events.c @@ -331,6 +331,38 @@ int match_session(struct cds_lfht_node *node, const void *key) return !strcmp(session_info->name, name); } +static +const char *notification_command_type_str( + enum notification_thread_command_type type) +{ + switch (type) { + case NOTIFICATION_COMMAND_TYPE_REGISTER_TRIGGER: + return "REGISTER_TRIGGER"; + case NOTIFICATION_COMMAND_TYPE_UNREGISTER_TRIGGER: + return "UNREGISTER_TRIGGER"; + case NOTIFICATION_COMMAND_TYPE_ADD_CHANNEL: + return "ADD_CHANNEL"; + case NOTIFICATION_COMMAND_TYPE_REMOVE_CHANNEL: + return "REMOVE_CHANNEL"; + case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING: + return "SESSION_ROTATION_ONGOING"; + case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED: + return "SESSION_ROTATION_COMPLETED"; + case NOTIFICATION_COMMAND_TYPE_ADD_TRACER_EVENT_SOURCE: + return "ADD_TRACER_EVENT_SOURCE"; + case NOTIFICATION_COMMAND_TYPE_REMOVE_TRACER_EVENT_SOURCE: + return "REMOVE_TRACER_EVENT_SOURCE"; + case NOTIFICATION_COMMAND_TYPE_LIST_TRIGGERS: + return "LIST_TRIGGERS"; + case NOTIFICATION_COMMAND_TYPE_QUIT: + return "QUIT"; + case NOTIFICATION_COMMAND_TYPE_CLIENT_COMMUNICATION_UPDATE: + return "CLIENT_COMMUNICATION_UPDATE"; + default: + abort(); + } +} + /* * Match trigger based on name and credentials only. * Name duplication is NOT allowed for the same uid. @@ -2578,11 +2610,15 @@ int handle_notification_thread_command_register_trigger( ret = evaluate_session_condition_for_client(condition, state, &evaluation, &object_uid, &object_gid); + LTTNG_OPTIONAL_SET(&object_creds.uid, object_uid); + LTTNG_OPTIONAL_SET(&object_creds.gid, object_gid); break; case LTTNG_OBJECT_TYPE_CHANNEL: ret = evaluate_channel_condition_for_client(condition, state, &evaluation, &object_uid, &object_gid); + LTTNG_OPTIONAL_SET(&object_creds.uid, object_uid); + LTTNG_OPTIONAL_SET(&object_creds.gid, object_gid); break; case LTTNG_OBJECT_TYPE_NONE: ret = 0; @@ -2598,9 +2634,6 @@ int handle_notification_thread_command_register_trigger( goto error_put_client_list; } - LTTNG_OPTIONAL_SET(&object_creds.uid, object_uid); - LTTNG_OPTIONAL_SET(&object_creds.gid, object_gid); - DBG("Newly registered trigger's condition evaluated to %s", evaluation ? "true" : "false"); if (!evaluation) { @@ -2802,22 +2835,22 @@ int handle_notification_thread_command( struct notification_thread_command, cmd_list_node); cds_list_del(&cmd->cmd_list_node); pthread_mutex_unlock(&handle->cmd_queue.lock); + + DBG("[notification-thread] Received `%s` command", + notification_command_type_str(cmd->type)); switch (cmd->type) { case NOTIFICATION_COMMAND_TYPE_REGISTER_TRIGGER: - DBG("[notification-thread] Received register trigger command"); ret = handle_notification_thread_command_register_trigger(state, cmd->parameters.register_trigger.trigger, &cmd->reply_code); break; case NOTIFICATION_COMMAND_TYPE_UNREGISTER_TRIGGER: - DBG("[notification-thread] Received unregister trigger command"); ret = handle_notification_thread_command_unregister_trigger( state, cmd->parameters.unregister_trigger.trigger, &cmd->reply_code); break; case NOTIFICATION_COMMAND_TYPE_ADD_CHANNEL: - DBG("[notification-thread] Received add channel command"); ret = handle_notification_thread_command_add_channel( state, cmd->parameters.add_channel.session.name, @@ -2830,7 +2863,6 @@ int handle_notification_thread_command( &cmd->reply_code); break; case NOTIFICATION_COMMAND_TYPE_REMOVE_CHANNEL: - DBG("[notification-thread] Received remove channel command"); ret = handle_notification_thread_command_remove_channel( state, cmd->parameters.remove_channel.key, cmd->parameters.remove_channel.domain, @@ -2838,9 +2870,6 @@ int handle_notification_thread_command( break; case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING: case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED: - DBG("[notification-thread] Received session rotation %s command", - cmd->type == NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING ? - "ongoing" : "completed"); ret = handle_notification_thread_command_session_rotation( state, cmd->type, @@ -2879,7 +2908,6 @@ int handle_notification_thread_command( break; } case NOTIFICATION_COMMAND_TYPE_QUIT: - DBG("[notification-thread] Received quit command"); cmd->reply_code = LTTNG_OK; ret = 1; goto end; @@ -4153,14 +4181,17 @@ int handle_notification_thread_event_notification(struct notification_thread_sta int ret; struct lttng_ust_event_notifier_notification ust_notification; struct lttng_kernel_event_notifier_notification kernel_notification; + struct lttng_evaluation *evaluation = NULL; struct cds_lfht_node *node; struct cds_lfht_iter iter; struct notification_trigger_tokens_ht_element *element; - enum lttng_action_type action_type; - const struct lttng_action *action; + enum lttng_trigger_status status; struct lttng_event_notifier_notification notification; void *reception_buffer; size_t reception_size; + enum action_executor_status executor_status; + struct notification_client_list *client_list = NULL; + const char *trigger_name; notification.type = domain; @@ -4209,11 +4240,12 @@ int handle_notification_thread_event_notification(struct notification_thread_sta hash_key_u64(¬ification.token, lttng_ht_seed), match_trigger_token, ¬ification.token, &iter); node = cds_lfht_iter_get_node(&iter); - if (caa_likely(!node)) { + if (caa_unlikely(!node)) { /* - * This is not an error, slow consumption of the pipe can lead - * to situations where a trigger is removed but we still get - * tracer notification matching to a previous trigger. + * This is not an error, slow consumption of the tracer + * notifications can lead to situations where a trigger is + * removed but we still get tracer notifications matching a + * trigger that no longer exists. */ ret = 0; goto end_unlock; @@ -4223,17 +4255,91 @@ int handle_notification_thread_event_notification(struct notification_thread_sta struct notification_trigger_tokens_ht_element, node); - action = lttng_trigger_get_const_action(element->trigger); - action_type = lttng_action_get_type(action); - DBG("Received message from tracer event source: event source fd = %d, token = %" PRIu64 ", action type = '%s'", - notification_pipe_read_fd, notification.token, - lttng_action_type_string(action_type)); + if (!lttng_trigger_should_fire(element->trigger)) { + ret = 0; + goto end_unlock; + } - /* TODO: Perform actions */ + lttng_trigger_fire(element->trigger); - ret = 0; + status = lttng_trigger_get_name(element->trigger, &trigger_name); + assert(status == LTTNG_TRIGGER_STATUS_OK); + evaluation = lttng_evaluation_event_rule_create(trigger_name); + if (evaluation == NULL) { + ERR("Failed to create event rule evaluation while creating and enqueuing action executor job"); + ret = -1; + goto end_unlock; + } + + client_list = get_client_list_from_condition(state, + lttng_trigger_get_const_condition(element->trigger)); + executor_status = action_executor_enqueue(state->executor, + element->trigger, evaluation, NULL, client_list); + switch (executor_status) { + case ACTION_EXECUTOR_STATUS_OK: + ret = 0; + break; + case ACTION_EXECUTOR_STATUS_OVERFLOW: + { + struct notification_client_list_element *client_list_element, + *tmp; + + /* + * Not a fatal error; this is expected and simply means the + * executor has too much work queued already. + */ + ret = 0; + + /* No clients subscribed to notifications for this trigger. */ + if (!client_list) { + break; + } + + /* Warn clients that a notification (or more) was dropped. */ + pthread_mutex_lock(&client_list->lock); + cds_list_for_each_entry_safe(client_list_element, tmp, + &client_list->list, node) { + enum client_transmission_status transmission_status; + struct notification_client *client = + client_list_element->client; + + pthread_mutex_lock(&client->lock); + ret = client_notification_overflow(client); + if (ret) { + /* Fatal error. */ + goto next_client; + } + + transmission_status = + client_flush_outgoing_queue(client); + ret = client_handle_transmission_status( + client, transmission_status, state); + if (ret) { + /* Fatal error. */ + goto next_client; + } +next_client: + pthread_mutex_unlock(&client->lock); + if (ret) { + break; + } + } + + pthread_mutex_unlock(&client_list->lock); + break; + } + case ACTION_EXECUTOR_STATUS_ERROR: + /* Fatal error, shut down everything. */ + ERR("Fatal error encoutered while enqueuing action to the action executor"); + ret = -1; + goto end_unlock; + default: + /* Unhandled error. */ + abort(); + } end_unlock: + notification_client_list_put(client_list); rcu_read_unlock(); end: return ret;