Global type declarations can be used more than once in a single tracepoint,
or many tracepoints can use it. It must be statedumped only once in a given
session.

Signed-off-by: Geneviève Bastien <[email protected]>
---
 src/bin/lttng-sessiond/ust-metadata.c | 46 +++++++++++++++++++++++
 src/bin/lttng-sessiond/ust-registry.c | 69 +++++++++++++++++++++++++++++++++++
 src/bin/lttng-sessiond/ust-registry.h | 15 ++++++++
 3 files changed, 130 insertions(+)

diff --git a/src/bin/lttng-sessiond/ust-metadata.c 
b/src/bin/lttng-sessiond/ust-metadata.c
index 743901a..dc144e1 100644
--- a/src/bin/lttng-sessiond/ust-metadata.c
+++ b/src/bin/lttng-sessiond/ust-metadata.c
@@ -322,6 +322,40 @@ int _lttng_one_global_type_statedump(struct 
ust_registry_session *session,
                const struct ustctl_global_type_decl *global_type_decl)
 {
        int ret = 0, i;
+       struct ust_registry_global_type_decl *global_type;
+       struct cds_lfht_node *nodep;
+       struct lttng_ht_iter iter;
+       struct lttng_ht_node_str *node;
+
+       /* Check if the global type was already dumped */
+       global_type = zmalloc(sizeof(*global_type));
+       if (!global_type) {
+               PERROR("zmalloc ust registry global type");
+               return -ENOMEM;
+       }
+       global_type->category = global_type_decl->mtype;
+       switch (global_type_decl->mtype) {
+       case ustctl_mtype_enum:
+               strncpy(global_type->name, global_type_decl->u.ctf_enum.name, 
LTTNG_UST_SYM_NAME_LEN);
+               global_type->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       rcu_read_lock();
+       cds_lfht_lookup(session->global_types_ht->ht, 
session->global_types_ht->hash_fct((void *) global_type, lttng_ht_seed),
+                       session->global_types_ht->match_fct, global_type, 
&iter.iter);
+       node = lttng_ht_iter_get_node_str(&iter);
+       if (node != NULL) {
+               DBG("global type %s already in metadata", global_type->name);
+               rcu_read_unlock();
+               free(global_type);
+               return ret;
+       }
+       cds_lfht_node_init(&global_type->node.node);
+       rcu_read_unlock();
+
 
        switch (global_type_decl->mtype) {
        case ustctl_mtype_enum:
@@ -371,6 +405,17 @@ int _lttng_one_global_type_statedump(struct 
ust_registry_session *session,
                return -EINVAL;
        }
 
+       /* Flag this global type as dumped */
+       /*
+        * This is an add unique with a custom match function for global types.
+        * The node are matched using the category and global type name.
+        */
+       rcu_read_lock();
+       nodep = cds_lfht_add_unique(session->global_types_ht->ht, 
session->global_types_ht->hash_fct(global_type, lttng_ht_seed),
+                       session->global_types_ht->match_fct, global_type, 
&global_type->node.node);
+       assert(nodep == &global_type->node.node);
+       rcu_read_unlock();
+
        return ret;
 }
 
@@ -388,6 +433,7 @@ int _lttng_global_type_decl_statedump(struct 
ust_registry_session *session,
                const struct ustctl_global_type_decl *global_type_decl = 
&event->global_type_decl[i];
 
                ret = _lttng_one_global_type_statedump(session, 
global_type_decl);
+               DBG("_lttng_global_type_decl_statedump %d", ret);
                if (ret)
                        return ret;
        }
diff --git a/src/bin/lttng-sessiond/ust-registry.c 
b/src/bin/lttng-sessiond/ust-registry.c
index 281ea7c..80df17a 100644
--- a/src/bin/lttng-sessiond/ust-registry.c
+++ b/src/bin/lttng-sessiond/ust-registry.c
@@ -73,6 +73,49 @@ static unsigned long ht_hash_event(void *_key, unsigned long 
seed)
 }
 
 /*
+ * Hash table match function for global type declarations in the session.
+ */
+static int ht_match_global_type(struct cds_lfht_node *node, const void *_key)
+{
+       struct ust_registry_global_type_decl *global_type;
+       const struct ust_registry_global_type_decl *key;
+
+       assert(node);
+       assert(_key);
+
+       global_type = caa_container_of(node, struct 
ust_registry_global_type_decl, node.node);
+       assert(global_type);
+       key = _key;
+
+       /* It has to be a perfect match. */
+       if (global_type->category != key->category) {
+               goto no_match;
+       }
+       if (strncmp(global_type->name, key->name, strlen(global_type->name) != 
0)) {
+               goto no_match;
+       }
+
+       /* Match */
+       return 1;
+
+no_match:
+       return 0;
+}
+
+static unsigned long ht_hash_global_type(void *_key, unsigned long seed)
+{
+       uint64_t xored_key;
+       struct ust_registry_global_type_decl *key = _key;
+
+       assert(key);
+
+       xored_key = (uint64_t) (hash_key_ulong((void *)key->category, seed) ^
+                               hash_key_str(key->name, seed));
+
+       return hash_key_u64(&xored_key, seed);
+}
+
+/*
  * Return negative value on error, 0 if OK.
  *
  * TODO: we could add stricter verification of more types to catch
@@ -570,6 +613,16 @@ int ust_registry_session_init(struct ust_registry_session 
**sessionp,
        session->uint64_t_alignment = uint64_t_alignment;
        session->long_alignment = long_alignment;
        session->byte_order = byte_order;
+       session->global_types_ht = 0;
+       session->global_types_ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
+       if (!session->global_types_ht) {
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       /* Set custom match function. */
+       session->global_types_ht->match_fct = ht_match_global_type;
+       session->global_types_ht->hash_fct = ht_hash_global_type;
 
        session->channels = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
        if (!session->channels) {
@@ -610,6 +663,7 @@ void ust_registry_session_destroy(struct 
ust_registry_session *reg)
        int ret;
        struct lttng_ht_iter iter;
        struct ust_registry_channel *chan;
+       struct ust_registry_global_type_decl *global_type;
 
        assert(reg);
 
@@ -632,4 +686,19 @@ void ust_registry_session_destroy(struct 
ust_registry_session *reg)
        }
 
        free(reg->metadata);
+
+       /* Destroy the global type hash table */
+       if (reg->global_types_ht) {
+               rcu_read_lock();
+               /* Destroy all global types associated with this registry. */
+               cds_lfht_for_each_entry(reg->global_types_ht->ht, &iter.iter, 
global_type,
+                               node.node) {
+                       /* Delete the node from the ht and free it. */
+                       ret = lttng_ht_del(reg->global_types_ht, &iter);
+                       assert(!ret);
+                       free(global_type);
+               }
+               rcu_read_unlock();
+               ht_cleanup_push(reg->global_types_ht);
+       }
 }
