tracepoint: Refactor representation of nested types
[lttng-ust.git] / liblttng-ust-comm / lttng-ust-comm.c
index 814ccde17954b82200242e4ec03304907c2fac5c..d7991f19b6098b97f1333f013e332df426c3bf0d 100644 (file)
@@ -55,6 +55,11 @@ static
 int serialize_one_field(struct lttng_session *session,
                struct ustctl_field *fields, size_t *iter_output,
                const struct lttng_event_field *lf);
+static
+int serialize_fields(struct lttng_session *session,
+               struct ustctl_field *ustctl_fields,
+               size_t *iter_output, size_t nr_lttng_fields,
+               const struct lttng_event_field *lttng_fields);
 
 /*
  * Human readable error message.
@@ -773,8 +778,18 @@ ssize_t count_one_type(const struct lttng_type *lt)
        case atype_sequence:
                return 1;
        case atype_struct:
-               //TODO: implement non-empty struct.
-               return 1;
+               return count_fields_recursive(lt->u.legacy._struct.nr_fields,
+                               lt->u.legacy._struct.fields);
+       case atype_enum_nestable:
+               return count_one_type(lt->u.enum_nestable.container_type) + 1;
+       case atype_array_nestable:
+               return count_one_type(lt->u.array_nestable.elem_type) + 1;
+       case atype_sequence_nestable:
+               return count_one_type(lt->u.sequence_nestable.elem_type) + 1;
+       case atype_struct_nestable:
+               return count_fields_recursive(lt->u.struct_nestable.nr_fields,
+                               lt->u.struct_nestable.fields);
+
        case atype_dynamic:
        {
                const struct lttng_event_field *choices;
@@ -791,6 +806,7 @@ ssize_t count_one_type(const struct lttng_type *lt)
                 */
                return count_fields_recursive(nr_choices, choices) + 2;
        }
+
        default:
                return -EINVAL;
        }
@@ -939,7 +955,10 @@ int serialize_basic_type(struct lttng_session *session,
                break;
        }
        case atype_array:
+       case atype_array_nestable:
        case atype_sequence:
+       case atype_sequence_nestable:
+       case atype_enum_nestable:
        default:
                return -EINVAL;
        }
