Implement variant type
[lttng-modules.git] / lttng-events.c
index 71b530177a3c22c9cd0b6cae032c5172130cbc31..0c72015fd1a56edc79f4ef9e4106c8aa3745c48c 100644 (file)
 #include <linux/seq_file.h>
 #include <linux/file.h>
 #include <linux/anon_inodes.h>
-#include "wrapper/file.h"
+#include <wrapper/file.h>
 #include <linux/jhash.h>
 #include <linux/uaccess.h>
 #include <linux/vmalloc.h>
 
-#include "wrapper/uuid.h"
-#include "wrapper/vmalloc.h"   /* for wrapper_vmalloc_sync_all() */
-#include "wrapper/random.h"
-#include "wrapper/tracepoint.h"
-#include "wrapper/list.h"
-#include "lttng-kernel-version.h"
-#include "lttng-events.h"
-#include "lttng-tracer.h"
-#include "lttng-abi-old.h"
-#include "wrapper/vzalloc.h"
+#include <wrapper/uuid.h>
+#include <wrapper/vmalloc.h>   /* for wrapper_vmalloc_sync_all() */
+#include <wrapper/random.h>
+#include <wrapper/tracepoint.h>
+#include <wrapper/list.h>
+#include <lttng-kernel-version.h>
+#include <lttng-events.h>
+#include <lttng-tracer.h>
+#include <lttng-abi-old.h>
+#include <lttng-endian.h>
+#include <wrapper/vzalloc.h>
 
 #define METADATA_CACHE_DEFAULT_SIZE 4096
 
@@ -77,6 +78,10 @@ static
 int _lttng_session_metadata_statedump(struct lttng_session *session);
 static
 void _lttng_metadata_channel_hangup(struct lttng_metadata_stream *stream);
+static
+int _lttng_field_statedump(struct lttng_session *session,
+               const struct lttng_event_field *field,
+               size_t nesting);
 
 void synchronize_trace(void)
 {
@@ -1660,19 +1665,221 @@ err:
        return -ENOMEM;
 }
 
