struct cds_list_head node;
};
+/*
+ * Facilities to carry the different notifications type in the action processing
+ * code path.
+ */
+struct lttng_event_notifier_notification {
+ union {
+ struct lttng_ust_event_notifier_notification *ust;
+ struct lttng_kernel_event_notifier_notification *kernel;
+ } notification;
+ uint64_t token;
+ enum lttng_domain_type type;
+};
+
struct channel_state_sample {
struct channel_key key;
struct cds_lfht_node channel_state_ht_node;
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.
enum lttng_error_code *_cmd_result)
{
int ret = 0;
+ bool found = false;
enum lttng_error_code cmd_result = LTTNG_OK;
struct notification_event_tracer_event_source_element *source_element = NULL, *tmp;
tracer_event_source_fd,
lttng_domain_type_str(source_element->domain));
cds_list_del(&source_element->node);
+ found = true;
break;
}
- /* It should always be found. */
- assert(source_element);
+ if (!found) {
+ /*
+ * This is temporarily allowed since the poll activity set is
+ * not properly cleaned-up for the moment. This is adressed in
+ * an upcoming fix.
+ */
+ source_element = NULL;
+ goto end;
+ }
if (!source_element->is_fd_in_poll_set) {
/* Skip the poll set removal. */
static
int handle_notification_thread_command_unregister_trigger(
struct notification_thread_state *state,
- struct lttng_trigger *trigger,
+ const struct lttng_trigger *trigger,
enum lttng_error_code *_cmd_reply)
{
struct cds_lfht_iter iter;
struct lttng_channel_trigger_list *trigger_list;
struct notification_client_list *client_list;
struct lttng_trigger_ht_element *trigger_ht_element = NULL;
- struct lttng_condition *condition = lttng_trigger_get_condition(
+ const struct lttng_condition *condition = lttng_trigger_get_const_condition(
trigger);
enum lttng_error_code cmd_reply;
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.trigger,
+ 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.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,
&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,
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,
break;
}
case NOTIFICATION_COMMAND_TYPE_QUIT:
- DBG("[notification-thread] Received quit command");
cmd->reply_code = LTTNG_OK;
ret = 1;
goto end;
return ret;
}
+int handle_notification_thread_event_notification(struct notification_thread_state *state,
+ int notification_pipe_read_fd,
+ enum lttng_domain_type domain)
+{
+ int ret;
+ struct lttng_ust_event_notifier_notification ust_notification;
+ struct lttng_kernel_event_notifier_notification kernel_notification;
+ 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;
+ struct lttng_event_notifier_notification notification;
+ void *reception_buffer;
+ size_t reception_size;
+
+ notification.type = domain;
+
+ switch(domain) {
+ case LTTNG_DOMAIN_UST:
+ reception_buffer = (void *) &ust_notification;
+ reception_size = sizeof(ust_notification);
+ notification.notification.ust = &ust_notification;
+ break;
+ case LTTNG_DOMAIN_KERNEL:
+ reception_buffer = (void *) &kernel_notification;
+ reception_size = sizeof(kernel_notification);
+ notification.notification.kernel = &kernel_notification;
+ break;
+ default:
+ abort();
+ }
+
+ /*
+ * The monitoring pipe only holds messages smaller than PIPE_BUF,
+ * ensuring that read/write of tracer notifications are atomic.
+ */
+ ret = lttng_read(notification_pipe_read_fd, reception_buffer,
+ reception_size);
+ if (ret != reception_size) {
+ PERROR("Failed to read from event source notification pipe: fd = %d, size to read = %zu, ret = %d",
+ notification_pipe_read_fd, reception_size, ret);
+ ret = -1;
+ goto end;
+ }
+
+ switch(domain) {
+ case LTTNG_DOMAIN_UST:
+ notification.token = ust_notification.token;
+ break;
+ case LTTNG_DOMAIN_KERNEL:
+ notification.token = kernel_notification.token;
+ break;
+ default:
+ abort();
+ }
+
+ /* Find triggers associated with this token. */
+ rcu_read_lock();
+ cds_lfht_lookup(state->trigger_tokens_ht,
+ 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)) {
+ /*
+ * 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.
+ */
+ ret = 0;
+ goto end_unlock;
+ }
+
+ element = caa_container_of(node,
+ 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));
+
+ /* TODO: Perform actions */
+
+ ret = 0;
+
+end_unlock:
+ rcu_read_unlock();
+end:
+ return ret;
+}
+
int handle_notification_thread_channel_sample(
struct notification_thread_state *state, int pipe,
enum lttng_domain_type domain)