ctf plugins: prepend trace's hostname, if exists, to trace name
[babeltrace.git] / plugins / ctf / common / metadata / visitor-generate-ir.c
index cb50a7e767737fdcd622f1012c587cfd413cca8c..aa7075486e04c2098ad8416204200a46bb6ed2da 100644 (file)
@@ -30,6 +30,7 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <assert.h>
@@ -225,6 +226,9 @@ struct ctx {
        /* Offset (ns) to apply to clock classes on creation */
        uint64_t clock_class_offset_ns;
 
+       /* Eventual name suffix of the trace to set */
+       char *trace_name_suffix;
+
        /* Trace attributes */
        enum bt_ctf_byte_order trace_bo;
        uint64_t trace_major;
@@ -571,6 +575,45 @@ int ctx_decl_scope_register_variant(struct ctx_decl_scope *scope,
                name, decl);
 }
 
+/**
+ * Destroys a visitor context.
+ *
+ * @param ctx  Visitor context to destroy
+ */
+static
+void ctx_destroy(struct ctx *ctx)
+{
+       struct ctx_decl_scope *scope;
+       /*
+        * Destroy all scopes, from current one to the root scope.
+        */
+
+       if (!ctx) {
+               goto end;
+       }
+
+       scope = ctx->current_scope;
+
+       while (scope) {
+               struct ctx_decl_scope *parent_scope = scope->parent_scope;
+
+               ctx_decl_scope_destroy(scope);
+               scope = parent_scope;
+       }
+
+       bt_put(ctx->trace);
+
+       if (ctx->stream_classes) {
+               g_hash_table_destroy(ctx->stream_classes);
+       }
+
+       free(ctx->trace_name_suffix);
+       g_free(ctx);
+
+end:
+       return;
+}
+
 /**
  * Creates a new visitor context.
  *
@@ -580,7 +623,7 @@ int ctx_decl_scope_register_variant(struct ctx_decl_scope *scope,
  */
 static
 struct ctx *ctx_create(struct bt_ctf_trace *trace, FILE *efd,
-               uint64_t clock_class_offset_ns)
+               uint64_t clock_class_offset_ns, const char *trace_name_suffix)
 {
        struct ctx *ctx = NULL;
        struct ctx_decl_scope *scope = NULL;
@@ -602,53 +645,27 @@ struct ctx *ctx_create(struct bt_ctf_trace *trace, FILE *efd,
                goto error;
        }
 
+       if (trace_name_suffix) {
+               ctx->trace_name_suffix = strdup(trace_name_suffix);
+               if (!ctx->trace_name_suffix) {
+                       goto error;
+               }
+       }
+
        ctx->trace = trace;
        ctx->efd = efd;
        ctx->current_scope = scope;
+       scope = NULL;
        ctx->trace_bo = BT_CTF_BYTE_ORDER_NATIVE;
        ctx->clock_class_offset_ns = clock_class_offset_ns;
        return ctx;
 
 error:
-       g_free(ctx);
+       ctx_destroy(ctx);
        ctx_decl_scope_destroy(scope);
        return NULL;
 }
 
