sequence type: use previous field for length if length_name is NULL
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Mon, 12 Apr 2021 18:04:36 +0000 (14:04 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 24 Apr 2021 00:13:00 +0000 (20:13 -0400)
A common use-case for sequences is to use the field located immediately
prior to the sequence as sequence length.

The fact that the sequence type needs to explicitly contain its length
name ties the sequence type to where it is placed within the structure
fields, preventing re-use of the sequence type.

In order to reduce the memory footprint of the field descriptions and
allow re-use of common field types, special-case the NULL length_name to
use the field prior to the sequence as length.

This allows more efficient type descriptions without reducing the
overall flexibility of sequence layout.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Change-Id: I5f2ae22ecc4d872d56f9302751990452fc34cb15

include/lttng/ust-events.h
include/lttng/ust-tracepoint-event.h
src/common/ustcomm.c

index cae9e71a55ef1cecbc2ebbc9b3e06222e6ddbb98..6920306846f2bc273d883b027403d97281492adb 100644 (file)
@@ -193,7 +193,7 @@ struct lttng_ust_type_array {
 struct lttng_ust_type_sequence {
        struct lttng_ust_type_common parent;
        uint32_t struct_size;
-       const char *length_name;        /* Length field name. */
+       const char *length_name;        /* Length field name. If NULL, use previous field. */
        const struct lttng_ust_type_common *elem_type;
        unsigned int alignment;         /* Minimum alignment before elements. */
        enum lttng_ust_string_encoding encoding;
index 654b367f173c7fa3c738e7f333e02bb3f539b823..586f59f9643cd392720cf0c81ce35986e1c0e482 100644 (file)
@@ -360,7 +360,7 @@ void lttng_ust__event_template_proto___##_provider##___##_name(LTTNG_UST__TP_ARG
                                .type = lttng_ust_type_sequence, \
                        },                                      \
                        .struct_size = sizeof(struct lttng_ust_type_sequence), \
-                       .length_name = "_" #_item "_length",    \
+                       .length_name = NULL,    /* Use previous field. */ \
                        .elem_type = lttng_ust_type_integer_define(_type, _byte_order, _elem_type_base), \
                        .alignment = 0,                         \
                        .encoding = lttng_ust_string_encoding_##_encoding, \
index 00cbf5a73bae82b0a30568490eb9923706036125..ada896f68f60ad1b0d077a4786c63b44f45c123d 100644 (file)
@@ -37,7 +37,8 @@ ssize_t count_fields_recursive(size_t nr_fields,
 static
 int serialize_one_field(struct lttng_ust_session *session,
                struct lttng_ust_ctl_field *fields, size_t *iter_output,
-               const struct lttng_ust_event_field *lf);
+               const struct lttng_ust_event_field *lf,
+               const char **prev_field_name);
 static
 int serialize_fields(struct lttng_ust_session *session,
                struct lttng_ust_ctl_field *lttng_ust_ctl_fields,
@@ -973,7 +974,7 @@ int serialize_dynamic_type(struct lttng_ust_session *session,
                LTTNG_UST_ABI_SYM_NAME_LEN - strlen(tag_field_name) - 1);
        tag_field.type = tag_type;
        ret = serialize_one_field(session, fields, iter_output,
-               &tag_field);
+               &tag_field, NULL);
        if (ret)
                return ret;
 
@@ -997,7 +998,7 @@ int serialize_dynamic_type(struct lttng_ust_session *session,
        /* Serialize choice fields after variant. */
        for (i = 0; i < nr_choices; i++) {
                ret = serialize_one_field(session, fields,
-                       iter_output, choices[i]);
+                       iter_output, choices[i], NULL);
                if (ret)
                        return ret;
        }
@@ -1008,7 +1009,8 @@ static
 int serialize_one_type(struct lttng_ust_session *session,
                struct lttng_ust_ctl_field *fields, size_t *iter_output,
                const char *field_name, const struct lttng_ust_type_common *lt,
-               enum lttng_ust_string_encoding parent_encoding)
+               enum lttng_ust_string_encoding parent_encoding,
+               const char *prev_field_name)
 {
        int ret;
 
@@ -1098,7 +1100,7 @@ int serialize_one_type(struct lttng_ust_session *session,
 
                ret = serialize_one_type(session, fields, iter_output, NULL,
                                lttng_ust_get_type_array(lt)->elem_type,
-                               lttng_ust_get_type_array(lt)->encoding);
+                               lttng_ust_get_type_array(lt)->encoding, NULL);
                if (ret)
                        return -EINVAL;
                break;
@@ -1107,6 +1109,7 @@ int serialize_one_type(struct lttng_ust_session *session,
        {
                struct lttng_ust_ctl_field *uf = &fields[*iter_output];
                struct lttng_ust_ctl_type *ut = &uf->type;
+               const char *length_name = lttng_ust_get_type_sequence(lt)->length_name;
 
                if (field_name) {
                        strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
@@ -1115,16 +1118,23 @@ int serialize_one_type(struct lttng_ust_session *session,
                        uf->name[0] = '\0';
                }
                ut->atype = lttng_ust_ctl_atype_sequence_nestable;
+               /*
+                * If length_name field is NULL, use the previous field
+                * as length.
+                */
+               if (!length_name)
+                       length_name = prev_field_name;
+               if (!length_name)
+                       return -EINVAL;
                strncpy(ut->u.sequence_nestable.length_name,
-                       lttng_ust_get_type_sequence(lt)->length_name,
-                       LTTNG_UST_ABI_SYM_NAME_LEN);
+                       length_name, LTTNG_UST_ABI_SYM_NAME_LEN);
                ut->u.sequence_nestable.length_name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
                ut->u.sequence_nestable.alignment = lttng_ust_get_type_sequence(lt)->alignment;
                (*iter_output)++;
 
                ret = serialize_one_type(session, fields, iter_output, NULL,
                                lttng_ust_get_type_sequence(lt)->elem_type,
-                               lttng_ust_get_type_sequence(lt)->encoding);
+                               lttng_ust_get_type_sequence(lt)->encoding, NULL);
                if (ret)
                        return -EINVAL;
                break;
@@ -1178,7 +1188,7 @@ int serialize_one_type(struct lttng_ust_session *session,
 
                ret = serialize_one_type(session, fields, iter_output, NULL,
                                lttng_ust_get_type_enum(lt)->container_type,
-                               lttng_ust_string_encoding_none);
+                               lttng_ust_string_encoding_none, NULL);
                if (ret)
                        return -EINVAL;
                if (session) {
@@ -1202,13 +1212,23 @@ int serialize_one_type(struct lttng_ust_session *session,
 static
 int serialize_one_field(struct lttng_ust_session *session,
                struct lttng_ust_ctl_field *fields, size_t *iter_output,
-               const struct lttng_ust_event_field *lf)
+               const struct lttng_ust_event_field *lf,
+               const char **prev_field_name_p)
 {
+       const char *prev_field_name = NULL;
+       int ret;
+
        /* skip 'nowrite' fields */
        if (lf->nowrite)
                return 0;
 
-       return serialize_one_type(session, fields, iter_output, lf->name, lf->type, lttng_ust_string_encoding_none);
+       if (prev_field_name_p)
+               prev_field_name = *prev_field_name_p;
+       ret = serialize_one_type(session, fields, iter_output, lf->name, lf->type,
+                       lttng_ust_string_encoding_none, prev_field_name);
+       if (prev_field_name_p)
+               *prev_field_name_p = lf->name;
+       return ret;
 }
 
 static
@@ -1217,12 +1237,14 @@ int serialize_fields(struct lttng_ust_session *session,
                size_t *iter_output, size_t nr_lttng_fields,
                const struct lttng_ust_event_field * const *lttng_fields)
 {
+       const char *prev_field_name = NULL;
        int ret;
        size_t i;
 
        for (i = 0; i < nr_lttng_fields; i++) {
                ret = serialize_one_field(session, lttng_ust_ctl_fields,
-                               iter_output, lttng_fields[i]);
+                               iter_output, lttng_fields[i],
+                               &prev_field_name);
                if (ret)
                        return ret;
        }
@@ -1307,9 +1329,10 @@ int serialize_ctx_fields(struct lttng_ust_session *session,
                struct lttng_ust_ctx_field *lttng_fields)
 {
        struct lttng_ust_ctl_field *fields;
-       int ret;
+       const char *prev_field_name = NULL;
        size_t i, iter_output = 0;
        ssize_t nr_write_fields;
+       int ret;
 
        nr_write_fields = count_ctx_fields_recursive(nr_fields,
                        lttng_fields);
@@ -1323,7 +1346,7 @@ int serialize_ctx_fields(struct lttng_ust_session *session,
 
        for (i = 0; i < nr_fields; i++) {
                ret = serialize_one_field(session, fields, &iter_output,
-                               lttng_fields[i].event_field);
+                               lttng_fields[i].event_field, &prev_field_name);
                if (ret)
                        goto error_type;
        }
This page took 0.028677 seconds and 4 git commands to generate.