Fix: babeltrace should skip erroneous traces
[babeltrace.git] / converter / babeltrace.c
index a7004e1b1e60a21e1531d463f98380afe5dfe7b2..904c0150868630c47e60820a4e359635b6bf9588 100644 (file)
  * all copies or substantial portions of the Software.
  */
 
-#define _XOPEN_SOURCE 700
+#define _GNU_SOURCE
 #include <config.h>
 #include <babeltrace/babeltrace.h>
 #include <babeltrace/format.h>
 #include <babeltrace/context.h>
 #include <babeltrace/ctf/types.h>
+#include <babeltrace/ctf/events.h>
+/* TODO: fix object model for format-agnostic callbacks */
+#include <babeltrace/ctf/events-internal.h>
+#include <babeltrace/ctf/iterator.h>
 #include <babeltrace/ctf-text/types.h>
 #include <babeltrace/iterator.h>
 #include <popt.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <fcntl.h>
-#include <ftw.h>
-#include <dirent.h>
 #include <unistd.h>
 #include <inttypes.h>
+#include <fts.h>
 
 #include <babeltrace/ctf-ir/metadata.h>        /* 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, "[warning] [Context] opening trace \"%s\" from %s "
+                                       "for reading.\n", node->fts_accpath, path);
+                               /* Allow to skip erroneous traces. */
+                               continue;
+                       }
+                       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);
This page took 0.025131 seconds and 4 git commands to generate.