-/**
- * Destroys a visitor context.
- *
- * @param ctx  Visitor context to destroy
- */
-static
-void ctx_destroy(struct ctx *ctx)
-{
-       struct ctx_decl_scope *scope;
-       /*
-        * Destroy all scopes, from current one to the root scope.
-        */
-
-       if (!ctx) {
-               goto end;
-       }
-
-       scope = ctx->current_scope;
-
-       while (scope) {
-               struct ctx_decl_scope *parent_scope = scope->parent_scope;
-
-               ctx_decl_scope_destroy(scope);
-               scope = parent_scope;
-       }
-
-       bt_put(ctx->trace);
-       g_hash_table_destroy(ctx->stream_classes);
-       g_free(ctx);
-
-end:
-       return;
-}
-
 /**
  * Pushes a new declaration scope on top of a visitor context's
  * declaration scope stack.
@@ -854,6 +871,11 @@ int get_unary_unsigned(struct bt_list_head *head, uint64_t *value)
        int ret = 0;
        struct ctf_node *node;
 
+       if (bt_list_empty(head)) {
+               ret = -1;
+               goto end;
+       }
+
        bt_list_for_each_entry(node, head, siblings) {
                int uexpr_type = node->u.unary_expression.type;
                int uexpr_link = node->u.unary_expression.link;
@@ -1044,7 +1066,7 @@ enum bt_ctf_byte_order get_real_byte_order(struct ctx *ctx,
        enum bt_ctf_byte_order bo = byte_order_from_unary_expr(ctx->efd, uexpr);
 
        if (bo == BT_CTF_BYTE_ORDER_NATIVE) {
-               bo = bt_ctf_trace_get_byte_order(ctx->trace);
+               bo = bt_ctf_trace_get_native_byte_order(ctx->trace);
        }
 
        return bo;
@@ -1172,7 +1194,7 @@ static
 int get_type_specifier_list_name(struct ctx *ctx,
        struct ctf_node *type_specifier_list, GString *str)
 {
-       int ret;
+       int ret = 0;
        struct ctf_node *iter;
        int alias_item_nr = 0;
        struct bt_list_head *head =
@@ -1291,7 +1313,7 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list,
                        nested_decl_copy = bt_ctf_field_type_copy(nested_decl);
                        BT_PUT(nested_decl);
                        if (!nested_decl_copy) {
-                               _PERROR("%s", "cannot copy nested declaration");
+                               _PERROR("%s", "cannot copy nested field type");
                                ret = -EINVAL;
                                goto error;
                        }
@@ -1366,7 +1388,7 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list,
                        BT_PUT(nested_decl);
                        if (!array_decl) {
                                _PERROR("%s",
-                                       "cannot create array declaration");
+                                       "cannot create array field type");
                                ret = -ENOMEM;
                                goto error;
                        }
@@ -1391,7 +1413,7 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list,
                        BT_PUT(nested_decl);
                        if (!seq_decl) {
                                _PERROR("%s",
-                                       "cannot create sequence declaration");
+                                       "cannot create sequence field type");
                                ret = -ENOMEM;
                                goto error;
                        }
@@ -1464,7 +1486,7 @@ int visit_struct_decl_field(struct ctx *ctx,
                        &qfield_name, iter, &field_decl, NULL);
                if (ret) {
                        assert(!field_decl);
-                       _PERROR("%s", "unable to find structure field declaration type");
+                       _PERROR("%s", "cannot visit type declarator");
                        goto error;
                }
 
@@ -1523,7 +1545,7 @@ int visit_variant_decl_field(struct ctx *ctx,
                if (ret) {
                        assert(!field_decl);
                        _PERROR("%s",
-                               "unable to find variant field declaration type");
+                               "cannot visit type declarator");
                        goto error;
                }
 
@@ -1574,7 +1596,7 @@ int visit_typedef(struct ctx *ctx, struct ctf_node *type_specifier_list,
                ret = visit_type_declarator(ctx, type_specifier_list,
                        &qidentifier, iter, &type_decl, NULL);
                if (ret) {
-                       _PERROR("%s", "problem creating type declaration");
+                       _PERROR("%s", "cannot visit type declarator");
                        ret = -EINVAL;
                        goto end;
                }
@@ -1627,7 +1649,7 @@ int visit_typealias(struct ctx *ctx, struct ctf_node *target,
                &qdummy_field_name, node, &type_decl, NULL);
        if (ret) {
                assert(!type_decl);
-               _PERROR("%s", "problem creating type declaration");
+               _PERROR("%s", "cannot visit type declarator");
                goto end;
        }
 
@@ -1795,7 +1817,7 @@ int visit_struct_decl(struct ctx *ctx, const char *name,
                struct_decl_copy = bt_ctf_field_type_copy(*struct_decl);
                if (!struct_decl_copy) {
                        _PERROR("%s",
-                               "cannot create copy of structure declaration");
+                               "cannot create copy of structure field type");
                        ret = -EINVAL;
                        goto error;
                }
@@ -1829,7 +1851,7 @@ int visit_struct_decl(struct ctx *ctx, const char *name,
 
                *struct_decl = bt_ctf_field_type_structure_create();
                if (!*struct_decl) {
-                       _PERROR("%s", "cannot create structure declaration");
+                       _PERROR("%s", "cannot create structure field type");
                        ret = -ENOMEM;
                        goto error;
                }
@@ -1912,7 +1934,7 @@ int visit_variant_decl(struct ctx *ctx, const char *name,
                        untagged_variant_decl);
                if (!variant_decl_copy) {
                        _PERROR("%s",
-                               "cannot create copy of structure declaration");
+                               "cannot create copy of variant field type");
                        ret = -EINVAL;
                        goto error;
                }
@@ -1938,7 +1960,7 @@ int visit_variant_decl(struct ctx *ctx, const char *name,
                untagged_variant_decl = bt_ctf_field_type_variant_create(NULL,
                        NULL);
                if (!untagged_variant_decl) {
-                       _PERROR("%s", "cannot create variant declaration");
+                       _PERROR("%s", "cannot create variant field type");
                        ret = -ENOMEM;
                        goto error;
                }
@@ -2119,7 +2141,7 @@ int visit_enum_decl(struct ctx *ctx, const char *name,
                enum_decl_copy = bt_ctf_field_type_copy(*enum_decl);
                if (!enum_decl_copy) {
                        _PERROR("%s",
-                               "cannot create copy of enumeration declaration");
+                               "cannot create copy of enumeration field type");
                        ret = -EINVAL;
                        goto error;
                }
@@ -2172,7 +2194,7 @@ int visit_enum_decl(struct ctx *ctx, const char *name,
 
                *enum_decl = bt_ctf_field_type_enumeration_create(integer_decl);
                if (!*enum_decl) {
-                       _PERROR("%s", "cannot create enumeration declaration");
+                       _PERROR("%s", "cannot create enumeration field type");
                        ret = -ENOMEM;
                        goto error;
                }
@@ -2232,7 +2254,7 @@ int visit_type_specifier(struct ctx *ctx,
        /* Make a copy of the type declaration */
        decl_copy = bt_ctf_field_type_copy(*decl);
        if (!decl_copy) {
-               _PERROR("%s", "cannot create copy of type declaration");
+               _PERROR("%s", "cannot create field type copy");
                ret = -EINVAL;
                goto error;
        }
