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 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)
#include "health-sessiond.h"
#include "thread.h"
+#include "kernel.h"
+#include <common/kernel-ctl/kernel-ctl.h>
+
#include <urcu.h>
#include <urcu/list.h>
#include <urcu/rculfhash.h>
PERROR("close kernel consumer channel monitoring pipe");
}
}
+
end:
free(handle);
}
return ret;
}
+static int handle_event_notification_pipe(int event_source_fd,
+ enum lttng_domain_type domain,
+ uint32_t revents,
+ struct notification_thread_state *state)
+{
+ int ret = 0;
+
+ if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
+ ret = handle_notification_thread_remove_tracer_event_source_no_result(
+ state, event_source_fd);
+ if (ret) {
+ ERR("[notification-thread] Failed to remove event notification pipe from poll set: fd = %d",
+ event_source_fd);
+ }
+ goto end;
+ }
+
+ ret = handle_notification_thread_event_notification(
+ state, event_source_fd, domain);
+ if (ret) {
+ ERR("[notification-thread] Event notification handling error occurred for fd: %d",
+ event_source_fd);
+ ret = -1;
+ goto end;
+ }
+end:
+ return ret;
+}
+
+/*
+ * Return the event source domain type via parameter.
+ */
+static bool fd_is_event_notification_source(const struct notification_thread_state *state,
+ int fd,
+ enum lttng_domain_type *domain)
+{
+ struct notification_event_tracer_event_source_element *source_element;
+
+ assert(domain);
+
+ cds_list_for_each_entry(source_element,
+ &state->tracer_event_sources_list, node) {
+ if (source_element->fd != fd) {
+ continue;
+ }
+
+ *domain = source_element->domain;
+ return true;
+ }
+
+ return false;
+}
+
/*
* This thread services notification channel clients and commands received
* from various lttng-sessiond components over a command queue.
int ret;
struct notification_thread_handle *handle = data;
struct notification_thread_state state;
+ enum lttng_domain_type domain;
DBG("[notification-thread] Started notification thread");
if (ret) {
goto error;
}
+ } else if (fd_is_event_notification_source(&state, fd, &domain)) {
+ ret = handle_event_notification_pipe(fd, domain, revents, &state);
+ if (ret) {
+ goto error;
+ }
} else {
/* Activity on a client's socket. */
if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {