ctf.fs source: add `get-metadata-info` query info action
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Sat, 11 Feb 2017 22:30:46 +0000 (17:30 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Sun, 28 May 2017 16:57:38 +0000 (12:57 -0400)
The `get-metadata-info` query info action of the ctf.fs source returns,
if successful, the (possibly decoded) metadata string and if the
metadata file is packetized or not. It only needs the `path` parameter
which is the trace directory path (non-recursive).

You can test it with the query-info command:

    babeltrace query-info --source ctf.fs get-metadata-info
                          -p 'path="/path/to/trace"'

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
plugins/ctf/fs/fs.c
plugins/ctf/fs/fs.h
plugins/ctf/fs/metadata.c
plugins/ctf/fs/metadata.h
plugins/ctf/plugin.c

index b7b049569981c27379c80b3e6d37ebd23482215f..b406ee96deee4e494626c9ad4542a4c9383491b5 100644 (file)
@@ -45,6 +45,7 @@
 #define PRINT_ERR_STREAM       ctf_fs->error_fp
 #define PRINT_PREFIX           "ctf-fs"
 #include "print.h"
+#define METADATA_TEXT_SIG      "/* CTF 1.8"
 
 BT_HIDDEN
 bool ctf_fs_debug;
@@ -735,3 +736,129 @@ error:
         ctf_fs_destroy_data(ctf_fs);
        return ret;
 }