@@ -949,7 +968,7 @@ int serialize_basic_type(struct lttng_session *session,
 static
 int serialize_dynamic_type(struct lttng_session *session,
                struct ustctl_field *fields, size_t *iter_output,
-               const struct lttng_event_field *lf)
+               const char *field_name)
 {
        const struct lttng_event_field *choices;
        char tag_field_name[LTTNG_UST_SYM_NAME_LEN];
@@ -967,7 +986,7 @@ int serialize_dynamic_type(struct lttng_session *session,
        tag_type = &tag_field_generic->type;
 
        /* Serialize enum field. */
-       strncpy(tag_field_name, lf->name, LTTNG_UST_SYM_NAME_LEN);
+       strncpy(tag_field_name, field_name, LTTNG_UST_SYM_NAME_LEN);
        tag_field_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
        strncat(tag_field_name,
                "_tag",
@@ -984,14 +1003,15 @@ int serialize_dynamic_type(struct lttng_session *session,
        if (ret)
                return ret;
 
-       strncpy(uf->name, lf->name, LTTNG_UST_SYM_NAME_LEN);
+       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
        uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
        uf->type.atype = ustctl_atype_variant;
-       uf->type.u.variant.nr_choices = nr_choices;
-       strncpy(uf->type.u.variant.tag_name,
+       uf->type.u.variant_nestable.nr_choices = nr_choices;
+       strncpy(uf->type.u.variant_nestable.tag_name,
                tag_field_name,
                LTTNG_UST_SYM_NAME_LEN);
-       uf->type.u.variant.tag_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+       uf->type.u.variant_nestable.tag_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+       uf->type.u.variant_nestable.alignment = 0;
        (*iter_output)++;
 
        /* Serialize choice fields after variant. */
@@ -1005,16 +1025,16 @@ int serialize_dynamic_type(struct lttng_session *session,
 }
 
 static
-int serialize_one_field(struct lttng_session *session,
+int serialize_one_type(struct lttng_session *session,
                struct ustctl_field *fields, size_t *iter_output,
-               const struct lttng_event_field *lf)
+               const char *field_name, const struct lttng_type *lt)
 {
-       const struct lttng_type *lt = &lf->type;
        int ret;
 
-       /* skip 'nowrite' fields */
-       if (lf->nowrite)
-               return 0;
+       /*
+        * Serializing a type (rather than a field) generates a ustctl_field
+        * entry with 0-length name.
+        */
 
        switch (lt->atype) {
        case atype_integer:
@@ -1026,10 +1046,14 @@ int serialize_one_field(struct lttng_session *session,
                struct ustctl_type *ut = &uf->type;
                enum ustctl_abstract_types atype;
 
-               strncpy(uf->name, lf->name, LTTNG_UST_SYM_NAME_LEN);
-               uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               if (field_name) {
+                       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
+                       uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               } else {
+                       uf->name[0] = '\0';
+               }
                ret = serialize_basic_type(session, &atype, lt->atype,
-                       &ut->u.basic, &lt->u.basic);
+                       &ut->u.legacy.basic, &lt->u.legacy.basic);
                if (ret)
                        return ret;
                ut->atype = atype;
@@ -1044,21 +1068,46 @@ int serialize_one_field(struct lttng_session *session,
                const struct lttng_basic_type *lbt;
                enum ustctl_abstract_types atype;
 
-               strncpy(uf->name, lf->name, LTTNG_UST_SYM_NAME_LEN);
-               uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
-               uf->type.atype = ustctl_atype_array;
-               ubt = &ut->u.array.elem_type;
-               lbt = &lt->u.array.elem_type;
-               ut->u.array.length = lt->u.array.length;
+               if (field_name) {
+                       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
+                       uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               } else {
+                       uf->name[0] = '\0';
+               }
+               ut->atype = ustctl_atype_array;
+               ubt = &ut->u.legacy.array.elem_type;
+               lbt = &lt->u.legacy.array.elem_type;
+               ut->u.legacy.array.length = lt->u.legacy.array.length;
                ret = serialize_basic_type(session, &atype, lbt->atype,
                        &ubt->u.basic, &lbt->u.basic);
                if (ret)
                        return -EINVAL;
                ubt->atype = atype;
-               ut->atype = ustctl_atype_array;
                (*iter_output)++;
                break;
        }
+       case atype_array_nestable:
+       {
+               struct ustctl_field *uf = &fields[*iter_output];
+               struct ustctl_type *ut = &uf->type;
+
+               if (field_name) {
+                       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
+                       uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               } else {
+                       uf->name[0] = '\0';
+               }
+               ut->atype = ustctl_atype_array_nestable;
+               ut->u.array_nestable.length = lt->u.array_nestable.length;
+               ut->u.array_nestable.alignment = lt->u.array_nestable.alignment;
+               (*iter_output)++;
+
+               ret = serialize_one_type(session, fields, iter_output, NULL,
+                               lt->u.array_nestable.elem_type);
+               if (ret)
+                       return -EINVAL;
+               break;
+       }
        case atype_sequence:
        {
                struct ustctl_field *uf = &fields[*iter_output];
@@ -1066,32 +1115,60 @@ int serialize_one_field(struct lttng_session *session,
                struct ustctl_basic_type *ubt;
                const struct lttng_basic_type *lbt;
                enum ustctl_abstract_types atype;
-               int ret;
 
-               strncpy(uf->name, lf->name, LTTNG_UST_SYM_NAME_LEN);
-               uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               if (field_name) {
+                       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
+                       uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               } else {
+                       uf->name[0] = '\0';
+               }
                uf->type.atype = ustctl_atype_sequence;
-               ubt = &ut->u.sequence.length_type;
-               lbt = &lt->u.sequence.length_type;
+               ubt = &ut->u.legacy.sequence.length_type;
+               lbt = &lt->u.legacy.sequence.length_type;
                ret = serialize_basic_type(session, &atype, lbt->atype,
                        &ubt->u.basic, &lbt->u.basic);
                if (ret)
                        return -EINVAL;
                ubt->atype = atype;
-               ubt = &ut->u.sequence.elem_type;
-               lbt = &lt->u.sequence.elem_type;
+               ubt = &ut->u.legacy.sequence.elem_type;
+               lbt = &lt->u.legacy.sequence.elem_type;
                ret = serialize_basic_type(session, &atype, lbt->atype,
                        &ubt->u.basic, &lbt->u.basic);
                if (ret)
                        return -EINVAL;
                ubt->atype = atype;
-               ut->atype = ustctl_atype_sequence;
                (*iter_output)++;
                break;
        }
+       case atype_sequence_nestable:
+       {
+               struct ustctl_field *uf = &fields[*iter_output];
+               struct ustctl_type *ut = &uf->type;
+
+               if (field_name) {
+                       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
+                       uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               } else {
+                       uf->name[0] = '\0';
+               }
+               ut->atype = ustctl_atype_sequence_nestable;
+               strncpy(ut->u.sequence_nestable.length_name,
+                       lt->u.sequence_nestable.length_name,
+                       LTTNG_UST_SYM_NAME_LEN);
+               ut->u.sequence_nestable.length_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               ut->u.sequence_nestable.alignment = lt->u.sequence_nestable.alignment;
+               (*iter_output)++;
+
+               ret = serialize_one_type(session, fields, iter_output, NULL,
+                               lt->u.sequence_nestable.elem_type);
+               if (ret)
+                       return -EINVAL;
+               break;
+       }
        case atype_dynamic:
        {
-               ret = serialize_dynamic_type(session, fields, iter_output, lf);
+               ret = serialize_dynamic_type(session, fields, iter_output,
+                               field_name);
                if (ret)
                        return -EINVAL;
                break;
@@ -1100,17 +1177,76 @@ int serialize_one_field(struct lttng_session *session,
        {
                struct ustctl_field *uf = &fields[*iter_output];
 
-               /*
-                * TODO: add support for non-empty struct.
-                */
-               if (lf->type.u._struct.nr_fields != 0) {
-                       return -EINVAL;
+               if (field_name) {
+                       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
+                       uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               } else {
+                       uf->name[0] = '\0';
                }
-               strncpy(uf->name, lf->name, LTTNG_UST_SYM_NAME_LEN);
-               uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
                uf->type.atype = ustctl_atype_struct;
-               uf->type.u._struct.nr_fields = 0;
+               uf->type.u.legacy._struct.nr_fields = lt->u.legacy._struct.nr_fields;
                (*iter_output)++;
+
+               ret = serialize_fields(session, fields, iter_output,
+                               lt->u.legacy._struct.nr_fields,
+                               lt->u.legacy._struct.fields);
+               if (ret)
+                       return -EINVAL;
+               break;
+       }
+       case atype_struct_nestable:
+       {
+               struct ustctl_field *uf = &fields[*iter_output];
+
+               if (field_name) {
+                       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
+                       uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               } else {
+                       uf->name[0] = '\0';
+               }
+               uf->type.atype = ustctl_atype_struct_nestable;
+               uf->type.u.struct_nestable.nr_fields = lt->u.struct_nestable.nr_fields;
+               uf->type.u.struct_nestable.alignment = lt->u.struct_nestable.alignment;
+               (*iter_output)++;
+
+               ret = serialize_fields(session, fields, iter_output,
+                               lt->u.struct_nestable.nr_fields,
+                               lt->u.struct_nestable.fields);
+               if (ret)
+                       return -EINVAL;
+               break;
+       }
+       case atype_enum_nestable:
+       {
+               struct ustctl_field *uf = &fields[*iter_output];
+               struct ustctl_type *ut = &uf->type;
+
+               if (field_name) {
+                       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
+                       uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               } else {
+                       uf->name[0] = '\0';
+               }
+               strncpy(ut->u.enum_nestable.name, lt->u.enum_nestable.desc->name,
+                               LTTNG_UST_SYM_NAME_LEN);
+               ut->u.enum_nestable.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               ut->atype = ustctl_atype_enum_nestable;
+               (*iter_output)++;
+
+               ret = serialize_one_type(session, fields, iter_output, NULL,
+                               lt->u.enum_nestable.container_type);
+               if (ret)
+                       return -EINVAL;
+               if (session) {
+                       const struct lttng_enum *_enum;
+
+                       _enum = lttng_ust_enum_get_from_desc(session, lt->u.enum_nestable.desc);
+                       if (!_enum)
+                               return -EINVAL;
+                       ut->u.enum_nestable.id = _enum->id;
+               } else {
+                       ut->u.enum_nestable.id = -1ULL;
+               }
                break;
        }
        default:
@@ -1119,8 +1255,38 @@ int serialize_one_field(struct lttng_session *session,
        return 0;
 }
 
+static
+int serialize_one_field(struct lttng_session *session,
+               struct ustctl_field *fields, size_t *iter_output,
+               const struct lttng_event_field *lf)
+{
+       /* skip 'nowrite' fields */
+       if (lf->nowrite)
+               return 0;
+
+       return serialize_one_type(session, fields, iter_output, lf->name, &lf->type);
+}
+
 static
 int serialize_fields(struct lttng_session *session,
+               struct ustctl_field *ustctl_fields,
+               size_t *iter_output, size_t nr_lttng_fields,
+               const struct lttng_event_field *lttng_fields)
+{
+       int ret;
+       size_t i;
+
+       for (i = 0; i < nr_lttng_fields; i++) {
+               ret = serialize_one_field(session, ustctl_fields,
+                               iter_output, &lttng_fields[i]);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+static
+int alloc_serialize_fields(struct lttng_session *session,
                size_t *_nr_write_fields,
                struct ustctl_field **ustctl_fields,
                size_t nr_fields,
@@ -1128,7 +1294,7 @@ int serialize_fields(struct lttng_session *session,
 {
        struct ustctl_field *fields;
        int ret;
-       size_t i, iter_output = 0;
+       size_t iter_output = 0;
        ssize_t nr_write_fields;
 
        nr_write_fields = count_fields_recursive(nr_fields, lttng_fields);
@@ -1140,12 +1306,10 @@ int serialize_fields(struct lttng_session *session,
        if (!fields)
                return -ENOMEM;
 
-       for (i = 0; i < nr_fields; i++) {
-               ret = serialize_one_field(session, fields, &iter_output,
-                               &lttng_fields[i]);
-               if (ret)
-                       goto error_type;
-       }
+       ret = serialize_fields(session, fields, &iter_output, nr_fields,
+                       lttng_fields);
+       if (ret)
+               goto error_type;
 
        *_nr_write_fields = nr_write_fields;
        *ustctl_fields = fields;
@@ -1270,7 +1434,7 @@ int ustcomm_register_event(int sock,
 
        /* Calculate fields len, serialize fields. */
        if (nr_fields > 0) {
-               ret = serialize_fields(session, &nr_write_fields, &fields,
+               ret = alloc_serialize_fields(session, &nr_write_fields, &fields,
                                nr_fields, lttng_fields);
                if (ret)
                        return ret;
This page took 0.027987 seconds and 4 git commands to generate.