+static
+int print_tabs(struct lttng_session *session, size_t nesting)
+{
+       size_t i;
+
+       for (i = 0; i < nesting; i++) {
+               int ret;
+
+               ret = lttng_metadata_printf(session, "  ");
+               if (ret) {
+                       return ret;
+               }
+       }
+       return 0;
+}
+
+/*
+ * Must be called with sessions_mutex held.
+ */
+static
+int _lttng_struct_type_statedump(struct lttng_session *session,
+               const struct lttng_type *type,
+               size_t nesting)
+{
+       int ret;
+       uint32_t i, nr_fields;
+
+       ret = print_tabs(session, nesting);
+       if (ret)
+               return ret;
+       ret = lttng_metadata_printf(session,
+               "struct {\n");
+       if (ret)
+               return ret;
+       nr_fields = type->u._struct.nr_fields;
+       for (i = 0; i < nr_fields; i++) {
+               const struct lttng_event_field *iter_field;
+
+               iter_field = &type->u._struct.fields[i];
+               ret = _lttng_field_statedump(session, iter_field, nesting + 1);
+               if (ret)
+                       return ret;
+       }
+       ret = print_tabs(session, nesting);
+       if (ret)
+               return ret;
+       ret = lttng_metadata_printf(session,
+               "}");
+       return ret;
+}
+
+/*
+ * Must be called with sessions_mutex held.
+ */
+static
+int _lttng_struct_statedump(struct lttng_session *session,
+               const struct lttng_event_field *field,
+               size_t nesting)
+{
+       int ret;
+
+       ret = _lttng_struct_type_statedump(session,
+                       &field->type, nesting);
+       if (ret)
+               return ret;
+       ret = lttng_metadata_printf(session,
+               "_%s;\n",
+               field->name);
+       return ret;
+}
+
+/*
+ * Must be called with sessions_mutex held.
+ */
+static
+int _lttng_variant_type_statedump(struct lttng_session *session,
+               const struct lttng_type *type,
+               size_t nesting)
+{
+       int ret;
+       uint32_t i, nr_choices;
+
+       ret = print_tabs(session, nesting);
+       if (ret)
+               return ret;
+       ret = lttng_metadata_printf(session,
+               "variant <_%s> {\n",
+               type->u.variant.tag_name);
+       if (ret)
+               return ret;
+       nr_choices = type->u.variant.nr_choices;
+       for (i = 0; i < nr_choices; i++) {
+               const struct lttng_event_field *iter_field;
+
+               iter_field = &type->u.variant.choices[i];
+               ret = _lttng_field_statedump(session, iter_field, nesting + 1);
+               if (ret)
+                       return ret;
+       }
+       ret = print_tabs(session, nesting);
+       if (ret)
+               return ret;
+       ret = lttng_metadata_printf(session,
+               "}");
+       return ret;
+}
+
+/*
+ * Must be called with sessions_mutex held.
+ */
+static
+int _lttng_variant_statedump(struct lttng_session *session,
+               const struct lttng_event_field *field,
+               size_t nesting)
+{
+       int ret;
+
+       ret = _lttng_variant_type_statedump(session,
+                       &field->type, nesting);
+       if (ret)
+               return ret;
+       ret = lttng_metadata_printf(session,
+               "_%s;\n",
+               field->name);
+       return ret;
+}
+
+/*
+ * Must be called with sessions_mutex held.
+ */
+static
+int _lttng_array_compound_statedump(struct lttng_session *session,
+               const struct lttng_event_field *field,
+               size_t nesting)
+{
+       int ret;
+       const struct lttng_type *elem_type;
+
+       /* Only array of structures and variants are currently supported. */
+       elem_type = field->type.u.array_compound.elem_type;
+       switch (elem_type->atype) {
+       case atype_struct:
+               ret = _lttng_struct_type_statedump(session, elem_type, nesting);
+               if (ret)
+                       return ret;
+               break;
+       case atype_variant:
+               ret = _lttng_variant_type_statedump(session, elem_type, nesting);
+               if (ret)
+                       return ret;
+               break;
+       default:
+               return -EINVAL;
+       }
+       ret = lttng_metadata_printf(session,
+               " _%s[%u];\n",
+               field->name,
+               field->type.u.array_compound.length);
+       return ret;
+}
+
+/*
+ * Must be called with sessions_mutex held.
+ */
+static
+int _lttng_sequence_compound_statedump(struct lttng_session *session,
+               const struct lttng_event_field *field,
+               size_t nesting)
+{
+       int ret;
+       const char *length_name;
+       const struct lttng_type *elem_type;
+
+       length_name = field->type.u.sequence_compound.length_name;
+
+       /* Only array of structures and variants are currently supported. */
+       elem_type = field->type.u.sequence_compound.elem_type;
+       switch (elem_type->atype) {
+       case atype_struct:
+               ret = _lttng_struct_type_statedump(session, elem_type, nesting);
+               if (ret)
+                       return ret;
+               break;
+       case atype_variant:
+               ret = _lttng_variant_type_statedump(session, elem_type, nesting);
+               if (ret)
+                       return ret;
+               break;
+       default:
+               return -EINVAL;
+       }
+       ret = lttng_metadata_printf(session,
+               " _%s[ _%s ];\n",
+               field->name,
+               length_name);
+       return ret;
+}
+
 /*
  * Must be called with sessions_mutex held.
  */
 static
 int _lttng_field_statedump(struct lttng_session *session,
-                        const struct lttng_event_field *field)
+               const struct lttng_event_field *field,
+               size_t nesting)
 {
        int ret = 0;
 
        switch (field->type.atype) {
        case atype_integer:
+               ret = print_tabs(session, nesting);
+               if (ret)
+                       return ret;
                ret = lttng_metadata_printf(session,
-                       "               integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n",
+                       "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n",
                        field->type.u.basic.integer.size,
                        field->type.u.basic.integer.alignment,
                        field->type.u.basic.integer.signedness,
@@ -1682,7 +1889,7 @@ int _lttng_field_statedump(struct lttng_session *session,
                                        ? "UTF8"
                                        : "ASCII",
                        field->type.u.basic.integer.base,
-#ifdef __BIG_ENDIAN
+#if __BYTE_ORDER == __BIG_ENDIAN
                        field->type.u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
 #else
                        field->type.u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
@@ -1690,8 +1897,11 @@ int _lttng_field_statedump(struct lttng_session *session,
                        field->name);
                break;
        case atype_enum:
+               ret = print_tabs(session, nesting);
+               if (ret)
+                       return ret;
                ret = lttng_metadata_printf(session,
-                       "               %s _%s;\n",
+                       "%s _%s;\n",
                        field->type.u.basic.enumeration.name,
                        field->name);
                break;
@@ -1701,15 +1911,21 @@ int _lttng_field_statedump(struct lttng_session *session,
 
                elem_type = &field->type.u.array.elem_type;
                if (field->type.u.array.elem_alignment) {
+                       ret = print_tabs(session, nesting);
+                       if (ret)
+                               return ret;
                        ret = lttng_metadata_printf(session,
-                       "               struct { } align(%u) _%s_padding;\n",
+                       "struct { } align(%u) _%s_padding;\n",
                                        field->type.u.array.elem_alignment * CHAR_BIT,
                                        field->name);
                        if (ret)
                                return ret;
                }
+               ret = print_tabs(session, nesting);
+               if (ret)
+                       return ret;
                ret = lttng_metadata_printf(session,
-                       "               integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n",
+                       "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n",
                        elem_type->u.basic.integer.size,
                        elem_type->u.basic.integer.alignment,
                        elem_type->u.basic.integer.signedness,
@@ -1719,7 +1935,7 @@ int _lttng_field_statedump(struct lttng_session *session,
                                        ? "UTF8"
                                        : "ASCII",
                        elem_type->u.basic.integer.base,
-#ifdef __BIG_ENDIAN
+#if __BYTE_ORDER == __BIG_ENDIAN
                        elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
 #else
                        elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
@@ -1734,8 +1950,11 @@ int _lttng_field_statedump(struct lttng_session *session,
 
                elem_type = &field->type.u.sequence.elem_type;
                length_type = &field->type.u.sequence.length_type;
+               ret = print_tabs(session, nesting);
+               if (ret)
+                       return ret;
                ret = lttng_metadata_printf(session,
-                       "               integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n",
+                       "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n",
                        length_type->u.basic.integer.size,
                        (unsigned int) length_type->u.basic.integer.alignment,
                        length_type->u.basic.integer.signedness,
@@ -1745,7 +1964,7 @@ int _lttng_field_statedump(struct lttng_session *session,
                                        ? "UTF8"
                                        : "ASCII"),
                        length_type->u.basic.integer.base,
-#ifdef __BIG_ENDIAN
+#if __BYTE_ORDER == __BIG_ENDIAN
                        length_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
 #else
                        length_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
@@ -1755,15 +1974,21 @@ int _lttng_field_statedump(struct lttng_session *session,
                        return ret;
 
                if (field->type.u.sequence.elem_alignment) {
+                       ret = print_tabs(session, nesting);
+                       if (ret)
+                               return ret;
                        ret = lttng_metadata_printf(session,
-                       "               struct { } align(%u) _%s_padding;\n",
+                       "struct { } align(%u) _%s_padding;\n",
                                        field->type.u.sequence.elem_alignment * CHAR_BIT,
                                        field->name);
                        if (ret)
                                return ret;
                }
+               ret = print_tabs(session, nesting);
+               if (ret)
+                       return ret;
                ret = lttng_metadata_printf(session,
-                       "               integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n",
+                       "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n",
                        elem_type->u.basic.integer.size,
                        (unsigned int) elem_type->u.basic.integer.alignment,
                        elem_type->u.basic.integer.signedness,
@@ -1773,7 +1998,7 @@ int _lttng_field_statedump(struct lttng_session *session,
                                        ? "UTF8"
                                        : "ASCII"),
                        elem_type->u.basic.integer.base,
-#ifdef __BIG_ENDIAN
+#if __BYTE_ORDER == __BIG_ENDIAN
                        elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
 #else
                        elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
@@ -1785,12 +2010,28 @@ int _lttng_field_statedump(struct lttng_session *session,
 
        case atype_string:
                /* Default encoding is UTF8 */
+               ret = print_tabs(session, nesting);
+               if (ret)
+                       return ret;
                ret = lttng_metadata_printf(session,
-                       "               string%s _%s;\n",
+                       "string%s _%s;\n",
                        field->type.u.basic.string.encoding == lttng_encode_ASCII ?
                                " { encoding = ASCII; }" : "",
                        field->name);
                break;
+       case atype_struct:
+               ret = _lttng_struct_statedump(session, field, nesting);
+               break;
+       case atype_array_compound:
+               ret = _lttng_array_compound_statedump(session, field, nesting);
+               break;
+       case atype_sequence_compound:
+               ret = _lttng_sequence_compound_statedump(session, field, nesting);
+               break;
+       case atype_variant:
+               ret = _lttng_variant_statedump(session, field, nesting);
+               break;
+
        default:
                WARN_ON_ONCE(1);
                return -EINVAL;
@@ -1810,7 +2051,7 @@ int _lttng_context_metadata_statedump(struct lttng_session *session,
        for (i = 0; i < ctx->nr_fields; i++) {
                const struct lttng_ctx_field *field = &ctx->fields[i];
 
-               ret = _lttng_field_statedump(session, &field->event_field);
+               ret = _lttng_field_statedump(session, &field->event_field, 2);
                if (ret)
                        return ret;
        }
@@ -1828,7 +2069,7 @@ int _lttng_fields_metadata_statedump(struct lttng_session *session,
        for (i = 0; i < desc->nr_fields; i++) {
                const struct lttng_event_field *field = &desc->fields[i];
 
-               ret = _lttng_field_statedump(session, field);
+               ret = _lttng_field_statedump(session, field, 2);
                if (ret)
                        return ret;
        }
@@ -2111,7 +2352,7 @@ int _lttng_session_metadata_statedump(struct lttng_session *session)
                CTF_SPEC_MAJOR,
                CTF_SPEC_MINOR,
                uuid_s,
-#ifdef __BIG_ENDIAN
+#if __BYTE_ORDER == __BIG_ENDIAN
                "be"
 #else
                "le"
@@ -2272,6 +2513,9 @@ static int __init lttng_events_init(void)
        if (ret)
                return ret;
        ret = wrapper_get_pageblock_flags_mask_init();
+       if (ret)
+               return ret;
+       ret = lttng_probes_init();
        if (ret)
                return ret;
        ret = lttng_context_init();
This page took 0.027723 seconds and 4 git commands to generate.