From 7237592a76cceda97a1c79904fed583e215d3fa9 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Sat, 6 Apr 2013 15:47:13 -0400 Subject: [PATCH] Implement ctf-metadata output plugin Fixes #284 Signed-off-by: Mathieu Desnoyers --- converter/babeltrace.c | 77 ++++++++++++++++++++ formats/ctf-text/ctf-text.c | 89 ++++++++++++++++++++++++ formats/ctf/ctf.c | 4 +- include/babeltrace/babeltrace-internal.h | 3 + include/babeltrace/ctf-ir/metadata.h | 2 + include/babeltrace/types.h | 4 ++ 6 files changed, 178 insertions(+), 1 deletion(-) diff --git a/converter/babeltrace.c b/converter/babeltrace.c index 1fe06adf..a34af175 100644 --- a/converter/babeltrace.c +++ b/converter/babeltrace.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include /* TODO: fix object model for format-agnostic callbacks */ @@ -515,6 +516,67 @@ int bt_context_add_traces_recursive(struct bt_context *ctx, const char *path, return ret; } +static +int trace_pre_handler(struct bt_trace_descriptor *td_write, + struct bt_context *ctx) +{ + struct ctf_text_stream_pos *sout; + struct trace_collection *tc; + int ret, i; + + sout = container_of(td_write, struct ctf_text_stream_pos, + trace_descriptor); + + if (!sout->parent.pre_trace_cb) + return 0; + + tc = ctx->tc; + for (i = 0; i < tc->array->len; i++) { + struct bt_trace_descriptor *td = + g_ptr_array_index(tc->array, i); + + ret = sout->parent.pre_trace_cb(&sout->parent, td); + if (ret) { + fprintf(stderr, "[error] Writing to trace pre handler failed.\n"); + goto end; + } + } + ret = 0; +end: + return ret; +} + +static +int trace_post_handler(struct bt_trace_descriptor *td_write, + struct bt_context *ctx) +{ + struct ctf_text_stream_pos *sout; + struct trace_collection *tc; + int ret, i; + + sout = container_of(td_write, struct ctf_text_stream_pos, + trace_descriptor); + + if (!sout->parent.post_trace_cb) + return 0; + + tc = ctx->tc; + for (i = 0; i < tc->array->len; i++) { + struct bt_trace_descriptor *td = + g_ptr_array_index(tc->array, i); + + ret = sout->parent.post_trace_cb(&sout->parent, td); + if (ret) { + fprintf(stderr, "[error] Writing to trace post handler failed.\n"); + goto end; + } + } + ret = 0; +end: + return ret; +} + +static int convert_trace(struct bt_trace_descriptor *td_write, struct bt_context *ctx) { @@ -527,6 +589,9 @@ int convert_trace(struct bt_trace_descriptor *td_write, sout = container_of(td_write, struct ctf_text_stream_pos, trace_descriptor); + if (!sout->parent.event_cb) + return 0; + begin_pos.type = BT_SEEK_BEGIN; iter = bt_ctf_iter_create(ctx, &begin_pos, NULL); if (!iter) { @@ -660,12 +725,24 @@ int main(int argc, char **argv) if (partial_error) sleep(PARTIAL_ERROR_SLEEP); + ret = trace_pre_handler(td_write, ctx); + if (ret) { + fprintf(stderr, "Error in trace pre handle.\n\n"); + goto error_copy_trace; + } + ret = convert_trace(td_write, ctx); if (ret) { fprintf(stderr, "Error printing trace.\n\n"); goto error_copy_trace; } + ret = trace_post_handler(td_write, ctx); + if (ret) { + fprintf(stderr, "Error in trace post handle.\n\n"); + goto error_copy_trace; + } + fmt_write->close_trace(td_write); bt_context_put(ctx); diff --git a/formats/ctf-text/ctf-text.c b/formats/ctf-text/ctf-text.c index d6bafd31..b44ed844 100644 --- a/formats/ctf-text/ctf-text.c +++ b/formats/ctf-text/ctf-text.c @@ -93,6 +93,13 @@ struct bt_trace_descriptor *ctf_text_open_trace(const char *path, int flags, static int ctf_text_close_trace(struct bt_trace_descriptor *descriptor); +static +struct bt_trace_descriptor *ctf_metadata_open_trace(const char *path, int flags, + void (*packet_seek)(struct bt_stream_pos *pos, size_t index, + int whence), FILE *metadata_fp); +static +int ctf_metadata_close_trace(struct bt_trace_descriptor *descriptor); + static rw_dispatch write_dispatch_table[] = { [ CTF_TYPE_INTEGER ] = ctf_text_integer_write, @@ -111,6 +118,12 @@ struct bt_format ctf_text_format = { .close_trace = ctf_text_close_trace, }; +static +struct bt_format ctf_metadata_format = { + .open_trace = ctf_metadata_open_trace, + .close_trace = ctf_metadata_close_trace, +}; + static GQuark Q_STREAM_PACKET_CONTEXT_TIMESTAMP_BEGIN, Q_STREAM_PACKET_CONTEXT_TIMESTAMP_END, Q_STREAM_PACKET_CONTEXT_EVENTS_DISCARDED, @@ -592,6 +605,78 @@ int ctf_text_close_trace(struct bt_trace_descriptor *td) return 0; } +static +int ctf_metadata_trace_pre_handler(struct bt_stream_pos *ppos, + struct bt_trace_descriptor *td) +{ + struct ctf_text_stream_pos *pos = + container_of(ppos, struct ctf_text_stream_pos, parent); + struct ctf_trace *trace; + + trace = container_of(td, struct ctf_trace, parent); + if (!trace->metadata_string) + return -EINVAL; + if (trace->metadata_packetized) { + fprintf(pos->fp, "/* CTF %u.%u */\n", + BT_CTF_MAJOR, BT_CTF_MINOR); + } + fprintf(pos->fp, "%s", trace->metadata_string); + return 0; +} + +static +struct bt_trace_descriptor *ctf_metadata_open_trace(const char *path, int flags, + void (*packet_seek)(struct bt_stream_pos *pos, size_t index, + int whence), FILE *metadata_fp) +{ + struct ctf_text_stream_pos *pos; + FILE *fp; + + pos = g_new0(struct ctf_text_stream_pos, 1); + + pos->last_real_timestamp = -1ULL; + pos->last_cycles_timestamp = -1ULL; + switch (flags & O_ACCMODE) { + case O_RDWR: + if (!path) + fp = stdout; + else + fp = fopen(path, "w"); + if (!fp) + goto error; + pos->fp = fp; + pos->parent.pre_trace_cb = ctf_metadata_trace_pre_handler; + pos->print_names = 0; + break; + case O_RDONLY: + default: + fprintf(stderr, "[error] Incorrect open flags.\n"); + goto error; + } + + return &pos->trace_descriptor; +error: + g_free(pos); + return NULL; +} + +static +int ctf_metadata_close_trace(struct bt_trace_descriptor *td) +{ + int ret; + struct ctf_text_stream_pos *pos = + container_of(td, struct ctf_text_stream_pos, trace_descriptor); + if (pos->fp != stdout) { + ret = fclose(pos->fp); + if (ret) { + perror("Error on fclose"); + return -1; + } + } + g_free(pos); + return 0; +} + static void __attribute__((constructor)) ctf_text_init(void) { @@ -600,10 +685,14 @@ void __attribute__((constructor)) ctf_text_init(void) ctf_text_format.name = g_quark_from_static_string("text"); ret = bt_register_format(&ctf_text_format); assert(!ret); + ctf_metadata_format.name = g_quark_from_static_string("ctf-metadata"); + ret = bt_register_format(&ctf_metadata_format); + assert(!ret); } static void __attribute__((destructor)) ctf_text_exit(void) { + bt_unregister_format(&ctf_metadata_format); bt_unregister_format(&ctf_text_format); } diff --git a/formats/ctf/ctf.c b/formats/ctf/ctf.c index 137c11ec..c98fcede 100644 --- a/formats/ctf/ctf.c +++ b/formats/ctf/ctf.c @@ -1096,6 +1096,8 @@ int ctf_open_trace_metadata_read(struct ctf_trace *td, fprintf(stderr, "[warning] Empty metadata.\n"); goto end_packet_read; } + td->metadata_string = buf; + td->metadata_packetized = 1; } else { unsigned int major, minor; ssize_t nr_items; @@ -1154,7 +1156,6 @@ end_packet_read: perror("Error on fclose"); } } - free(buf); end_stream: if (metadata_stream->pos.fd >= 0) { closeret = close(metadata_stream->pos.fd); @@ -2026,6 +2027,7 @@ int ctf_close_trace(struct bt_trace_descriptor *tdp) perror("Error closedir"); return ret; } + free(td->metadata_string); g_free(td); return 0; } diff --git a/include/babeltrace/babeltrace-internal.h b/include/babeltrace/babeltrace-internal.h index 1e3631c5..22866bc9 100644 --- a/include/babeltrace/babeltrace-internal.h +++ b/include/babeltrace/babeltrace-internal.h @@ -182,6 +182,9 @@ extern int babeltrace_verbose, babeltrace_debug; */ #define BT_HIDDEN __attribute__((visibility("hidden"))) +#define BT_CTF_MAJOR 1 +#define BT_CTF_MINOR 8 + struct bt_trace_descriptor; struct trace_collection { GPtrArray *array; /* struct bt_trace_descriptor */ diff --git a/include/babeltrace/ctf-ir/metadata.h b/include/babeltrace/ctf-ir/metadata.h index 91df0362..eb37c2df 100644 --- a/include/babeltrace/ctf-ir/metadata.h +++ b/include/babeltrace/ctf-ir/metadata.h @@ -184,6 +184,8 @@ struct ctf_trace { struct definition_scope *definition_scope; GPtrArray *streams; /* Array of struct ctf_stream_declaration pointers */ struct ctf_stream_definition *metadata; + char *metadata_string; + int metadata_packetized; GHashTable *clocks; GHashTable *callsites; struct ctf_clock *single_clock; /* currently supports only one clock */ diff --git a/include/babeltrace/types.h b/include/babeltrace/types.h index 22c6876d..026d28c6 100644 --- a/include/babeltrace/types.h +++ b/include/babeltrace/types.h @@ -115,6 +115,10 @@ struct bt_stream_pos { rw_dispatch *rw_table; /* rw dispatch table */ int (*event_cb)(struct bt_stream_pos *pos, struct ctf_stream_definition *stream); + int (*pre_trace_cb)(struct bt_stream_pos *pos, + struct bt_trace_descriptor *trace); + int (*post_trace_cb)(struct bt_stream_pos *pos, + struct bt_trace_descriptor *trace); }; static inline -- 2.34.1