@@ -2267,7 +2289,7 @@ int visit_integer_decl(struct ctx *ctx,
        enum bt_ctf_string_encoding encoding = BT_CTF_STRING_ENCODING_NONE;
        enum bt_ctf_integer_base base = BT_CTF_INTEGER_BASE_DECIMAL;
        enum bt_ctf_byte_order byte_order =
-               bt_ctf_trace_get_byte_order(ctx->trace);
+               bt_ctf_trace_get_native_byte_order(ctx->trace);
 
        *integer_decl = NULL;
 
@@ -2565,7 +2587,7 @@ int visit_integer_decl(struct ctx *ctx,
 
        *integer_decl = bt_ctf_field_type_integer_create((unsigned int) size);
        if (!*integer_decl) {
-               _PERROR("%s", "cannot create integer declaration");
+               _PERROR("%s", "cannot create integer field type");
                ret = -ENOMEM;
                goto error;
        }
@@ -2586,7 +2608,7 @@ int visit_integer_decl(struct ctx *ctx,
        }
 
        if (ret) {
-               _PERROR("%s", "cannot configure integer declaration");
+               _PERROR("%s", "cannot configure integer field type");
                ret = -EINVAL;
                goto error;
        }
@@ -2613,7 +2635,7 @@ int visit_floating_point_number_decl(struct ctx *ctx,
        struct ctf_node *expression;
        uint64_t alignment = 1, exp_dig = 0, mant_dig = 0;
        enum bt_ctf_byte_order byte_order =
-               bt_ctf_trace_get_byte_order(ctx->trace);
+               bt_ctf_trace_get_native_byte_order(ctx->trace);
 
        *float_decl = NULL;
 
@@ -2741,7 +2763,7 @@ int visit_floating_point_number_decl(struct ctx *ctx,
        *float_decl = bt_ctf_field_type_floating_point_create();
        if (!*float_decl) {
                _PERROR("%s",
-                       "cannot create floating point number declaration");
+                       "cannot create floating point number field type");
                ret = -ENOMEM;
                goto error;
        }
@@ -2754,7 +2776,7 @@ int visit_floating_point_number_decl(struct ctx *ctx,
        ret |= bt_ctf_field_type_set_alignment(*float_decl, alignment);
        if (ret) {
                _PERROR("%s",
-                       "cannot configure floating point number declaration");
+                       "cannot configure floating point number field type");
                ret = -EINVAL;
                goto error;
        }
@@ -2845,14 +2867,14 @@ int visit_string_decl(struct ctx *ctx,
 
        *string_decl = bt_ctf_field_type_string_create();
        if (!*string_decl) {
-               _PERROR("%s", "cannot create string declaration");
+               _PERROR("%s", "cannot create string field type");
                ret = -ENOMEM;
                goto error;
        }
 
        ret = bt_ctf_field_type_string_set_encoding(*string_decl, encoding);
        if (ret) {
-               _PERROR("%s", "cannot configure string declaration");
+               _PERROR("%s", "cannot configure string field type");
                ret = -EINVAL;
                goto error;
        }
@@ -3036,7 +3058,8 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node,
 
                        ret = get_unary_unsigned(&node->u.ctf_expression.right,
                                (uint64_t *) &id);
-                       if (ret || id < 0) {
+                       /* Only read "id" if get_unary_unsigned() succeeded. */
+                       if (ret || (!ret && id < 0)) {
                                _PERROR("%s", "unexpected unary expression for event declaration's \"id\" attribute");
                                ret = -EINVAL;
                                goto error;
@@ -3060,7 +3083,11 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node,
 
                        ret = get_unary_unsigned(&node->u.ctf_expression.right,
                                (uint64_t *) stream_id);
-                       if (ret || *stream_id < 0) {
+                       /*
+                        * Only read "stream_id" if get_unary_unsigned()
+                        * succeeded.
+                        */
+                       if (ret || (!ret && *stream_id < 0)) {
                                _PERROR("%s", "unexpected unary expression for event declaration's \"stream_id\" attribute");
                                ret = -EINVAL;
                                goto error;
@@ -3107,7 +3134,7 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node,
                                        struct ctf_node, siblings),
                                &decl);
                        if (ret) {
-                               _PERROR("%s", "cannot create event payload declaration");
+                               _PERROR("%s", "cannot create event payload field type");
                                goto error;
                        }
 
@@ -3116,7 +3143,7 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node,
                                event_class, decl);
                        BT_PUT(decl);
                        if (ret) {
-                               _PERROR("%s", "cannot set event's payload declaration");
+                               _PERROR("%s", "cannot set event's payload field type");
                                goto error;
                        }
 
@@ -3501,17 +3528,7 @@ int visit_event_decl(struct ctx *ctx, struct ctf_node *node)
                event_id);
        if (eevent_class) {
                BT_PUT(eevent_class);
-               _PERROR("%s", "duplicate event with ID %" PRId64 " in same stream");
-               ret = -EEXIST;
-               goto error;
-       }
-
-       eevent_class = bt_ctf_stream_class_get_event_class_by_name(stream_class,
-               event_name);
-       if (eevent_class) {
-               BT_PUT(eevent_class);
-               _PERROR("%s",
-                       "duplicate event with name \"%s\" in same stream");
+               _PERROR("duplicate event with ID %" PRId64 " in same stream", event_id);
                ret = -EEXIST;
                goto error;
        }
@@ -3584,7 +3601,8 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
 
                        ret = get_unary_unsigned(&node->u.ctf_expression.right,
                                (uint64_t *) &id);
-                       if (ret || id < 0) {
+                       /* Only read "id" if get_unary_unsigned() succeeded. */
+                       if (ret || (!ret && id < 0)) {
                                _PERROR("%s", "unexpected unary expression for stream declaration's \"id\" attribute");
                                ret = -EINVAL;
                                goto error;
@@ -3602,7 +3620,7 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
                        ret = bt_ctf_stream_class_set_id(stream_class, id);
                        if (ret) {
                                _PERROR("%s",
-                                       "cannot set stream declaration's ID");
+                                       "cannot set stream class's ID");
                                goto error;
                        }
 
@@ -3620,7 +3638,7 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
                                        struct ctf_node, siblings),
                                &decl);
                        if (ret) {
-                               _PERROR("%s", "cannot create event header declaration");
+                               _PERROR("%s", "cannot create event header field type");
                                goto error;
                        }
 
@@ -3630,7 +3648,7 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
                                stream_class, decl);
                        BT_PUT(decl);
                        if (ret) {
-                               _PERROR("%s", "cannot set stream's event header declaration");
+                               _PERROR("%s", "cannot set stream's event header field type");
                                goto error;
                        }
 
@@ -3648,7 +3666,7 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
                                        struct ctf_node, siblings),
                                &decl);
                        if (ret) {
-                               _PERROR("%s", "cannot create stream event context declaration");
+                               _PERROR("%s", "cannot create stream event context field type");
                                goto error;
                        }
 
