-/*
- * Hash table match function for event in the registry.
- */
-static int ht_match_event(struct cds_lfht_node *node, const void *_key)
-{
- const struct ust_registry_event *key;
- struct ust_registry_event *event;
-
- LTTNG_ASSERT(node);
- LTTNG_ASSERT(_key);
-
- event = caa_container_of(node, struct ust_registry_event, node.node);
- LTTNG_ASSERT(event);
- key = (ust_registry_event *) _key;
-
- /* It has to be a perfect match. First, compare the event names. */
- if (strncmp(event->name, key->name, sizeof(event->name))) {
- goto no_match;
- }
-
- /* Compare log levels. */
- if (event->loglevel_value != key->loglevel_value) {
- goto no_match;
- }
-
- /* Compare the arrays of fields. */
- if (!match_lttng_ust_ctl_field_array(event->fields, event->nr_fields,
- key->fields, key->nr_fields)) {
- goto no_match;
- }
-
- /* Compare model URI. */
- if (event->model_emf_uri != NULL && key->model_emf_uri == NULL) {
- goto no_match;
- } else if(event->model_emf_uri == NULL && key->model_emf_uri != NULL) {
- goto no_match;
- } else if (event->model_emf_uri != NULL && key->model_emf_uri != NULL) {
- if (strcmp(event->model_emf_uri, key->model_emf_uri)) {
- goto no_match;
- }
- }
-
- /* Match */
- return 1;
-
-no_match:
- return 0;
-}
-
-static unsigned long ht_hash_event(const void *_key, unsigned long seed)
-{
- uint64_t hashed_key;
- const struct ust_registry_event *key = (ust_registry_event *) _key;
-
- LTTNG_ASSERT(key);
-
- hashed_key = (uint64_t) hash_key_str(key->name, seed);
-
- return hash_key_u64(&hashed_key, seed);
-}
-
-static int compare_enums(const struct ust_registry_enum *reg_enum_a,
- const struct ust_registry_enum *reg_enum_b)
-{
- int ret = 0;
- size_t i;
-
- LTTNG_ASSERT(strcmp(reg_enum_a->name, reg_enum_b->name) == 0);
- if (reg_enum_a->nr_entries != reg_enum_b->nr_entries) {
- ret = -1;
- goto end;
- }
- for (i = 0; i < reg_enum_a->nr_entries; i++) {
- const struct lttng_ust_ctl_enum_entry *entries_a, *entries_b;
-
- entries_a = ®_enum_a->entries[i];
- entries_b = ®_enum_b->entries[i];
- if (entries_a->start.value != entries_b->start.value) {
- ret = -1;
- goto end;
- }
- if (entries_a->end.value != entries_b->end.value) {
- ret = -1;
- goto end;
- }
- if (entries_a->start.signedness != entries_b->start.signedness) {
- ret = -1;
- goto end;
- }
- if (entries_a->end.signedness != entries_b->end.signedness) {
- ret = -1;
- goto end;
- }
-
- if (strcmp(entries_a->string, entries_b->string)) {
- ret = -1;
- goto end;
- }
- }
-end:
- return ret;
-}
-
-/*
- * Hash table match function for enumerations in the session. Match is
- * performed on enumeration name, and confirmed by comparing the enum
- * entries.
- */
-static int ht_match_enum(struct cds_lfht_node *node, const void *_key)
-{
- struct ust_registry_enum *_enum;
- const struct ust_registry_enum *key;
-
- LTTNG_ASSERT(node);
- LTTNG_ASSERT(_key);
-
- _enum = caa_container_of(node, struct ust_registry_enum,
- node.node);
- LTTNG_ASSERT(_enum);
- key = (ust_registry_enum *) _key;
-
- if (strncmp(_enum->name, key->name, LTTNG_UST_ABI_SYM_NAME_LEN)) {
- goto no_match;
- }
- if (compare_enums(_enum, key)) {
- goto no_match;
- }
-
- /* Match. */
- return 1;
-
-no_match:
- return 0;
-}
-
-/*
- * Hash table match function for enumerations in the session. Match is
- * performed by enumeration ID.
- */
-static int ht_match_enum_id(struct cds_lfht_node *node, const void *_key)
-{
- struct ust_registry_enum *_enum;
- const struct ust_registry_enum *key = (ust_registry_enum *) _key;
-
- LTTNG_ASSERT(node);
- LTTNG_ASSERT(_key);
-
- _enum = caa_container_of(node, struct ust_registry_enum, node.node);
- LTTNG_ASSERT(_enum);
-
- if (_enum->id != key->id) {
- goto no_match;
- }
-
- /* Match. */
- return 1;
-
-no_match:
- return 0;
-}
-
-/*
- * Hash table hash function for enumerations in the session. The
- * enumeration name is used for hashing.
- */
-static unsigned long ht_hash_enum(void *_key, unsigned long seed)
-{
- struct ust_registry_enum *key = (ust_registry_enum *) _key;
-
- LTTNG_ASSERT(key);
- return hash_key_str(key->name, seed);
-}
-
-/*
- * Return negative value on error, 0 if OK.
- *
- * TODO: we could add stricter verification of more types to catch
- * errors in liblttng-ust implementation earlier than consumption by the
- * trace reader.
- */
-static
-int validate_event_field(struct lttng_ust_ctl_field *field,
- const char *event_name,
- struct ust_app *app)
-{
- int ret = 0;
-
- switch(field->type.atype) {
- case lttng_ust_ctl_atype_integer:
- case lttng_ust_ctl_atype_enum:
- case lttng_ust_ctl_atype_array:
- case lttng_ust_ctl_atype_sequence:
- case lttng_ust_ctl_atype_string:
- case lttng_ust_ctl_atype_variant:
- case lttng_ust_ctl_atype_array_nestable:
- case lttng_ust_ctl_atype_sequence_nestable:
- case lttng_ust_ctl_atype_enum_nestable:
- case lttng_ust_ctl_atype_variant_nestable:
- break;
- case lttng_ust_ctl_atype_struct:
- if (field->type.u.legacy._struct.nr_fields != 0) {
- WARN("Unsupported non-empty struct field.");
- ret = -EINVAL;
- goto end;
- }
- break;
- case lttng_ust_ctl_atype_struct_nestable:
- if (field->type.u.struct_nestable.nr_fields != 0) {
- WARN("Unsupported non-empty struct field.");
- ret = -EINVAL;
- goto end;
- }
- break;
-
- case lttng_ust_ctl_atype_float:
- switch (field->type.u._float.mant_dig) {
- case 0:
- WARN("UST application '%s' (pid: %d) has unknown float mantissa '%u' "
- "in field '%s', rejecting event '%s'",
- app->name, app->pid,
- field->type.u._float.mant_dig,
- field->name,
- event_name);
- ret = -EINVAL;
- goto end;
- default:
- break;
- }
- break;
-
- default:
- ret = -ENOENT;
- goto end;
- }
-end:
- return ret;
-}
-
-static
-int validate_event_fields(size_t nr_fields, struct lttng_ust_ctl_field *fields,
- const char *event_name, struct ust_app *app)
-{
- unsigned int i;
-
- for (i = 0; i < nr_fields; i++) {
- if (validate_event_field(&fields[i], event_name, app) < 0)
- return -EINVAL;
- }
- return 0;
-}
-
-/*
- * Allocate event and initialize it. This does NOT set a valid event id from a
- * registry.
- */
-static struct ust_registry_event *alloc_event(int session_objd,
- int channel_objd, char *name, char *sig, size_t nr_fields,
- struct lttng_ust_ctl_field *fields, int loglevel_value,
- char *model_emf_uri, struct ust_app *app)
-{
- struct ust_registry_event *event = NULL;
-
- /*
- * Ensure that the field content is valid.
- */
- if (validate_event_fields(nr_fields, fields, name, app) < 0) {
- return NULL;
- }
-
- event = (ust_registry_event *) zmalloc(sizeof(*event));
- if (!event) {
- PERROR("zmalloc ust registry event");
- goto error;
- }
-
- event->session_objd = session_objd;
- event->channel_objd = channel_objd;
- /* Allocated by ustctl. */
- event->signature = sig;
- event->nr_fields = nr_fields;
- event->fields = fields;
- event->loglevel_value = loglevel_value;
- event->model_emf_uri = model_emf_uri;
- if (name) {
- /* Copy event name and force NULL byte. */
- strncpy(event->name, name, sizeof(event->name));
- event->name[sizeof(event->name) - 1] = '\0';
- }
- cds_lfht_node_init(&event->node.node);