+
+BT_HIDDEN
+struct bt_value *ctf_fs_query_info(struct bt_component_class *comp_class,
+               const char *action, 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(action, "get-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 info parameters is not a map value object\n");
+                       goto error;
+               }
+
+               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_is_packetized(metadata_fp, &bo);
+
+               if (is_packetized) {
+                       ret = ctf_metadata_packetized_file_to_buf(NULL,
+                               metadata_fp, (uint8_t **) &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;
+               }
+       } else {
+               fprintf(stderr, "Unknown query info action `%s`\n", action);
+               goto error;
+       }
+
+       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;
+}
index de572cda5ac578824040855181f967f12d4afed9..936cfdd0184e3c9990615e2ec8c479b7ee63648d 100644 (file)
@@ -126,4 +126,8 @@ enum bt_notification_iterator_status ctf_fs_iterator_next(
 struct bt_notification *ctf_fs_iterator_get(
                struct bt_notification_iterator *iterator);
 
+BT_HIDDEN
+struct bt_value *ctf_fs_query_info(struct bt_component_class *comp_class,
+               const char *action, struct bt_value *params);
+
 #endif /* BABELTRACE_PLUGIN_CTF_FS_H */
index 03309dd34fa09d4e17c9caf844609ad320027d9c..e531056c91fadb2769d2ba0483e8cfbb4464f3ba 100644 (file)
@@ -56,6 +56,35 @@ struct packet_header {
        uint8_t  minor;
 } __attribute__((__packed__));
 
+BT_HIDDEN
+FILE *ctf_fs_metadata_open_file(const char *trace_path)
+{
+       GString *metadata_path = g_string_new(trace_path);
+       FILE *fp = NULL;
+
+       if (!metadata_path) {
+               goto error;
+       }
+
+       g_string_append(metadata_path, "/" CTF_FS_METADATA_FILENAME);
+       fp = fopen(metadata_path->str, "rb");
+       if (!fp) {
+               goto error;
+       }
+
+       goto end;
+
+error:
+       if (fp) {
+               fclose(fp);
+               fp = NULL;
+       }
+
+end:
+       g_string_free(metadata_path, TRUE);
+       return fp;
+}
+
 static struct ctf_fs_file *get_file(struct ctf_fs_component *ctf_fs,
                const char *trace_path)
 {
@@ -84,29 +113,31 @@ end:
        return file;
 }
 
-static
-bool is_packetized(struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file)
+BT_HIDDEN
+bool ctf_metadata_is_packetized(FILE *fp, int *byte_order)
 {
        uint32_t magic;
        size_t len;
        int ret = 0;
 
-       len = fread(&magic, sizeof(magic), 1, file->fp);
+       len = fread(&magic, sizeof(magic), 1, fp);
        if (len != 1) {
                goto end;
        }
 
-       if (magic == TSDL_MAGIC) {
-               ret = 1;
-               ctf_fs->metadata->bo = BYTE_ORDER;
-       } else if (magic == GUINT32_SWAP_LE_BE(TSDL_MAGIC)) {
-               ret = 1;
-               ctf_fs->metadata->bo = BYTE_ORDER == BIG_ENDIAN ?
-                       LITTLE_ENDIAN : BIG_ENDIAN;
+       if (byte_order) {
+               if (magic == TSDL_MAGIC) {
+                       ret = 1;
+                       *byte_order = BYTE_ORDER;
+               } else if (magic == GUINT32_SWAP_LE_BE(TSDL_MAGIC)) {
+                       ret = 1;
+                       *byte_order = BYTE_ORDER == BIG_ENDIAN ?
+                               LITTLE_ENDIAN : BIG_ENDIAN;
+               }
        }
 
 end:
-       rewind(file->fp);
+       rewind(fp);
 
        return ret;
 }
@@ -118,7 +149,8 @@ bool is_version_valid(unsigned int major, unsigned int minor)
 }
 
 static
-int decode_packet(struct ctf_fs_component *ctf_fs, FILE *in_fp, FILE *out_fp)
+int decode_packet(struct ctf_fs_component *ctf_fs, FILE *in_fp, FILE *out_fp,
+               int byte_order)
 {
        struct packet_header header;
        size_t readlen, writelen, toread;
@@ -133,7 +165,7 @@ int decode_packet(struct ctf_fs_component *ctf_fs, FILE *in_fp, FILE *out_fp)
                goto error;
        }
 
-       if (ctf_fs->metadata->bo != BYTE_ORDER) {
+       if (byte_order != BYTE_ORDER) {
                header.magic = GUINT32_SWAP_LE_BE(header.magic);
                header.checksum = GUINT32_SWAP_LE_BE(header.checksum);
                header.content_size = GUINT32_SWAP_LE_BE(header.content_size);
@@ -162,12 +194,14 @@ int decode_packet(struct ctf_fs_component *ctf_fs, FILE *in_fp, FILE *out_fp)
        }
 
        /* Set expected trace UUID if not set; otherwise validate it */
-       if (!ctf_fs->metadata->is_uuid_set) {
-               memcpy(ctf_fs->metadata->uuid, header.uuid, sizeof(header.uuid));
-               ctf_fs->metadata->is_uuid_set = true;
-       } else if (bt_uuid_compare(header.uuid, ctf_fs->metadata->uuid)) {
-               PERR("Metadata UUID mismatch between packets of the same file\n");
-               goto error;
+       if (ctf_fs) {
+               if (!ctf_fs->metadata->is_uuid_set) {
+                       memcpy(ctf_fs->metadata->uuid, header.uuid, sizeof(header.uuid));
+                       ctf_fs->metadata->is_uuid_set = true;
+               } else if (bt_uuid_compare(header.uuid, ctf_fs->metadata->uuid)) {
+                       PERR("Metadata UUID mismatch between packets of the same file\n");
+                       goto error;
+               }
        }
 
        if ((header.content_size / CHAR_BIT) < sizeof(header)) {
@@ -218,9 +252,9 @@ end:
        return ret;
 }
 
-static
-int packetized_file_to_buf(struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file,
-               uint8_t **buf)
+BT_HIDDEN
+int ctf_metadata_packetized_file_to_buf(struct ctf_fs_component *ctf_fs,
+               FILE *fp, uint8_t **buf, int byte_order)
 {
        FILE *out_fp;
        size_t size;
@@ -235,11 +269,11 @@ int packetized_file_to_buf(struct ctf_fs_component *ctf_fs, struct ctf_fs_file *
        }
 
        for (;;) {
-               if (feof(file->fp) != 0) {
+               if (feof(fp) != 0) {
                        break;
                }
 
-               tret = decode_packet(ctf_fs, file->fp, out_fp);
+               tret = decode_packet(ctf_fs, fp, out_fp, byte_order);
                if (tret) {
                        PERR("Cannot decode packet #%zu\n", packet_index);
                        goto error;
@@ -296,9 +330,10 @@ void ctf_fs_metadata_set_trace(struct ctf_fs_component *ctf_fs)
                // yydebug = 1;
        }
 
-       if (is_packetized(ctf_fs, file)) {
+       if (ctf_metadata_is_packetized(file->fp, &ctf_fs->metadata->bo)) {
                PDBG("Metadata file \"%s\" is packetized\n", file->path->str);
-               ret = packetized_file_to_buf(ctf_fs, file, &buf);
+               ret = ctf_metadata_packetized_file_to_buf(ctf_fs, file->fp,
+                       &buf, ctf_fs->metadata->bo);
                if (ret) {
                        // log: details
                        goto error;
index 7ed7f069296e554fc4de253e15c6e3a8a3de0621..a8ca942d7a7db7980aee38913997d85fa3215303 100644 (file)
@@ -40,4 +40,14 @@ void ctf_fs_metadata_fini(struct ctf_fs_metadata *metadata);
 BT_HIDDEN
 void ctf_fs_metadata_set_trace(struct ctf_fs_component *ctf_fs);
 
+BT_HIDDEN
+FILE *ctf_fs_metadata_open_file(const char *trace_path);
+
+BT_HIDDEN
+bool ctf_metadata_is_packetized(FILE *fp, int *byte_order);
+
+BT_HIDDEN
+int ctf_metadata_packetized_file_to_buf(struct ctf_fs_component *ctf_fs,
+               FILE *fp, uint8_t **buf, int byte_order);
+
 #endif /* CTF_FS_METADATA_H */
index b79e5073a9dbf3bb797d6e5f14be462a6d004766..f91e1a1bb1518d918c3e0c3967e58e512254becc 100644 (file)
@@ -40,6 +40,7 @@ BT_PLUGIN_LICENSE("MIT");
 BT_PLUGIN_SOURCE_COMPONENT_CLASS(fs, ctf_fs_iterator_get, ctf_fs_iterator_next);
 BT_PLUGIN_SOURCE_COMPONENT_CLASS_DESCRIPTION(fs, CTF_FS_COMPONENT_DESCRIPTION);
 BT_PLUGIN_SOURCE_COMPONENT_CLASS_INIT_METHOD(fs, ctf_fs_init);
+BT_PLUGIN_SOURCE_COMPONENT_CLASS_QUERY_INFO_METHOD(fs, ctf_fs_query_info);
 BT_PLUGIN_SOURCE_COMPONENT_CLASS_DESTROY_METHOD(fs, ctf_fs_destroy);
 BT_PLUGIN_SOURCE_COMPONENT_CLASS_NOTIFICATION_ITERATOR_INIT_METHOD(fs,
        ctf_fs_iterator_init);
This page took 0.032645 seconds and 4 git commands to generate.