Move UST registry into sessiond and implement notifiers
[lttng-ust.git] / liblttng-ust / lttng-events.c
index 790d14b2495992d893e9d63f15ca8e65a3f6738a..f77db60c512f7d3d1f7a5d6bdef970d307368a4e 100644 (file)
@@ -45,6 +45,8 @@
 
 #include <usterr-signal-safe.h>
 #include <helper.h>
+#include <ust-ctl.h>
+#include <ust-comm.h>
 #include "error.h"
 #include "compat.h"
 #include "lttng-ust-uuid.h"
@@ -76,7 +78,6 @@ void ust_unlock(void)
 static CDS_LIST_HEAD(sessions);
 
 static void _lttng_event_destroy(struct lttng_event *event);
-static void _lttng_channel_destroy(struct lttng_channel *chan);
 static int _lttng_event_unregister(struct lttng_event *event);
 static
 int _lttng_event_metadata_statedump(struct lttng_session *session,
@@ -92,6 +93,20 @@ void lttng_session_sync_enablers(struct lttng_session *session);
 static
 void lttng_enabler_destroy(struct lttng_enabler *enabler);
 
+/*
+ * Called with ust lock held.
+ */
+int lttng_session_active(void)
+{
+       struct lttng_session *iter;
+
+       cds_list_for_each_entry(iter, &sessions, node) {
+               if (iter->active)
+                       return 1;
+       }
+       return 0;
+}
+
 static
 int lttng_loglevel_match(int loglevel,
                unsigned int has_loglevel,
@@ -127,7 +142,7 @@ void synchronize_trace(void)
 struct lttng_session *lttng_session_create(void)
 {
        struct lttng_session *session;
-       int ret;
+       int i;
 
        session = zmalloc(sizeof(struct lttng_session));
        if (!session)
@@ -135,14 +150,32 @@ struct lttng_session *lttng_session_create(void)
        CDS_INIT_LIST_HEAD(&session->chan_head);
        CDS_INIT_LIST_HEAD(&session->events_head);
        CDS_INIT_LIST_HEAD(&session->enablers_head);
-       ret = lttng_ust_uuid_generate(session->uuid);
-       if (ret != 0) {
-               session->uuid[0] = '\0';
-       }
+       for (i = 0; i < LTTNG_UST_EVENT_HT_SIZE; i++)
+               CDS_INIT_HLIST_HEAD(&session->events_ht.table[i]);
        cds_list_add(&session->node, &sessions);
        return session;
 }
 
+/*
+ * Only used internally at session destruction.
+ */
+static
+void _lttng_channel_unmap(struct lttng_channel *lttng_chan)
+{
+       struct channel *chan;
+       struct lttng_ust_shm_handle *handle;
+
+       cds_list_del(&lttng_chan->node);
+       lttng_destroy_context(lttng_chan->ctx);
+       chan = lttng_chan->chan;
+       handle = lttng_chan->handle;
+       /*
+        * note: lttng_chan is private data contained within handle. It
+        * will be freed along with the handle.
+        */
+       channel_destroy(chan, handle, 0);
+}
+
 void lttng_session_destroy(struct lttng_session *session)
 {
        struct lttng_channel *chan, *tmpchan;
@@ -163,7 +196,7 @@ void lttng_session_destroy(struct lttng_session *session)
                        &session->events_head, node)
                _lttng_event_destroy(event);
        cds_list_for_each_entry_safe(chan, tmpchan, &session->chan_head, node)
-               _lttng_channel_destroy(chan);
+               _lttng_channel_unmap(chan);
        cds_list_del(&session->node);
        free(session);
 }
@@ -172,12 +205,17 @@ int lttng_session_enable(struct lttng_session *session)
 {
        int ret = 0;
        struct lttng_channel *chan;
+       int notify_socket;
 
        if (session->active) {
                ret = -EBUSY;
                goto end;
        }
 
+       notify_socket = lttng_get_notify_socket(session->owner);
+       if (notify_socket < 0)
+               return notify_socket;
+
        /* We need to sync enablers with session before activation. */
        lttng_session_sync_enablers(session);
 
@@ -186,12 +224,27 @@ int lttng_session_enable(struct lttng_session *session)
         * we need to use.
         */
        cds_list_for_each_entry(chan, &session->chan_head, node) {
+               const struct lttng_ctx *ctx;
+               const struct lttng_event_field *fields = NULL;
+               size_t nr_fields = 0;
+
+               /* don't change it if session stop/restart */
                if (chan->header_type)
-                       continue;               /* don't change it if session stop/restart */
-               if (chan->free_event_id < 31)
-                       chan->header_type = 1;  /* compact */
-               else
-                       chan->header_type = 2;  /* large */
+                       continue;
+               ctx = chan->ctx;
+               if (ctx) {
+                       nr_fields = ctx->nr_fields;
+                       fields = &ctx->fields->event_field;
+               }
+               ret = ustcomm_register_channel(notify_socket,
+                       session->objd,
+                       chan->objd,
+                       nr_fields,
+                       fields,
+                       &chan->id,
+                       &chan->header_type);
+               if (ret)
+                       return ret;
        }
 
        CMM_ACCESS_ONCE(session->active) = 1;
@@ -264,62 +317,6 @@ int lttng_event_disable(struct lttng_event *event)
        return 0;
 }
 
-struct lttng_channel *lttng_channel_create(struct lttng_session *session,
-                                      const char *transport_name,
-                                      void *buf_addr,
-                                      size_t subbuf_size, size_t num_subbuf,
-                                      unsigned int switch_timer_interval,
-                                      unsigned int read_timer_interval,
-                                      int **shm_fd, int **wait_fd,
-                                      uint64_t **memory_map_size,
-                                      struct lttng_channel *chan_priv_init)
-{
-       struct lttng_channel *chan = NULL;
-       struct lttng_transport *transport;
-
-       if (session->been_active)
-               goto active;    /* Refuse to add channel to active session */
-       transport = lttng_transport_find(transport_name);
-       if (!transport) {
-               DBG("LTTng transport %s not found\n",
-                      transport_name);
-               goto notransport;
-       }
-       chan_priv_init->id = session->free_chan_id++;
-       chan_priv_init->session = session;
-       /*
-        * Note: the channel creation op already writes into the packet
-        * headers. Therefore the "chan" information used as input
-        * should be already accessible.
-        */
-       chan = transport->ops.channel_create(transport_name, buf_addr,
-                       subbuf_size, num_subbuf, switch_timer_interval,
-                       read_timer_interval, shm_fd, wait_fd,
-                       memory_map_size, chan_priv_init);
-       if (!chan)
-               goto create_error;
-       chan->enabled = 1;
-       chan->ops = &transport->ops;
-       cds_list_add(&chan->node, &session->chan_head);
-       return chan;
-
-create_error:
-notransport:
-active:
-       return NULL;
-}
-
-/*
- * Only used internally at session destruction.
- */
-static
-void _lttng_channel_destroy(struct lttng_channel *chan)
-{
-       cds_list_del(&chan->node);
-       lttng_destroy_context(chan->ctx);
-       chan->ops->channel_destroy(chan);
-}
-
 /*
  * Supports event creation while tracing session is active.
  */
@@ -329,17 +326,18 @@ int lttng_event_create(const struct lttng_event_desc *desc,
 {
        const char *event_name = desc->name;
        struct lttng_event *event;
+       struct lttng_session *session = chan->session;
+       struct cds_hlist_head *head;
+       struct cds_hlist_node *node;
        int ret = 0;
-
-       if (chan->used_event_id == -1U) {
-               ret = -ENOMEM;
-               goto full;
-       }
-       /*
-        * This is O(n^2) (for each event, the loop is called at event
-        * creation). Might require a hash if we have lots of events.
-        */
-       cds_list_for_each_entry(event, &chan->session->events_head, node) {
+       size_t name_len = strlen(event_name);
+       uint32_t hash;
+       int notify_socket, loglevel;
+       const char *uri;
+
+       hash = jhash(event_name, name_len, 0);
+       head = &chan->session->events_ht.table[hash & (LTTNG_UST_EVENT_HT_SIZE - 1)];
+       cds_hlist_for_each_entry(event, node, head, hlist) {
                assert(event->desc);
                if (!strncmp(event->desc->name,
                                desc->name,
@@ -349,6 +347,12 @@ int lttng_event_create(const struct lttng_event_desc *desc,
                }
        }
 
+       notify_socket = lttng_get_notify_socket(session->owner);
+       if (notify_socket < 0) {
+               ret = notify_socket;
+               goto socket_error;
+       }
+
        /*
         * Check if loglevel match. Refuse to connect event if not.
         */
@@ -359,39 +363,59 @@ int lttng_event_create(const struct lttng_event_desc *desc,
        }
        event->chan = chan;
 
-       /*
-        * used_event_id counts the maximum number of event IDs that can
-        * register if all probes register.
-        */
-       chan->used_event_id++;
        event->enabled = 1;
        CDS_INIT_LIST_HEAD(&event->bytecode_runtime_head);
        CDS_INIT_LIST_HEAD(&event->enablers_ref_head);
        event->desc = desc;
+
+       if (desc->loglevel)
+               loglevel = *(*event->desc->loglevel);
+       else
+               loglevel = TRACE_DEFAULT;
+       if (desc->u.ext.model_emf_uri)
+               uri = *(desc->u.ext.model_emf_uri);
+       else
+               uri = NULL;
+
+       /* Fetch event ID from sessiond */
+       ret = ustcomm_register_event(notify_socket,
+               session->objd,
+               chan->objd,
+               event_name,
+               loglevel,
+               desc->signature,
+               desc->nr_fields,
+               desc->fields,
+               uri,
+               &event->id);
+       if (ret < 0) {
+               goto sessiond_register_error;
+       }
        /* Populate lttng_event structure before tracepoint registration. */
        cmm_smp_wmb();
        ret = __tracepoint_probe_register(event_name,
                        desc->probe_callback,
                        event, desc->signature);
        if (ret)
-               goto register_error;
-       event->id = chan->free_event_id++;
+               goto tracepoint_register_error;
+
        ret = _lttng_event_metadata_statedump(chan->session, chan, event);
        if (ret)
                goto statedump_error;
        cds_list_add(&event->node, &chan->session->events_head);
+       cds_hlist_add_head(&event->hlist, head);
        return 0;
 
 statedump_error:
        WARN_ON_ONCE(__tracepoint_probe_unregister(event_name,
                                desc->probe_callback,
                                event));
-       lttng_event_put(event->desc);
-register_error:
+tracepoint_register_error:
+sessiond_register_error:
        free(event);
 cache_error:
+socket_error:
 exist:
-full:
        return ret;
 }
 
@@ -499,17 +523,24 @@ void lttng_create_event_if_missing(struct lttng_enabler *enabler)
        cds_list_for_each_entry(probe_desc, probe_list, head) {
                for (i = 0; i < probe_desc->nr_events; i++) {
                        int found = 0, ret;
+                       struct cds_hlist_head *head;
+                       struct cds_hlist_node *node;
+                       const char *event_name;
+                       size_t name_len;
+                       uint32_t hash;
 
                        desc = probe_desc->event_desc[i];
                        if (!lttng_desc_match_enabler(desc, enabler))
                                continue;
+                       event_name = desc->name;
+                       name_len = strlen(event_name);
 
                        /*
-                        * For each event in session event list,
-                        * check if already created.
+                        * Check if already created.
                         */
-                       cds_list_for_each_entry(event,
-                                       &session->events_head, node) {
+                       hash = jhash(event_name, name_len, 0);
+                       head = &session->events_ht.table[hash & (LTTNG_UST_EVENT_HT_SIZE - 1)];
+                       cds_hlist_for_each_entry(event, node, head, hlist) {
                                if (event->desc == desc)
                                        found = 1;
                        }
@@ -523,8 +554,8 @@ void lttng_create_event_if_missing(struct lttng_enabler *enabler)
                        ret = lttng_event_create(probe_desc->event_desc[i],
                                        enabler->chan);
                        if (ret) {
-                               DBG("Unable to create event %s\n",
-                                       probe_desc->event_desc[i]->name);
+                               DBG("Unable to create event %s, error %d\n",
+                                       probe_desc->event_desc[i]->name, ret);
                        }
                }
        }
@@ -610,7 +641,6 @@ void _lttng_event_destroy(struct lttng_event *event)
 {
        struct lttng_enabler_ref *enabler_ref, *tmp_enabler_ref;
 
-       lttng_event_put(event->desc);
        cds_list_del(&event->node);
        lttng_destroy_context(event->ctx);
        lttng_free_event_filter_runtime(event);
@@ -1078,7 +1108,7 @@ uint64_t measure_clock_offset(void)
 static
 int _lttng_session_metadata_statedump(struct lttng_session *session)
 {
-       unsigned char *uuid_c = session->uuid;
+       unsigned char *uuid_c;
        char uuid_s[LTTNG_UST_UUID_STR_LEN],
                clock_uuid_s[LTTNG_UST_UUID_STR_LEN];
        struct lttng_channel *chan;
@@ -1095,6 +1125,7 @@ int _lttng_session_metadata_statedump(struct lttng_session *session)
                DBG("LTTng: attempt to start tracing, but metadata channel is not found. Operation abort.\n");
                return -EPERM;
        }
+       uuid_c = session->metadata->uuid;
 
        snprintf(uuid_s, sizeof(uuid_s),
                "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
@@ -1391,10 +1422,11 @@ void lttng_session_sync_enablers(struct lttng_session *session)
                }
                event->enabled = enabled;
 
-               /* Check if has enablers without bytecode */
+               /* Check if has enablers without bytecode enabled */
                cds_list_for_each_entry(enabler_ref,
                                &event->enablers_ref_head, node) {
-                       if (cds_list_empty(&enabler_ref->ref->filter_bytecode_head)) {
+                       if (enabler_ref->ref->enabled
+                                       && cds_list_empty(&enabler_ref->ref->filter_bytecode_head)) {
                                has_enablers_without_bytecode = 1;
                                break;
                        }
@@ -1407,7 +1439,6 @@ void lttng_session_sync_enablers(struct lttng_session *session)
                                &event->bytecode_runtime_head, node) {
                        lttng_filter_sync_state(runtime);
                }
-
        }
 }
 
@@ -1425,16 +1456,3 @@ void lttng_session_lazy_sync_enablers(struct lttng_session *session)
                return;
        lttng_session_sync_enablers(session);
 }
-
-/*
- * Take the TLS "fault" in libuuid if dlopen'd, which can take the
- * dynamic linker mutex, outside of the UST lock, since the UST lock is
- * taken in constructors, which are called with dynamic linker mutex
- * held.
- */
-void lttng_fixup_event_tls(void)
-{
-       unsigned char uuid[LTTNG_UST_UUID_STR_LEN];
-
-       (void) lttng_ust_uuid_generate(uuid);
-}
This page took 0.027147 seconds and 4 git commands to generate.