ctf plugins: prepend trace's hostname, if exists, to trace name
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Tue, 30 May 2017 00:21:46 +0000 (20:21 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 9 Jun 2017 20:58:13 +0000 (16:58 -0400)
This makes the trace names a little more precise.

Note that as of this patch the visitor sets the trace's name just before
adding the first stream class, because after this, the trace is frozen
and we cannot set its name anymore. This is done as lately as possible
to increase our chance of having decoded the metadata's `env` block
(where the hostname is), if any. This can lead to an unnamed trace if
there's no stream classes. But if there's no stream classes, there can't
be any packet or event anyway, so there can't be any notification which
refers to this trace, so no other component should see the fact that
there's no name.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
plugins/ctf/common/metadata/visitor-generate-ir.c

index fb0f1df11045c0ccce1c04e97608286a65dc89af..aa7075486e04c2098ad8416204200a46bb6ed2da 100644 (file)
@@ -226,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;
@@ -572,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.
  *
@@ -581,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;
@@ -603,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.
@@ -4624,6 +4640,62 @@ 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)
 {
@@ -4631,6 +4703,20 @@ int move_ctx_stream_classes_to_trace(struct ctx *ctx)
        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)) {
@@ -4664,12 +4750,6 @@ struct ctf_visitor_generate_ir *ctf_visitor_generate_ir_create(FILE *efd,
                goto error;
        }
 
-       ret = bt_ctf_trace_set_name(trace, name);
-       if (ret) {
-               _FPERROR(efd, "cannot set trace's name to `%s`", name);
-               goto error;
-       }
-
        /* Set packet header to NULL to override the default one */
        ret = bt_ctf_trace_set_packet_header_type(trace, NULL);
        if (ret) {
@@ -4679,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.0292 seconds and 4 git commands to generate.