@@ -3658,7 +3676,7 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
                                stream_class, decl);
                        BT_PUT(decl);
                        if (ret) {
-                               _PERROR("%s", "cannot set stream's event context declaration");
+                               _PERROR("%s", "cannot set stream's event context field type");
                                goto error;
                        }
 
@@ -3676,7 +3694,7 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
                                        struct ctf_node, siblings),
                                &decl);
                        if (ret) {
-                               _PERROR("%s", "cannot create packet context declaration");
+                               _PERROR("%s", "cannot create packet context field type");
                                goto error;
                        }
 
@@ -3686,7 +3704,7 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
                                stream_class, decl);
                        BT_PUT(decl);
                        if (ret) {
-                               _PERROR("%s", "cannot set stream's packet context declaration");
+                               _PERROR("%s", "cannot set stream's packet context field type");
                                goto error;
                        }
 
@@ -3762,7 +3780,7 @@ int visit_stream_decl(struct ctx *ctx, struct ctf_node *node)
                        bt_ctf_trace_get_packet_header_type(ctx->trace);
                if (!packet_header_decl) {
                        _PERROR("%s",
-                               "cannot get trace packet header declaration");
+                               "cannot get trace packet header field type");
                        goto error;
                }
 
@@ -3915,6 +3933,13 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set)
                                goto error;
                        }
 
