Move ctf-fs source query implementations to their own file
[babeltrace.git] / plugins / ctf / fs-src / fs.c
index 965f5963e6f8f1ed15a0619be9bc8d508400a9dc..3f49e00cba439d621116f1ed7e87392884d099d5 100644 (file)
@@ -25,6 +25,7 @@
  * SOFTWARE.
  */
 
+#include <babeltrace/common-internal.h>
 #include <babeltrace/ctf-ir/packet.h>
 #include <babeltrace/ctf-ir/clock-class.h>
 #include <babeltrace/ctf-ir/stream.h>
 #include <assert.h>
 #include <inttypes.h>
 #include <stdbool.h>
-#include <unistd.h>
 #include "fs.h"
 #include "metadata.h"
 #include "data-stream-file.h"
 #include "file.h"
 #include "../common/metadata/decoder.h"
+#include "query.h"
 
 #define PRINT_ERR_STREAM       ctf_fs->error_fp
 #define PRINT_PREFIX           "ctf-fs"
 #define PRINT_DBG_CHECK                ctf_fs_debug
 #include "../print.h"
-#define METADATA_TEXT_SIG      "/* CTF 1.8"
 
 BT_HIDDEN
 bool ctf_fs_debug;
@@ -271,7 +271,6 @@ int create_one_port_for_trace(struct ctf_fs_trace *ctf_fs_trace,
                struct ctf_fs_ds_file_group *ds_file_group)
 {
        int ret = 0;
-       struct bt_private_port *port = NULL;
        struct ctf_fs_port_data *port_data = NULL;
        GString *port_name = NULL;
        struct ctf_fs_component *ctf_fs = ctf_fs_trace->ctf_fs;
@@ -300,9 +299,9 @@ int create_one_port_for_trace(struct ctf_fs_trace *ctf_fs_trace,
        }
 
        port_data->ds_file_group = ds_file_group;
-       port = bt_private_component_source_add_output_private_port(
-               ctf_fs->priv_comp, port_name->str, port_data);
-       if (!port) {
+       ret = bt_private_component_source_add_output_private_port(
+               ctf_fs->priv_comp, port_name->str, port_data, NULL);
+       if (ret) {
                goto error;
        }
 
@@ -318,7 +317,6 @@ end:
                g_string_free(port_name, TRUE);
        }
 
-       bt_put(port);
        port_data_destroy(port_data);
        return ret;
 }
@@ -930,6 +928,13 @@ struct ctf_fs_trace *ctf_fs_trace_create(struct ctf_fs_component *ctf_fs,
                goto error;
        }
 
+       /*
+        * create_ds_file_groups() created all the streams that this
+        * trace needs. There won't be any more. Therefore it is safe to
+        * make this trace static.
+        */
+       (void) bt_ctf_trace_set_is_static(ctf_fs_trace->metadata->trace);
+
        goto end;
 
 error:
