X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=converter%2Fbabeltrace.c;h=a6c1f548677127f44691c2dd28e68982222a74a2;hp=a7004e1b1e60a21e1531d463f98380afe5dfe7b2;hb=9ff2b8adeaadc0a8fbd8c5aa23f2cbadf2f1a55f;hpb=e669e45e7fdff6b855907cde40524ebf4cc8a3bc diff --git a/converter/babeltrace.c b/converter/babeltrace.c index a7004e1b..a6c1f548 100644 --- a/converter/babeltrace.c +++ b/converter/babeltrace.c @@ -18,12 +18,16 @@ * all copies or substantial portions of the Software. */ -#define _XOPEN_SOURCE 700 +#define _GNU_SOURCE #include #include #include #include #include +#include +/* TODO: fix object model for format-agnostic callbacks */ +#include +#include #include #include #include @@ -33,10 +37,9 @@ #include #include #include -#include -#include #include #include +#include #include /* for clocks */ @@ -71,6 +74,7 @@ enum { OPT_CLOCK_SECONDS, OPT_CLOCK_DATE, OPT_CLOCK_GMT, + OPT_CLOCK_FORCE_CORRELATE, }; static struct poptOption long_options[] = { @@ -89,6 +93,7 @@ static struct poptOption long_options[] = { { "clock-seconds", 0, POPT_ARG_NONE, NULL, OPT_CLOCK_SECONDS, NULL, NULL }, { "clock-date", 0, POPT_ARG_NONE, NULL, OPT_CLOCK_DATE, NULL, NULL }, { "clock-gmt", 0, POPT_ARG_NONE, NULL, OPT_CLOCK_GMT, NULL, NULL }, + { "clock-force-correlate", 0, POPT_ARG_NONE, NULL, OPT_CLOCK_FORCE_CORRELATE, NULL, NULL }, { NULL, 0, 0, NULL, 0, NULL, NULL }, }; @@ -129,6 +134,8 @@ static void usage(FILE *fp) fprintf(fp, " (default is: [hh:mm:ss.ns])\n"); fprintf(fp, " --clock-date Print clock date\n"); fprintf(fp, " --clock-gmt Print clock in GMT time zone (default: local time zone)\n"); + fprintf(fp, " --clock-force-correlate Assume that clocks are inherently correlated\n"); + fprintf(fp, " across traces.\n"); list_formats(fp); fprintf(fp, "\n"); } @@ -274,6 +281,9 @@ static int parse_options(int argc, char **argv) case OPT_CLOCK_GMT: opt_clock_gmt = 1; break; + case OPT_CLOCK_FORCE_CORRELATE: + opt_clock_force_correlate = 1; + break; default: ret = -EINVAL; @@ -296,42 +306,133 @@ end: } +/* + * bt_context_add_traces_recursive: Open a trace recursively + * + * Find each trace present in the subdirectory starting from the given + * path, and add them to the context. The packet_seek parameter can be + * NULL: this specify to use the default format packet_seek. + * + * Return: 0 on success, nonzero on failure. + * Unable to open toplevel: failure. + * Unable to open some subdirectory or file: warn and continue; + */ +int bt_context_add_traces_recursive(struct bt_context *ctx, const char *path, + const char *format_str, + void (*packet_seek)(struct stream_pos *pos, + size_t offset, int whence)) +{ + FTS *tree; + FTSENT *node; + GArray *trace_ids; + char lpath[PATH_MAX]; + char * const paths[2] = { lpath, NULL }; + int ret = -1; + + /* + * Need to copy path, because fts_open can change it. + * It is the pointer array, not the strings, that are constant. + */ + strncpy(lpath, path, PATH_MAX); + lpath[PATH_MAX - 1] = '\0'; + + tree = fts_open(paths, FTS_NOCHDIR | FTS_LOGICAL, 0); + if (tree == NULL) { + fprintf(stderr, "[error] [Context] Cannot traverse \"%s\" for reading.\n", + path); + return -EINVAL; + } + + trace_ids = g_array_new(FALSE, TRUE, sizeof(int)); + + while ((node = fts_read(tree))) { + int dirfd, metafd; + + if (!(node->fts_info & FTS_D)) + continue; + + dirfd = open(node->fts_accpath, 0); + if (dirfd < 0) { + fprintf(stderr, "[error] [Context] Unable to open trace " + "directory file descriptor.\n"); + ret = dirfd; + goto error; + } + metafd = openat(dirfd, "metadata", O_RDONLY); + if (metafd < 0) { + ret = close(dirfd); + if (ret < 0) { + perror("close"); + goto error; + } + } else { + int trace_id; + + ret = close(metafd); + if (ret < 0) { + perror("close"); + goto error; + } + ret = close(dirfd); + if (ret < 0) { + perror("close"); + goto error; + } + + trace_id = bt_context_add_trace(ctx, + node->fts_accpath, format_str, + packet_seek, NULL, NULL); + if (trace_id < 0) { + fprintf(stderr, "[error] [Context] opening trace \"%s\" from %s " + "for reading.\n", node->fts_accpath, path); + ret = trace_id; + goto error; + } + g_array_append_val(trace_ids, trace_id); + } + } + + g_array_free(trace_ids, TRUE); + return ret; + +error: + return ret; +} int convert_trace(struct trace_descriptor *td_write, struct bt_context *ctx) { - struct bt_iter *iter; - struct ctf_stream *stream; - struct ctf_stream_event *event; + struct bt_ctf_iter *iter; struct ctf_text_stream_pos *sout; struct bt_iter_pos begin_pos; + struct bt_ctf_event *ctf_event; int ret; sout = container_of(td_write, struct ctf_text_stream_pos, trace_descriptor); begin_pos.type = BT_SEEK_BEGIN; - iter = bt_iter_create(ctx, &begin_pos, NULL); + iter = bt_ctf_iter_create(ctx, &begin_pos, NULL); if (!iter) { ret = -1; goto error_iter; } - while (bt_iter_read_event(iter, &stream, &event) == 0) { - ret = sout->parent.event_cb(&sout->parent, stream); + while ((ctf_event = bt_ctf_iter_read_event(iter))) { + ret = sout->parent.event_cb(&sout->parent, ctf_event->parent->stream); if (ret) { fprintf(stderr, "[error] Writing event failed.\n"); goto end; } - ret = bt_iter_next(iter); + ret = bt_iter_next(bt_ctf_get_iter(iter)); if (ret < 0) goto end; } ret = 0; end: - bt_iter_destroy(iter); + bt_ctf_iter_destroy(iter); error_iter: return ret; } @@ -387,7 +488,7 @@ int main(int argc, char **argv) ctx = bt_context_create(); ret = bt_context_add_traces_recursive(ctx, opt_input_path, - opt_input_format); + opt_input_format, NULL); if (ret) { fprintf(stderr, "[error] opening trace \"%s\" for reading.\n\n", opt_input_path);