From 91fd6f6a3e6a49647c31cc5a5ada2216dde9b29d Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Mon, 29 May 2017 20:21:46 -0400 Subject: [PATCH] ctf plugins: prepend trace's hostname, if exists, to trace name MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Jérémie Galarneau --- .../ctf/common/metadata/visitor-generate-ir.c | 166 +++++++++++++----- 1 file changed, 123 insertions(+), 43 deletions(-) diff --git a/plugins/ctf/common/metadata/visitor-generate-ir.c b/plugins/ctf/common/metadata/visitor-generate-ir.c index fb0f1df1..aa707548 100644 --- a/plugins/ctf/common/metadata/visitor-generate-ir.c +++ b/plugins/ctf/common/metadata/visitor-generate-ir.c @@ -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; -- 2.34.1