[lttng-dev] [Patch LTTng-tools v2 4/5] Dump a global type only once per session

Geneviève Bastien gbastien+lttng at versatic.net
Tue Feb 11 16:40:51 EST 2014


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 <gbastien+lttng at versatic.net>
---
 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




More information about the lttng-dev mailing list