fs-sink: add the single-trace option
authorJulien Desfossez <jdesfossez@efficios.com>
Thu, 15 Jun 2017 19:29:34 +0000 (15:29 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 16 Jun 2017 21:12:19 +0000 (17:12 -0400)
This option allows the user to control the output directory of the trace
written (instead of the path being derived from the source trace path
and hostname). This implies that the component only receives one trace.

If the output directory exists and is not empty, an error is returned.

To use it:
--component sink.ctf.fs --path /tmp/out -p single-trace=true

Signed-off-by: Julien Desfossez <jdesfossez@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
plugins/ctf/fs-sink/write.c
plugins/ctf/fs-sink/writer.c
plugins/ctf/fs-sink/writer.h

index dd380f5b667cd062f9c28a53cede8e360398f553..0b0cea42494caa9e28104d49670199f53c851328 100644 (file)
@@ -181,6 +181,48 @@ enum fs_writer_stream_state *insert_new_stream_state(
        return v;
 }
 
+/*
+ * Make sure the output path is valid for a single trace: either it does
+ * not exists or it is empty.
+ *
+ * Return 0 if the path is valid, -1 otherwise.
+ */
+static
+bool valid_single_trace_path(const char *path)
+{
+       int n = 0;
+       struct dirent *d;
+       DIR *dir = opendir(path);
+       int ret;
+
+       /* non-existant directory */
+       if (!dir) {
+               ret = 0;
+               goto end;
+       }
+
+       while ((d = readdir(dir)) != NULL) {
+               if (++n > 2) {
+                       break;
+               }
+       }
+
+       ret = closedir(dir);
+       if (ret) {
+               perror("closedir");
+               goto end;
+       }
+
+       if (n <= 2) {
+               ret = 0;
+       } else {
+               ret = -1;
+       }
+
+end:
+       return ret;
+}
+
 static
 int make_trace_path(struct writer_component *writer_component,
                struct bt_ctf_trace *trace, char *trace_path)
@@ -188,11 +230,14 @@ int make_trace_path(struct writer_component *writer_component,
        int ret;
        const char *trace_name;
 
-       trace_name = bt_ctf_trace_get_name(trace);
-       if (!trace_name) {
-               trace_name = writer_component->trace_name_base->str;
+       if (writer_component->single_trace) {
+               trace_name = "\0";
+       } else {
+               trace_name = bt_ctf_trace_get_name(trace);
+               if (!trace_name) {
+                       trace_name = writer_component->trace_name_base->str;
+               }
        }
-       /* XXX: we might have to skip the first level, TBD. */
 
        /* Sanitize the trace name. */
        if (strlen(trace_name) == 2 && !strcmp(trace_name, "..")) {
@@ -212,22 +257,34 @@ int make_trace_path(struct writer_component *writer_component,
        snprintf(trace_path, PATH_MAX, "%s/%s",
                        writer_component->base_path->str,
                        trace_name);
-       if (g_file_test(trace_path, G_FILE_TEST_EXISTS)) {
-               int i = 0;
-               do {
-                       snprintf(trace_path, PATH_MAX, "%s/%s-%d",
-                                       writer_component->base_path->str,
-                                       trace_name, ++i);
-               } while (g_file_test(trace_path, G_FILE_TEST_EXISTS) && i < INT_MAX);
-               if (i == INT_MAX) {
-                       fprintf(writer_component->err, "[error] Unable to find "
-                                       "a unique trace path\n");
+       /*
+        * Append a suffix if the trace_path exists and we are not in
+        * single-trace mode.
+        */
+       if (writer_component->single_trace) {
+               if (valid_single_trace_path(trace_path) != 0) {
+                       fprintf(writer_component->err,
+                                       "[error] Invalid output directory\n");
                        goto error;
                }
+       } else {
+               if (g_file_test(trace_path, G_FILE_TEST_EXISTS)) {
+                       int i = 0;
+
+                       do {
+                               snprintf(trace_path, PATH_MAX, "%s/%s-%d",
+                                               writer_component->base_path->str,
+                                               trace_name, ++i);
+                       } while (g_file_test(trace_path, G_FILE_TEST_EXISTS) && i < INT_MAX);
+                       if (i == INT_MAX) {
+                               fprintf(writer_component->err, "[error] Unable to find "
+                                               "a unique trace path\n");
+                               goto error;
+                       }
+               }
        }
 
        ret = 0;
-
        goto end;
 
 error:
@@ -249,6 +306,13 @@ struct fs_writer *insert_new_writer(
        struct fs_writer *fs_writer = NULL;
        int nr_stream, i;
 
+       if (writer_component->single_trace && writer_component->nr_traces > 0) {
+               fprintf(writer_component->err, "[error] Trying to process more "
+                               "than one trace but --single-trace mode "
+                               "enabled\n");
+               goto error;
+       }
+
        ret = make_trace_path(writer_component, trace, trace_path);
        if (ret) {
                fprintf(writer_component->err, "[error] %s in %s:%d\n",
@@ -331,6 +395,7 @@ struct fs_writer *insert_new_writer(
                fs_writer->static_listener_id = ret;
        }
 
+       writer_component->nr_traces++;
        g_hash_table_insert(writer_component->trace_map, (gpointer) trace,
                        fs_writer);
 
index 788e3e1440f8d5080c3502ff4e76612873364d5f..36e35d928819ed5ec2b131c04670f421184d6e54 100644 (file)
@@ -281,6 +281,38 @@ end:
        return ret;
 }
 
+static
+enum bt_component_status apply_one_bool(const char *key,
+               struct bt_value *params,
+               bool *option,
+               bool *found)
+{
+       enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+       struct bt_value *value = NULL;
+       enum bt_value_status status;
+       bt_bool bool_val;
+
+       value = bt_value_map_get(params, key);
+       if (!value) {
+               goto end;
+       }
+       status = bt_value_bool_get(value, &bool_val);
+       switch (status) {
+       case BT_VALUE_STATUS_OK:
+               break;
+       default:
+               ret = BT_COMPONENT_STATUS_ERROR;
+               goto end;
+       }
+       *option = (bool) bool_val;
+       if (found) {
+               *found = true;
+       }
+end:
+       bt_put(value);
+       return ret;
+}
+
 BT_HIDDEN
 enum bt_component_status writer_component_init(
        struct bt_private_component *component, struct bt_value *params,
@@ -324,6 +356,13 @@ enum bt_component_status writer_component_init(
                goto error;
        }
 
+       writer_component->single_trace = false;
+       ret = apply_one_bool("single-trace", params,
+                       &writer_component->single_trace, NULL);
+       if (ret != BT_COMPONENT_STATUS_OK) {
+               goto end;
+       }
+
        ret = bt_private_component_set_user_data(component, writer_component);
        if (ret != BT_COMPONENT_STATUS_OK) {
                goto error;
index 81ca1ed9acbf91f0412357ba4e4e60ce24803a1c..33403dc69e3dd99a65876f1e39c5df342d4ec7bc 100644 (file)
@@ -42,6 +42,8 @@ struct writer_component {
        FILE *err;
        struct bt_notification_iterator *input_iterator;
        bool error;
+       bool single_trace;
+       unsigned int nr_traces;
 };
 
 enum fs_writer_stream_state {
This page took 0.028717 seconds and 4 git commands to generate.