diff --git a/src/bin/lttng-sessiond/ust-registry.h 
b/src/bin/lttng-sessiond/ust-registry.h
index 8b41c2a..29bc120 100644
--- a/src/bin/lttng-sessiond/ust-registry.h
+++ b/src/bin/lttng-sessiond/ust-registry.h
@@ -31,6 +31,16 @@
 
 struct ust_app;
 
+struct ust_registry_global_type_decl {
+       uint32_t category;
+       char name[LTTNG_UST_SYM_NAME_LEN];
+       /*
+        * Node in the ust-session hash table. The global type name and
+        * category is used to initialize the node and for the match function.
+        */
+       struct lttng_ht_node_u64 node;
+};
+
 struct ust_registry_session {
        /*
         * With multiple writers and readers, use this lock to access the 
registry.
@@ -75,6 +85,11 @@ struct ust_registry_session {
         * deletes its sessions.
         */
        unsigned int metadata_closed;
+       /*
+        * Hash table containing global type declarations already dumped into 
the
+        * metadata. MUST be accessed with a RCU read side lock acquired.
+        */
+       struct lttng_ht *global_types_ht;
 };
 
 struct ust_registry_channel {
-- 
1.8.5.4


_______________________________________________
lttng-dev mailing list
[email protected]
http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev

Reply via email to