+                       ret = bt_ctf_trace_set_uuid(ctx->trace, ctx->trace_uuid);
+                       if (ret) {
+                               _PERROR("%s",
+                                       "cannot set trace's UUID");
+                               goto error;
+                       }
+
                        _SET(set, _TRACE_UUID_SET);
                } else if (!strcmp(left, "byte_order")) {
                        /* Native byte order is already known at this stage */
@@ -3939,7 +3964,7 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set)
                                        struct ctf_node, siblings),
                                &packet_header_decl);
                        if (ret) {
-                               _PERROR("%s", "cannot create packet header declaration");
+                               _PERROR("%s", "cannot create packet header field type");
                                goto error;
                        }
 
@@ -3948,7 +3973,7 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set)
                                packet_header_decl);
                        BT_PUT(packet_header_decl);
                        if (ret) {
-                               _PERROR("%s", "cannot set trace declaration's packet header declaration");
+                               _PERROR("%s", "cannot set trace's packet header field type");
                                goto error;
                        }
 
@@ -4615,13 +4640,83 @@ end:
        return ret;
 }
 
+static
+int set_trace_name(struct ctx *ctx)
+{
+       GString *name;
+       int ret = 0;
+       struct bt_value *value = NULL;
+
+       assert(bt_ctf_trace_get_stream_class_count(ctx->trace) == 0);
+       name = g_string_new(NULL);
+       if (!name) {
+               ret = -1;
+               goto end;
+       }
+
+       /*
+        * Check if we have a trace environment string value named `hostname`.
+        * If so, use it as the trace name's prefix.
+        */
+       value = bt_ctf_trace_get_environment_field_value_by_name(ctx->trace,
+               "hostname");
+       if (bt_value_is_string(value)) {
+               const char *hostname;
+
+               ret = bt_value_string_get(value, &hostname);
+               assert(ret == 0);
+               g_string_append(name, hostname);
+
+               if (ctx->trace_name_suffix) {
+                       g_string_append_c(name, G_DIR_SEPARATOR);
+               }
+       }
+
+       if (ctx->trace_name_suffix) {
+               g_string_append(name, ctx->trace_name_suffix);
+       }
+
+       ret = bt_ctf_trace_set_name(ctx->trace, name->str);
+       if (ret) {
+               goto error;
+       }
+
+       goto end;
+
+error:
+       ret = -1;
+
+end:
+       bt_put(value);
+
+       if (name) {
+               g_string_free(name, TRUE);
+       }
+
+       return ret;
+}
+
 static
 int move_ctx_stream_classes_to_trace(struct ctx *ctx)
 {
-       int ret;
+       int ret = 0;
        GHashTableIter iter;
        gpointer key, stream_class;
 
+       if (g_hash_table_size(ctx->stream_classes) > 0 &&
+                       bt_ctf_trace_get_stream_class_count(ctx->trace) == 0) {
+               /*
+                * We're about to add the first stream class to the
+                * trace. This will freeze the trace, and after this
+                * we cannot set the name anymore. At this point,
+                * set the trace name.
+                */
+               ret = set_trace_name(ctx);
+               if (ret) {
+                       goto end;
+               }
+       }
+
        g_hash_table_iter_init(&iter, ctx->stream_classes);
 
        while (g_hash_table_iter_next(&iter, &key, &stream_class)) {
@@ -4643,7 +4738,7 @@ end:
 
 BT_HIDDEN
 struct ctf_visitor_generate_ir *ctf_visitor_generate_ir_create(FILE *efd,
-               uint64_t clock_class_offset_ns)
+               uint64_t clock_class_offset_ns, const char *name)
 {
        int ret;
        struct ctx *ctx = NULL;
@@ -4664,7 +4759,7 @@ struct ctf_visitor_generate_ir *ctf_visitor_generate_ir_create(FILE *efd,
        }
 
        /* Create visitor's context */
-       ctx = ctx_create(trace, efd, clock_class_offset_ns);
+       ctx = ctx_create(trace, efd, clock_class_offset_ns, name);
        if (!ctx) {
                _FPERROR(efd, "%s", "cannot create visitor context");
                goto error;
This page took 0.035063 seconds and 4 git commands to generate.