@@ -966,39 +971,31 @@ static
 int add_trace_path(struct ctf_fs_component *ctf_fs, GList **trace_paths,
                const char *path)
 {
-       GString *path_str = g_string_new(NULL);
+       GString *norm_path = NULL;
        int ret = 0;
-       char *rp = NULL;
 
-       if (!path_str) {
+       norm_path = bt_common_normalize_path(path, NULL);
+       if (!norm_path) {
+               PERR("Failed to normalize path `%s`.\n", path);
                ret = -1;
                goto end;
        }
 
-       /*
-        * Find the real path so that we don't have relative components
-        * in the trace name. This also squashes consecutive slashes and
-        * removes any slash at the end.
-        */
-       rp = realpath(path, NULL);
-       if (!rp) {
-               PERR("realpath() failed: %s (%d)\n", strerror(errno), errno);
-               ret = -1;
-               goto end;
-       }
-
-       if (strcmp(rp, "/") == 0) {
+       if (strcmp(norm_path->str, "/") == 0) {
                PERR("Opening a trace in `/` is not supported.\n");
                ret = -1;
                goto end;
        }
 
-       g_string_assign(path_str, rp);
-       *trace_paths = g_list_prepend(*trace_paths, path_str);
+       *trace_paths = g_list_prepend(*trace_paths, norm_path);
        assert(*trace_paths);
+       norm_path = NULL;
 
 end:
-       free(rp);
+       if (norm_path) {
+               g_string_free(norm_path, TRUE);
+       }
+
        return ret;
 }
 
@@ -1019,8 +1016,8 @@ int find_ctf_traces(struct ctf_fs_component *ctf_fs,
 
        if (ret) {
                /*
-                * Do not even recurse: a CTF trace cannot contain
-                * another CTF trace.
+                * Stop recursion: a CTF trace cannot contain another
+                * CTF trace.
                 */
                ret = add_trace_path(ctf_fs, trace_paths, start_path);
                goto end;
@@ -1075,68 +1072,52 @@ end:
 }
 
 static
-GList *create_trace_names(GList *trace_paths) {
+GList *create_trace_names(GList *trace_paths, const char *base_path) {
        GList *trace_names = NULL;
-       size_t chars_to_strip = 0;
-       size_t at = 0;
        GList *node;
-       bool done = false;
+       const char *last_sep;
+       size_t base_dist;
 
        /*
-        * Find the number of characters to strip from the beginning,
-        * that is, the longest prefix until a common slash (also
-        * stripped).
+        * At this point we know that all the trace paths are
+        * normalized, and so is the base path. This means that
+        * they are absolute and they don't end with a separator.
+        * We can simply find the location of the last separator
+        * in the base path, which gives us the name of the actual
+        * directory to look into, and use this location as the
+        * start of each trace name within each trace path.
+        *
+        * For example:
+        *
+        *     Base path: /home/user/my-traces/some-trace
+        *     Trace paths:
+        *       - /home/user/my-traces/some-trace/host1/trace1
+        *       - /home/user/my-traces/some-trace/host1/trace2
+        *       - /home/user/my-traces/some-trace/host2/trace
+        *       - /home/user/my-traces/some-trace/other-trace
+        *
+        * In this case the trace names are:
+        *
+        *       - some-trace/host1/trace1
+        *       - some-trace/host1/trace2
+        *       - some-trace/host2/trace
+        *       - some-trace/other-trace
         */
-       while (true) {
-               gchar common_ch = '\0';
-
-               for (node = trace_paths; node; node = g_list_next(node)) {
-                       GString *gstr = node->data;
-                       gchar this_ch = gstr->str[at];
-
-                       if (this_ch == '\0') {
-                               done = true;
-                               break;
-                       }
-
-                       if (common_ch == '\0') {
-                               /*
-                                * Establish the expected common
-                                * character at this position.
-                                */
-                               common_ch = this_ch;
-                               continue;
-                       }
-
-                       if (this_ch != common_ch) {
-                               done = true;
-                               break;
-                       }
-               }
+       last_sep = strrchr(base_path, G_DIR_SEPARATOR);
 
-               if (done) {
-                       break;
-               }
-
-               if (common_ch == '/') {
-                       /*
-                        * Common character is a slash: safe to include
-                        * this slash in the number of characters to
-                        * strip because the paths are guaranteed not to
-                        * end with slash.
-                        */
-                       chars_to_strip = at + 1;
-               }
+       /* We know there's at least one separator */
+       assert(last_sep);
 
-               at++;
-       }
+       /* Distance to base */
+       base_dist = last_sep - base_path + 1;
 
        /* Create the trace names */
        for (node = trace_paths; node; node = g_list_next(node)) {
                GString *trace_name = g_string_new(NULL);
                GString *trace_path = node->data;
 
-               g_string_assign(trace_name, &trace_path->str[chars_to_strip]);
+               assert(trace_name);
+               g_string_assign(trace_name, &trace_path->str[base_dist]);
                trace_names = g_list_append(trace_names, trace_name);
        }
 
@@ -1149,12 +1130,20 @@ int create_ctf_fs_traces(struct ctf_fs_component *ctf_fs,
 {
        struct ctf_fs_trace *ctf_fs_trace = NULL;
        int ret = 0;
+       GString *norm_path = NULL;
        GList *trace_paths = NULL;
        GList *trace_names = NULL;
        GList *tp_node;
        GList *tn_node;
 
-       ret = find_ctf_traces(ctf_fs, &trace_paths, path_param);
+       norm_path = bt_common_normalize_path(path_param, NULL);
+       if (!norm_path) {
+               PERR("Failed to normalize path: `%s`.\n",
+                       path_param);
+               goto error;
+       }
+
+       ret = find_ctf_traces(ctf_fs, &trace_paths, norm_path->str);
        if (ret) {
                goto error;
        }
@@ -1165,7 +1154,7 @@ int create_ctf_fs_traces(struct ctf_fs_component *ctf_fs,
                goto error;
        }
 
-       trace_names = create_trace_names(trace_paths);
+       trace_names = create_trace_names(trace_paths, norm_path->str);
        if (!trace_names) {
                PERR("Cannot create trace names from trace paths.\n");
                goto error;
@@ -1216,6 +1205,10 @@ end:
                g_list_free(trace_names);
        }
 
+       if (norm_path) {
+               g_string_free(norm_path, TRUE);
+       }
+
        return ret;
 }
 
@@ -1281,7 +1274,7 @@ struct ctf_fs_component *ctf_fs_create(struct bt_private_component *priv_comp,
        }
 
        ctf_fs->error_fp = stderr;
-       ctf_fs->page_size = (size_t) getpagesize();
+       ctf_fs->page_size = bt_common_get_page_size();
        ctf_fs->port_data = g_ptr_array_new_with_free_func(port_data_destroy);
        if (!ctf_fs->port_data) {
                goto error;
@@ -1330,125 +1323,14 @@ BT_HIDDEN
 struct bt_value *ctf_fs_query(struct bt_component_class *comp_class,
                const char *object, struct bt_value *params)
 {
-       struct bt_value *results = NULL;
-       struct bt_value *path_value = NULL;
-       char *metadata_text = NULL;
-       FILE *metadata_fp = NULL;
-       GString *g_metadata_text = NULL;
-
-       if (strcmp(object, "metadata-info") == 0) {
-               int ret;
-               int bo;
-               const char *path;
-               bool is_packetized;
-
-               results = bt_value_map_create();
-               if (!results) {
-                       goto error;
-               }
-
-               if (!bt_value_is_map(params)) {
-                       fprintf(stderr,
-                               "Query parameters is not a map value object\n");
-                       goto error;
-               }
+       struct bt_value *result = NULL;
 
-               path_value = bt_value_map_get(params, "path");
-               ret = bt_value_string_get(path_value, &path);
-               if (ret) {
-                       fprintf(stderr,
-                               "Cannot get `path` string parameter\n");
-                       goto error;
-               }
-
-               assert(path);
-               metadata_fp = ctf_fs_metadata_open_file(path);
-               if (!metadata_fp) {
-                       fprintf(stderr,
-                               "Cannot open trace at path `%s`\n", path);
-                       goto error;
-               }
-
-               is_packetized = ctf_metadata_decoder_is_packetized(metadata_fp,
-                       &bo);
-
-               if (is_packetized) {
-                       ret = ctf_metadata_decoder_packetized_file_stream_to_buf(
-                               metadata_fp, &metadata_text, bo);
-                       if (ret) {
-                               fprintf(stderr,
-                                       "Cannot decode packetized metadata file\n");
-                               goto error;
-                       }
-               } else {
-                       long filesize;
-
-                       fseek(metadata_fp, 0, SEEK_END);
-                       filesize = ftell(metadata_fp);
-                       rewind(metadata_fp);
-                       metadata_text = malloc(filesize + 1);
-                       if (!metadata_text) {
-                               fprintf(stderr,
-                                       "Cannot allocate buffer for metadata text\n");
-                               goto error;
-                       }
-
-                       if (fread(metadata_text, filesize, 1, metadata_fp) !=
-                                       1) {
-                               fprintf(stderr,
-                                       "Cannot read metadata file\n");
-                               goto error;
-                       }
-
-                       metadata_text[filesize] = '\0';
-               }
-
-               g_metadata_text = g_string_new(NULL);
-               if (!g_metadata_text) {
-                       goto error;
-               }
-
-               if (strncmp(metadata_text, METADATA_TEXT_SIG,
-                               sizeof(METADATA_TEXT_SIG) - 1) != 0) {
-                       g_string_assign(g_metadata_text, METADATA_TEXT_SIG);
-                       g_string_append(g_metadata_text, " */\n\n");
-               }
-
-               g_string_append(g_metadata_text, metadata_text);
-
-               ret = bt_value_map_insert_string(results, "text",
-                       g_metadata_text->str);
-               if (ret) {
-                       fprintf(stderr, "Cannot insert metadata text into results\n");
-                       goto error;
-               }
-
-               ret = bt_value_map_insert_bool(results, "is-packetized",
-                       is_packetized);
-               if (ret) {
-                       fprintf(stderr, "Cannot insert is packetized into results\n");
-                       goto error;
-               }
+       if (!strcmp(object, "metadata-info")) {
+               result = metadata_info_query(comp_class, params);
        } else {
                fprintf(stderr, "Unknown query object `%s`\n", object);
-               goto error;
+               goto end;
        }
-
-       goto end;
-
-error:
-       BT_PUT(results);
-
 end:
-       bt_put(path_value);
-       free(metadata_text);
-
-       if (g_metadata_text) {
-               g_string_free(g_metadata_text, TRUE);
-       }
-
-       if (metadata_fp) {
-               fclose(metadata_fp);
-       }
-       return results;
+       return result;
 }
This page took 0.028724 seconds and 4 git commands to generate.