From: Jérémie Galarneau Date: Wed, 31 Aug 2016 19:16:06 +0000 (-0400) Subject: Move remaining protorectoral files to ctf fs plugin X-Git-Tag: v2.0.0-pre1~774 X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=56a1ccedd4a58b6c87d1bbd94e22094ad5ac1a98 Move remaining protorectoral files to ctf fs plugin Signed-off-by: Jérémie Galarneau --- diff --git a/converter/babeltrace.c b/converter/babeltrace.c index 035c4a25..cd7bd7c4 100644 --- a/converter/babeltrace.c +++ b/converter/babeltrace.c @@ -40,10 +40,12 @@ static char *opt_plugin_path; +static char *opt_input_path; enum { OPT_NONE = 0, OPT_PLUGIN_PATH, + OPT_INPUT_PATH, OPT_VERBOSE, OPT_DEBUG, OPT_HELP, @@ -60,6 +62,7 @@ enum { static struct poptOption long_options[] = { /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */ { "plugin-path", 0, POPT_ARG_STRING, NULL, OPT_PLUGIN_PATH, NULL, NULL }, + { "input-path", 0, POPT_ARG_STRING, NULL, OPT_INPUT_PATH, NULL, NULL }, { "verbose", 'v', POPT_ARG_NONE, NULL, OPT_VERBOSE, NULL, NULL }, { "debug", 'd', POPT_ARG_NONE, NULL, OPT_DEBUG, NULL, NULL }, { NULL, 0, 0, NULL, 0, NULL, NULL }, @@ -95,7 +98,7 @@ static int parse_options(int argc, char **argv) if (!opt_plugin_path) { ret = -EINVAL; goto end; - } ; + } break; case OPT_VERBOSE: babeltrace_verbose = 1; @@ -103,6 +106,13 @@ static int parse_options(int argc, char **argv) case OPT_DEBUG: babeltrace_debug = 1; break; + case OPT_INPUT_PATH: + opt_input_path = (char *) poptGetOptArg(pc); + if (!opt_input_path) { + ret = -EINVAL; + goto end; + } + break; default: ret = -EINVAL; goto end; @@ -133,7 +143,7 @@ const char *component_type_str(enum bt_component_type type) } static -void print_detected_component_classes(struct bt_component_factory *factory) +void print_found_component_classes(struct bt_component_factory *factory) { int count, i; @@ -183,18 +193,12 @@ void print_detected_component_classes(struct bt_component_factory *factory) } } -static -void test_sink_notifications(struct bt_component *sink) -{ - return; -} - int main(int argc, char **argv) { int ret; + enum bt_value_status value_status; struct bt_component_factory *component_factory = NULL; - struct bt_component_class *source_class = NULL; - struct bt_component_class *sink_class = NULL; + struct bt_component_class *source_class = NULL, *sink_class = NULL; struct bt_component *source = NULL, *sink = NULL; struct bt_value *source_params = NULL, *sink_params = NULL; @@ -206,6 +210,20 @@ int main(int argc, char **argv) exit(EXIT_SUCCESS); } + source_params = bt_value_map_create(); + if (!source_params) { + fprintf(stderr, "Failed to create source parameters map, aborting...\n"); + ret = -1; + goto end; + } + + value_status = bt_value_map_insert_string(source_params, "path", + opt_input_path); + if (value_status != BT_VALUE_STATUS_OK) { + ret = -1; + goto end; + } + printf_verbose("Verbose mode active.\n"); printf_debug("Debug mode active.\n"); @@ -229,25 +247,39 @@ int main(int argc, char **argv) goto end; } - print_detected_component_classes(component_factory); + print_found_component_classes(component_factory); + + source_class = bt_component_factory_get_component_class( + component_factory, "ctf", BT_COMPONENT_TYPE_SOURCE, + "fs"); + if (!source_class) { + fprintf(stderr, "Could not find ctf-fs output component class. Aborting...\n"); + ret = -1; + goto end; + } sink_class = bt_component_factory_get_component_class(component_factory, - NULL, BT_COMPONENT_TYPE_SINK, "text"); + "text", BT_COMPONENT_TYPE_SINK, "text"); if (!sink_class) { fprintf(stderr, "Could not find text output component class. Aborting...\n"); ret = -1; goto end; } + source = bt_component_create(source_class, "ctf-fs", source_params); + if (!source) { + fprintf(stderr, "Failed to instantiate source component. Aborting...\n"); + ret = -1; + goto end; + } + sink = bt_component_create(sink_class, "bt_text_output", sink_params); if (!sink) { - fprintf(stderr, "Failed to instanciate text output. Aborting...\n"); + fprintf(stderr, "Failed to instantiate output component. Aborting...\n"); ret = -1; goto end; } - test_sink_notifications(sink); - /* teardown and exit */ end: BT_PUT(component_factory); diff --git a/ctf-reader-proto/ctf-fs-data-stream.c b/ctf-reader-proto/ctf-fs-data-stream.c deleted file mode 100644 index c696927a..00000000 --- a/ctf-reader-proto/ctf-fs-data-stream.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright 2016 - Philippe Proulx - * Copyright 2010-2011 - EfficiOS Inc. and Linux Foundation - * - * Some functions are based on older functions written by Mathieu Desnoyers. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define PRINT_ERR_STREAM ctf_fs->error_fp -#define PRINT_PREFIX "ctf-fs-data-stream" -#include "print.h" - -#include "ctf-fs.h" -#include "ctf-fs-file.h" -#include "ctf-fs-metadata.h" -#include "ctf-notif-iter/ctf-notif-iter.h" - -static void ctf_fs_stream_destroy(struct ctf_fs_stream *stream) -{ - if (stream->file) { - ctf_fs_file_destroy(stream->file); - } - - if (stream->stream) { - BT_PUT(stream->stream); - } - - if (stream->notif_iter) { - bt_ctf_notif_iter_destroy(stream->notif_iter); - } - - g_free(stream); -} - -static size_t remaining_mmap_bytes(struct ctf_fs_stream *stream) -{ - return stream->mmap_offset + stream->mmap_len - - stream->request_offset; -} - -static int stream_munmap(struct ctf_fs_stream *stream) -{ - struct ctf_fs *ctf_fs = stream->file->ctf_fs; - - if (munmap(stream->mmap_addr, stream->mmap_len)) { - PERR("Cannot memory-unmap address %p (size %zu) of file \"%s\" (%p): %s\n", - stream->mmap_addr, stream->mmap_len, - stream->file->path->str, stream->file->fp, - strerror(errno)); - return -1; - } - - return 0; -} - -static int mmap_next(struct ctf_fs_stream *stream) -{ - struct ctf_fs *ctf_fs = stream->file->ctf_fs; - int ret = 0; - - /* Unmap old region */ - if (stream->mmap_addr) { - if (stream_munmap(stream)) { - goto error; - } - - stream->mmap_offset += stream->mmap_len; - stream->request_offset = stream->mmap_offset; - } - - /* Map new region */ - stream->mmap_addr = mmap((void *) 0, stream->mmap_len, - PROT_READ, MAP_PRIVATE, fileno(stream->file->fp), - stream->mmap_offset); - if (stream->mmap_addr == MAP_FAILED) { - PERR("Cannot memory-map address (size %zu) of file \"%s\" (%p) at offset %zu: %s\n", - stream->mmap_len, stream->file->path->str, - stream->file->fp, stream->mmap_offset, - strerror(errno)); - goto error; - } - - goto end; - -error: - stream_munmap(stream); - ret = -1; - -end: - return ret; -} - -static enum bt_ctf_notif_iter_medium_status medop_request_bytes( - size_t request_sz, uint8_t **buffer_addr, - size_t *buffer_sz, void *data) -{ - enum bt_ctf_notif_iter_medium_status status = - BT_CTF_NOTIF_ITER_MEDIUM_STATUS_OK; - struct ctf_fs_stream *stream = data; - struct ctf_fs *ctf_fs = stream->file->ctf_fs; - - if (request_sz == 0) { - goto end; - } - - /* Check if we need an initial memory map */ - if (!stream->mmap_addr) { - if (mmap_next(stream)) { - PERR("Cannot memory-map initial region of file \"%s\" (%p)\n", - stream->file->path->str, stream->file->fp); - goto error; - } - } - - /* Check if we have at least one memory-mapped byte left */ - if (remaining_mmap_bytes(stream) == 0) { - /* Are we at the end of the file? */ - if (stream->request_offset == stream->file->size) { - PDBG("Reached end of file \"%s\" (%p)\n", - stream->file->path->str, stream->file->fp); - status = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_EOF; - goto end; - } - - if (mmap_next(stream)) { - PERR("Cannot memory-map next region of file \"%s\" (%p)\n", - stream->file->path->str, stream->file->fp); - goto error; - } - } - - *buffer_sz = MIN(remaining_mmap_bytes(stream), request_sz); - *buffer_addr = ((uint8_t *) stream->mmap_addr) + - stream->request_offset - stream->mmap_offset; - stream->request_offset += *buffer_sz; - goto end; - -error: - status = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_ERROR; - -end: - return status; -} - -static struct bt_ctf_stream *medop_get_stream( - struct bt_ctf_stream_class *stream_class, void *data) -{ - struct ctf_fs_stream *fs_stream = data; - struct ctf_fs *ctf_fs = fs_stream->file->ctf_fs; - - if (!fs_stream->stream) { - int64_t id = bt_ctf_stream_class_get_id(stream_class); - - PDBG("Creating stream out of stream class %" PRId64 "\n", id); - fs_stream->stream = bt_ctf_stream_create(stream_class, - fs_stream->file->path->str); - if (!fs_stream->stream) { - PERR("Cannot create stream (stream class %" PRId64 ")\n", - id); - } - } - - return fs_stream->stream; -} - -static struct bt_ctf_notif_iter_medium_ops medops = { - .request_bytes = medop_request_bytes, - .get_stream = medop_get_stream, -}; - -static struct ctf_fs_stream *ctf_fs_stream_create(struct ctf_fs *ctf_fs, - struct ctf_fs_file *file) -{ - struct ctf_fs_stream *stream = g_new0(struct ctf_fs_stream, 1); - - if (!stream) { - goto error; - } - - stream->file = file; - stream->notif_iter = bt_ctf_notif_iter_create(ctf_fs->metadata.trace, - 12, medops, stream, ctf_fs->error_fp); - if (!stream->notif_iter) { - goto error; - } - stream->mmap_len = ctf_fs->page_size; - - goto end; - -error: - /* Do not touch borrowed file */ - stream->file = NULL; - ctf_fs_stream_destroy(stream); - stream = NULL; - -end: - return stream; -} - -int ctf_fs_data_stream_open_streams(struct ctf_fs *ctf_fs) -{ - int ret = 0; - GError *error = NULL; - GDir *dir = g_dir_open(ctf_fs->trace_path->str, 0, &error); - const char *name; - - if (!dir) { - PERR("Cannot open directory \"%s\": %s (code %d)\n", - ctf_fs->trace_path->str, error->message, - error->code); - goto error; - } - - while ((name = g_dir_read_name(dir))) { - struct ctf_fs_file *file = NULL; - struct ctf_fs_stream *stream = NULL; - - if (strcmp(name, CTF_FS_METADATA_FILENAME) == 0) { - /* Ignore the metadata stream */ - PDBG("Ignoring metadata file \"%s\"\n", - name); - continue; - } - - if (name[0] == '.') { - PDBG("Ignoring hidden file \"%s\"\n", - name); - continue; - } - - /* Create the file */ - file = ctf_fs_file_create(ctf_fs); - if (!file) { - PERR("Cannot create stream file object\n"); - goto error; - } - - /* Create full path string */ - g_string_append(file->path, ctf_fs->trace_path->str); - g_string_append(file->path, "/"); - g_string_append(file->path, name); - - if (!g_file_test(file->path->str, G_FILE_TEST_IS_REGULAR)) { - PDBG("Ignoring non-regular file \"%s\"\n", name); - ctf_fs_file_destroy(file); - continue; - } - - /* Open the file */ - if (ctf_fs_file_open(ctf_fs, file, "rb")) { - ctf_fs_file_destroy(file); - goto error; - } - - /* Create a private stream */ - stream = ctf_fs_stream_create(ctf_fs, file); - if (!stream) { - ctf_fs_file_destroy(file); - goto error; - } - - /* Append file to the array of files */ - g_ptr_array_add(ctf_fs->data_stream.streams, stream); - } - - goto end; - -error: - ret = -1; - -end: - if (dir) { - g_dir_close(dir); - dir = NULL; - } - - if (error) { - g_error_free(error); - } - - return ret; -} - -int ctf_fs_data_stream_init(struct ctf_fs *ctf_fs, - struct ctf_fs_data_stream *data_stream) -{ - int ret = 0; - - data_stream->streams = g_ptr_array_new_with_free_func( - (GDestroyNotify) ctf_fs_stream_destroy); - if (!data_stream->streams) { - PERR("Cannot allocate array of streams\n"); - goto error; - } - - goto end; - -error: - ret = -1; - -end: - return ret; -} - -void ctf_fs_data_stream_deinit(struct ctf_fs_data_stream *data_stream) -{ - g_ptr_array_free(data_stream->streams, TRUE); -} - -int ctf_fs_data_stream_get_next_notification( - struct ctf_fs *ctf_fs, - struct bt_ctf_notif_iter_notif **notification) -{ - int ret = 0; - struct ctf_fs_stream *stream = g_ptr_array_index( - ctf_fs->data_stream.streams, 0); - enum bt_ctf_notif_iter_status status; - - status = bt_ctf_notif_iter_get_next_notification( - stream->notif_iter, notification); - if (status != BT_CTF_NOTIF_ITER_STATUS_OK && - status != BT_CTF_NOTIF_ITER_STATUS_EOF) { - goto error; - } - if (status == BT_CTF_NOTIF_ITER_STATUS_EOF) { - *notification = NULL; - } - - goto end; - -error: - ret = -1; - -end: - return ret; -} diff --git a/ctf-reader-proto/ctf-fs-data-stream.h b/ctf-reader-proto/ctf-fs-data-stream.h deleted file mode 100644 index d8f67466..00000000 --- a/ctf-reader-proto/ctf-fs-data-stream.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef CTF_FS_DATA_STREAM_H -#define CTF_FS_DATA_STREAM_H - -/* - * Copyright 2016 - Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include - -#include "ctf-notif-iter/ctf-notif-iter.h" - -struct ctf_fs_stream { - struct ctf_fs_file *file; - struct bt_ctf_stream *stream; - struct bt_ctf_notif_iter *notif_iter; - void *mmap_addr; - size_t mmap_len; - off_t mmap_offset; - off_t request_offset; -}; - -struct ctf_fs_data_stream { - GPtrArray *streams; -}; - -BT_HIDDEN -int ctf_fs_data_stream_init(struct ctf_fs *ctf_fs, - struct ctf_fs_data_stream *data_stream); - -BT_HIDDEN -void ctf_fs_data_stream_deinit(struct ctf_fs_data_stream *data_stream); - -BT_HIDDEN -int ctf_fs_data_stream_open_streams(struct ctf_fs *ctf_fs); - -BT_HIDDEN -int ctf_fs_data_stream_get_next_notification( - struct ctf_fs *ctf_fs, - struct bt_ctf_notif_iter_notif **notification); - -#endif /* CTF_FS_DATA_STREAM_H */ diff --git a/ctf-reader-proto/ctf-fs-file.c b/ctf-reader-proto/ctf-fs-file.c deleted file mode 100644 index 45819ef7..00000000 --- a/ctf-reader-proto/ctf-fs-file.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2016 - Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include - -#define PRINT_ERR_STREAM ctf_fs->error_fp -#define PRINT_PREFIX "ctf-fs-file" -#include "print.h" - -#include "ctf-fs-file.h" - -void ctf_fs_file_destroy(struct ctf_fs_file *file) -{ - struct ctf_fs *ctf_fs = file->ctf_fs; - - if (!file) { - return; - } - - if (file->fp) { - PDBG("Closing file \"%s\" (%p)\n", file->path->str, file->fp); - - if (fclose(file->fp)) { - PERR("Cannot close file \"%s\": %s\n", file->path->str, - strerror(errno)); - } - } - - if (file->path) { - g_string_free(file->path, TRUE); - } - - g_free(file); -} - -struct ctf_fs_file *ctf_fs_file_create(struct ctf_fs *ctf_fs) -{ - struct ctf_fs_file *file = g_new0(struct ctf_fs_file, 1); - - if (!file) { - goto error; - } - - file->ctf_fs = ctf_fs; - file->path = g_string_new(NULL); - if (!file->path) { - goto error; - } - - goto end; - -error: - ctf_fs_file_destroy(file); - file = NULL; - -end: - return file; -} - -int ctf_fs_file_open(struct ctf_fs *ctf_fs, struct ctf_fs_file *file, - const char *mode) -{ - int ret = 0; - struct stat stat; - - PDBG("Opening file \"%s\" with mode \"%s\"\n", file->path->str, mode); - file->fp = fopen(file->path->str, mode); - if (!file->fp) { - PERR("Cannot open file \"%s\" with mode \"%s\": %s", - file->path->str, mode, strerror(errno)); - goto error; - } - - PDBG("Opened file: %p\n", file->fp); - - if (fstat(fileno(file->fp), &stat)) { - PERR("Cannot get file informations: %s\n", strerror(errno)); - goto error; - } - - file->size = stat.st_size; - PDBG(" File is %zu bytes\n", file->size); - goto end; - -error: - ret = -1; - - if (file->fp) { - if (fclose(file->fp)) { - PERR("Cannot close file \"%s\": %s\n", file->path->str, - strerror(errno)); - } - } - -end: - return ret; -} diff --git a/ctf-reader-proto/ctf-fs-file.h b/ctf-reader-proto/ctf-fs-file.h deleted file mode 100644 index 5da082eb..00000000 --- a/ctf-reader-proto/ctf-fs-file.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef CTF_FS_FILE_H -#define CTF_FS_FILE_H - -/* - * Copyright 2016 - Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include - -#include "ctf-fs.h" - -struct ctf_fs_file { - struct ctf_fs *ctf_fs; - GString *path; - FILE *fp; - off_t size; -}; - -BT_HIDDEN -void ctf_fs_file_destroy(struct ctf_fs_file *file); - -BT_HIDDEN -struct ctf_fs_file *ctf_fs_file_create(struct ctf_fs *ctf_fs); - -BT_HIDDEN -int ctf_fs_file_open(struct ctf_fs *ctf_fs, struct ctf_fs_file *file, - const char *mode); - -#endif /* CTF_FS_FILE_H */ diff --git a/ctf-reader-proto/ctf-fs-metadata.c b/ctf-reader-proto/ctf-fs-metadata.c deleted file mode 100644 index bfe24728..00000000 --- a/ctf-reader-proto/ctf-fs-metadata.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright 2016 - Philippe Proulx - * Copyright 2010-2011 - EfficiOS Inc. and Linux Foundation - * - * Some functions are based on older functions written by Mathieu Desnoyers. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define PRINT_ERR_STREAM ctf_fs->error_fp -#define PRINT_PREFIX "ctf-fs-metadata" -#include "print.h" - -#include "ctf-fs.h" -#include "ctf-fs-file.h" -#include "metadata-parsing/ctf-ast.h" -#include "metadata-parsing/ctf-scanner.h" - -#define TSDL_MAGIC 0x75d11d57 - -struct packet_header { - uint32_t magic; - uint8_t uuid[16]; - uint32_t checksum; - uint32_t content_size; - uint32_t packet_size; - uint8_t compression_scheme; - uint8_t encryption_scheme; - uint8_t checksum_scheme; - uint8_t major; - uint8_t minor; -} __attribute__((__packed__)); - -static struct ctf_fs_file *get_file(struct ctf_fs *ctf_fs, - const char *trace_path) -{ - struct ctf_fs_file *file = ctf_fs_file_create(ctf_fs); - - if (!file) { - goto error; - } - - g_string_append(file->path, trace_path); - g_string_append(file->path, "/" CTF_FS_METADATA_FILENAME); - - if (ctf_fs_file_open(ctf_fs, file, "rb")) { - goto error; - } - - goto end; - -error: - if (file) { - ctf_fs_file_destroy(file); - file = NULL; - } - -end: - return file; -} - -static -bool is_packetized(struct ctf_fs *ctf_fs, struct ctf_fs_file *file) -{ - uint32_t magic; - size_t len; - int ret = 0; - - len = fread(&magic, sizeof(magic), 1, file->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; - } - -end: - rewind(file->fp); - - return ret; -} - -static -bool is_version_valid(unsigned int major, unsigned int minor) -{ - return major == 1 && minor == 8; -} - -static -int decode_packet(struct ctf_fs *ctf_fs, FILE *in_fp, FILE *out_fp) -{ - struct packet_header header; - size_t readlen, writelen, toread; - uint8_t buf[512 + 1]; /* + 1 for debug-mode \0 */ - int ret = 0; - - readlen = fread(&header, sizeof(header), 1, in_fp); - if (feof(in_fp) != 0) { - goto end; - } - if (readlen < 1) { - goto error; - } - - if (ctf_fs->metadata.bo != 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); - header.packet_size = GUINT32_SWAP_LE_BE(header.packet_size); - } - - if (header.compression_scheme) { - PERR("Metadata packet compression not supported yet\n"); - goto error; - } - - if (header.encryption_scheme) { - PERR("Metadata packet encryption not supported yet\n"); - goto error; - } - - if (header.checksum || header.checksum_scheme) { - PERR("Metadata packet checksum verification not supported yet\n"); - goto error; - } - - if (!is_version_valid(header.major, header.minor)) { - PERR("Invalid metadata version: %u.%u\n", header.major, - header.minor); - goto error; - } - - /* 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 ((header.content_size / CHAR_BIT) < sizeof(header)) { - PERR("Bad metadata packet content size: %u\n", - header.content_size); - goto error; - } - - toread = header.content_size / CHAR_BIT - sizeof(header); - - for (;;) { - readlen = fread(buf, sizeof(uint8_t), - MIN(sizeof(buf) - 1, toread), in_fp); - if (ferror(in_fp)) { - PERR("Cannot read metadata packet buffer (at position %ld)\n", - ftell(in_fp)); - goto error; - } - - writelen = fwrite(buf, sizeof(uint8_t), readlen, out_fp); - if (writelen < readlen || ferror(out_fp)) { - PERR("Cannot write decoded metadata text to buffer\n"); - goto error; - } - - toread -= readlen; - if (toread == 0) { - int fseek_ret; - - /* Read leftover padding */ - toread = (header.packet_size - header.content_size) / - CHAR_BIT; - fseek_ret = fseek(in_fp, toread, SEEK_CUR); - if (fseek_ret < 0) { - PWARN("Missing padding at the end of the metadata file\n"); - } - - break; - } - } - - goto end; - -error: - ret = -1; - -end: - return ret; -} - -static -int packetized_file_to_buf(struct ctf_fs *ctf_fs, struct ctf_fs_file *file, - uint8_t **buf) -{ - FILE *out_fp; - size_t size; - int ret = 0; - int tret; - size_t packet_index = 0; - - out_fp = babeltrace_open_memstream((char **) buf, &size); - if (out_fp == NULL) { - PERR("Cannot open memory stream: %s\n", strerror(errno)); - goto error; - } - - for (;;) { - if (feof(file->fp) != 0) { - break; - } - - tret = decode_packet(ctf_fs, file->fp, out_fp); - if (tret) { - PERR("Cannot decode packet #%zu\n", packet_index); - goto error; - } - - packet_index++; - } - - /* Make sure the whole string ends with a null character */ - tret = fputc('\0', out_fp); - if (tret == EOF) { - PERR("Cannot append '\\0' to the decoded metadata buffer\n"); - goto error; - } - - /* Close stream, which also flushes the buffer */ - ret = babeltrace_close_memstream((char **) buf, &size, out_fp); - if (ret < 0) { - PERR("Cannot close memory stream: %s\n", strerror(errno)); - goto error; - } - - goto end; - -error: - ret = -1; - - if (out_fp) { - babeltrace_close_memstream((char **) buf, &size, out_fp); - } - - if (*buf) { - free(*buf); - } - -end: - return ret; -} - -void ctf_fs_metadata_set_trace(struct ctf_fs *ctf_fs) -{ - int ret = 0; - struct ctf_fs_file *file = get_file(ctf_fs, ctf_fs->trace_path->str); - struct ctf_scanner *scanner = NULL; - uint8_t *buf = NULL; - char *cbuf; - - if (!file) { - PERR("Cannot create metadata file object\n"); - goto error; - } - - if (babeltrace_debug) { - // yydebug = 1; - } - - if (is_packetized(ctf_fs, file)) { - PDBG("Metadata file \"%s\" is packetized\n", file->path->str); - ret = packetized_file_to_buf(ctf_fs, file, &buf); - if (ret) { - // log: details - goto error; - } - - cbuf = (char *) buf; - ctf_fs->metadata.text = (char *) cbuf; - - /* Convert the real file pointer to a memory file pointer */ - ret = fclose(file->fp); - file->fp = NULL; - if (ret) { - PERR("Cannot close file \"%s\": %s\n", file->path->str, - strerror(errno)); - goto error; - } - - file->fp = babeltrace_fmemopen(cbuf, strlen(cbuf), "rb"); - if (!file->fp) { - PERR("Cannot memory-open metadata buffer: %s\n", - strerror(errno)); - goto error; - } - } else { - unsigned int major, minor; - ssize_t nr_items; - - PDBG("Metadata file \"%s\" is plain text\n", file->path->str); - - /* Check text-only metadata header and version */ - nr_items = fscanf(file->fp, "/* CTF %10u.%10u", &major, &minor); - if (nr_items < 2) { - PWARN("Ill-shapen or missing \"/* CTF major.minor\" header in plain text metadata file\n"); - } - PDBG("Metadata version: %u.%u\n", major, minor); - - if (!is_version_valid(major, minor)) { - PERR("Invalid metadata version: %u.%u\n", major, minor); - goto error; - } - - rewind(file->fp); - } - - /* Allocate a scanner and append the metadata text content */ - scanner = ctf_scanner_alloc(); - if (!scanner) { - PERR("Cannot allocate a metadata lexical scanner\n"); - goto error; - } - - ret = ctf_scanner_append_ast(scanner, file->fp); - if (ret) { - PERR("Cannot create the metadata AST\n"); - goto error; - } - - ret = ctf_visitor_semantic_check(stderr, 0, &scanner->ast->root); - if (ret) { - PERR("Metadata semantic validation failed\n"); - goto error; - } - - ret = ctf_visitor_generate_ir(ctf_fs->error_fp, &scanner->ast->root, - &ctf_fs->metadata.trace); - if (ret) { - PERR("Cannot create trace object from metadata AST\n"); - goto error; - } - - goto end; - -error: - if (ctf_fs->metadata.text) { - free(ctf_fs->metadata.text); - ctf_fs->metadata.text = NULL; - } - -end: - if (file) { - ctf_fs_file_destroy(file); - } - - if (scanner) { - ctf_scanner_free(scanner); - } -} - -int ctf_fs_metadata_init(struct ctf_fs_metadata *metadata) -{ - /* Nothing to initialize for the moment */ - return 0; -} - -void ctf_fs_metadata_deinit(struct ctf_fs_metadata *metadata) -{ - if (metadata->text) { - free(metadata->text); - } - - if (metadata->trace) { - BT_PUT(metadata->trace); - } -} diff --git a/ctf-reader-proto/ctf-fs-metadata.h b/ctf-reader-proto/ctf-fs-metadata.h deleted file mode 100644 index ed9b7853..00000000 --- a/ctf-reader-proto/ctf-fs-metadata.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef CTF_FS_METADATA_H -#define CTF_FS_METADATA_H - -/* - * Copyright 2016 - Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include - -#define CTF_FS_METADATA_FILENAME "metadata" - -struct ctf_fs; - -struct ctf_fs_metadata { - struct bt_ctf_trace *trace; - uint8_t uuid[16]; - bool is_uuid_set; - int bo; - char *text; -}; - -BT_HIDDEN -int ctf_fs_metadata_init(struct ctf_fs_metadata *metadata); - -BT_HIDDEN -void ctf_fs_metadata_deinit(struct ctf_fs_metadata *metadata); - -BT_HIDDEN -void ctf_fs_metadata_set_trace(struct ctf_fs *ctf_fs); - -#endif /* CTF_FS_METADATA_H */ diff --git a/ctf-reader-proto/print.h b/ctf-reader-proto/print.h deleted file mode 100644 index 4c47f620..00000000 --- a/ctf-reader-proto/print.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef CTF_FS_PRINT_H -#define CTF_FS_PRINT_H - -/* - * Define PRINT_PREFIX and PRINT_ERR_STREAM, then include this file. - * - * Copyright (c) 2016 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -#include "ctf-fs.h" - -#define PERR(fmt, ...) \ - do { \ - if (PRINT_ERR_STREAM) { \ - fprintf(PRINT_ERR_STREAM, \ - "Error: " PRINT_PREFIX ": " fmt, \ - ##__VA_ARGS__); \ - } \ - } while (0) - -#define PWARN(fmt, ...) \ - do { \ - if (PRINT_ERR_STREAM) { \ - fprintf(PRINT_ERR_STREAM, \ - "Warning: " PRINT_PREFIX ": " fmt, \ - ##__VA_ARGS__); \ - } \ - } while (0) - -#define PDBG(fmt, ...) \ - do { \ - if (ctf_fs_debug) { \ - fprintf(stderr, \ - "Debug: " PRINT_PREFIX ": " fmt, \ - ##__VA_ARGS__); \ - } \ - } while (0) - -#endif /* CTF_FS_PRINT_H */ diff --git a/lib/plugin-system/source.c b/lib/plugin-system/source.c index e7c4c9af..333139f5 100644 --- a/lib/plugin-system/source.c +++ b/lib/plugin-system/source.c @@ -56,7 +56,7 @@ enum bt_component_status bt_component_source_validate( } source = container_of(component, struct bt_component_source, parent); - if (source->init_iterator) { + if (!source->init_iterator) { ret = BT_COMPONENT_STATUS_INVALID; goto end; } diff --git a/plugins/ctf/fs/Makefile.am b/plugins/ctf/fs/Makefile.am index 953ca337..c08c1aa9 100644 --- a/plugins/ctf/fs/Makefile.am +++ b/plugins/ctf/fs/Makefile.am @@ -1,7 +1,17 @@ AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -noinst_HEADERS = fs-internal.h +noinst_HEADERS = \ + fs.h \ + data-stream.h \ + file.h \ + metadata.h \ + print.h noinst_LTLIBRARIES = libbabeltrace-plugin-ctf-fs.la -# Plug-in system library -libbabeltrace_plugin_ctf_fs_la_SOURCES = fs.c +libbabeltrace_plugin_ctf_fs_la_LIBADD = \ + $(builddir)/../common/libbabeltrace-plugin-ctf-common.la +libbabeltrace_plugin_ctf_fs_la_SOURCES = \ + fs.c \ + data-stream.c \ + metadata.c \ + file.c diff --git a/plugins/ctf/fs/data-stream.c b/plugins/ctf/fs/data-stream.c new file mode 100644 index 00000000..6fba603a --- /dev/null +++ b/plugins/ctf/fs/data-stream.c @@ -0,0 +1,361 @@ +/* + * Copyright 2016 - Philippe Proulx + * Copyright 2010-2011 - EfficiOS Inc. and Linux Foundation + * + * Some functions are based on older functions written by Mathieu Desnoyers. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define PRINT_ERR_STREAM ctf_fs->error_fp +#define PRINT_PREFIX "ctf-fs-data-stream" +#include "print.h" + +#include "file.h" +#include "metadata.h" +#include "../common/notif-iter/notif-iter.h" + +static void ctf_fs_stream_destroy(struct ctf_fs_stream *stream) +{ + if (stream->file) { + ctf_fs_file_destroy(stream->file); + } + + if (stream->stream) { + BT_PUT(stream->stream); + } + + if (stream->notif_iter) { + bt_ctf_notif_iter_destroy(stream->notif_iter); + } + + g_free(stream); +} + +static size_t remaining_mmap_bytes(struct ctf_fs_stream *stream) +{ + return stream->mmap_offset + stream->mmap_len - + stream->request_offset; +} + +static int stream_munmap(struct ctf_fs_stream *stream) +{ + struct ctf_fs_component *ctf_fs = stream->file->ctf_fs; + + if (munmap(stream->mmap_addr, stream->mmap_len)) { + PERR("Cannot memory-unmap address %p (size %zu) of file \"%s\" (%p): %s\n", + stream->mmap_addr, stream->mmap_len, + stream->file->path->str, stream->file->fp, + strerror(errno)); + return -1; + } + + return 0; +} + +static int mmap_next(struct ctf_fs_stream *stream) +{ + struct ctf_fs_component *ctf_fs = stream->file->ctf_fs; + int ret = 0; + + /* Unmap old region */ + if (stream->mmap_addr) { + if (stream_munmap(stream)) { + goto error; + } + + stream->mmap_offset += stream->mmap_len; + stream->request_offset = stream->mmap_offset; + } + + /* Map new region */ + stream->mmap_addr = mmap((void *) 0, stream->mmap_len, + PROT_READ, MAP_PRIVATE, fileno(stream->file->fp), + stream->mmap_offset); + if (stream->mmap_addr == MAP_FAILED) { + PERR("Cannot memory-map address (size %zu) of file \"%s\" (%p) at offset %zu: %s\n", + stream->mmap_len, stream->file->path->str, + stream->file->fp, stream->mmap_offset, + strerror(errno)); + goto error; + } + + goto end; + +error: + stream_munmap(stream); + ret = -1; + +end: + return ret; +} + +static enum bt_ctf_notif_iter_medium_status medop_request_bytes( + size_t request_sz, uint8_t **buffer_addr, + size_t *buffer_sz, void *data) +{ + enum bt_ctf_notif_iter_medium_status status = + BT_CTF_NOTIF_ITER_MEDIUM_STATUS_OK; + struct ctf_fs_stream *stream = data; + struct ctf_fs_component *ctf_fs = stream->file->ctf_fs; + + if (request_sz == 0) { + goto end; + } + + /* Check if we need an initial memory map */ + if (!stream->mmap_addr) { + if (mmap_next(stream)) { + PERR("Cannot memory-map initial region of file \"%s\" (%p)\n", + stream->file->path->str, stream->file->fp); + goto error; + } + } + + /* Check if we have at least one memory-mapped byte left */ + if (remaining_mmap_bytes(stream) == 0) { + /* Are we at the end of the file? */ + if (stream->request_offset == stream->file->size) { + PDBG("Reached end of file \"%s\" (%p)\n", + stream->file->path->str, stream->file->fp); + status = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_EOF; + goto end; + } + + if (mmap_next(stream)) { + PERR("Cannot memory-map next region of file \"%s\" (%p)\n", + stream->file->path->str, stream->file->fp); + goto error; + } + } + + *buffer_sz = MIN(remaining_mmap_bytes(stream), request_sz); + *buffer_addr = ((uint8_t *) stream->mmap_addr) + + stream->request_offset - stream->mmap_offset; + stream->request_offset += *buffer_sz; + goto end; + +error: + status = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_ERROR; + +end: + return status; +} + +static struct bt_ctf_stream *medop_get_stream( + struct bt_ctf_stream_class *stream_class, void *data) +{ + struct ctf_fs_stream *fs_stream = data; + struct ctf_fs_component *ctf_fs = fs_stream->file->ctf_fs; + + if (!fs_stream->stream) { + int64_t id = bt_ctf_stream_class_get_id(stream_class); + + PDBG("Creating stream out of stream class %" PRId64 "\n", id); + fs_stream->stream = bt_ctf_stream_create(stream_class, + fs_stream->file->path->str); + if (!fs_stream->stream) { + PERR("Cannot create stream (stream class %" PRId64 ")\n", + id); + } + } + + return fs_stream->stream; +} + +static struct bt_ctf_notif_iter_medium_ops medops = { + .request_bytes = medop_request_bytes, + .get_stream = medop_get_stream, +}; + +static struct ctf_fs_stream *ctf_fs_stream_create( + struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file) +{ + struct ctf_fs_stream *stream = g_new0(struct ctf_fs_stream, 1); + + if (!stream) { + goto error; + } + + stream->file = file; + stream->notif_iter = bt_ctf_notif_iter_create(ctf_fs->metadata.trace, + 12, medops, stream, ctf_fs->error_fp); + if (!stream->notif_iter) { + goto error; + } + stream->mmap_len = ctf_fs->page_size; + + goto end; + +error: + /* Do not touch borrowed file */ + stream->file = NULL; + ctf_fs_stream_destroy(stream); + stream = NULL; + +end: + return stream; +} + +int ctf_fs_data_stream_open_streams(struct ctf_fs_component *ctf_fs) +{ + int ret = 0; + GError *error = NULL; + GDir *dir = g_dir_open(ctf_fs->trace_path->str, 0, &error); + const char *name; + + if (!dir) { + PERR("Cannot open directory \"%s\": %s (code %d)\n", + ctf_fs->trace_path->str, error->message, + error->code); + goto error; + } + + while ((name = g_dir_read_name(dir))) { + struct ctf_fs_file *file = NULL; + struct ctf_fs_stream *stream = NULL; + + if (strcmp(name, CTF_FS_METADATA_FILENAME) == 0) { + /* Ignore the metadata stream */ + PDBG("Ignoring metadata file \"%s\"\n", + name); + continue; + } + + if (name[0] == '.') { + PDBG("Ignoring hidden file \"%s\"\n", + name); + continue; + } + + /* Create the file */ + file = ctf_fs_file_create(ctf_fs); + if (!file) { + PERR("Cannot create stream file object\n"); + goto error; + } + + /* Create full path string */ + g_string_append(file->path, ctf_fs->trace_path->str); + g_string_append(file->path, "/"); + g_string_append(file->path, name); + + if (!g_file_test(file->path->str, G_FILE_TEST_IS_REGULAR)) { + PDBG("Ignoring non-regular file \"%s\"\n", name); + ctf_fs_file_destroy(file); + continue; + } + + /* Open the file */ + if (ctf_fs_file_open(ctf_fs, file, "rb")) { + ctf_fs_file_destroy(file); + goto error; + } + + /* Create a private stream */ + stream = ctf_fs_stream_create(ctf_fs, file); + if (!stream) { + ctf_fs_file_destroy(file); + goto error; + } + + /* Append file to the array of files */ + g_ptr_array_add(ctf_fs->data_stream.streams, stream); + } + + goto end; + +error: + ret = -1; + +end: + if (dir) { + g_dir_close(dir); + dir = NULL; + } + + if (error) { + g_error_free(error); + } + + return ret; +} + +int ctf_fs_data_stream_init(struct ctf_fs_component *ctf_fs, + struct ctf_fs_data_stream *data_stream) +{ + int ret = 0; + + data_stream->streams = g_ptr_array_new_with_free_func( + (GDestroyNotify) ctf_fs_stream_destroy); + if (!data_stream->streams) { + PERR("Cannot allocate array of streams\n"); + goto error; + } + + goto end; + +error: + ret = -1; + +end: + return ret; +} + +void ctf_fs_data_stream_deinit(struct ctf_fs_data_stream *data_stream) +{ + g_ptr_array_free(data_stream->streams, TRUE); +} + +int ctf_fs_data_stream_get_next_notification( + struct ctf_fs_component *ctf_fs, + struct bt_ctf_notif_iter_notif **notification) +{ + int ret = 0; + struct ctf_fs_stream *stream = g_ptr_array_index( + ctf_fs->data_stream.streams, 0); + enum bt_ctf_notif_iter_status status; + + status = bt_ctf_notif_iter_get_next_notification( + stream->notif_iter, notification); + if (status != BT_CTF_NOTIF_ITER_STATUS_OK && + status != BT_CTF_NOTIF_ITER_STATUS_EOF) { + goto error; + } + if (status == BT_CTF_NOTIF_ITER_STATUS_EOF) { + *notification = NULL; + } + + goto end; + +error: + ret = -1; + +end: + return ret; +} diff --git a/plugins/ctf/fs/data-stream.h b/plugins/ctf/fs/data-stream.h new file mode 100644 index 00000000..d8f67466 --- /dev/null +++ b/plugins/ctf/fs/data-stream.h @@ -0,0 +1,62 @@ +#ifndef CTF_FS_DATA_STREAM_H +#define CTF_FS_DATA_STREAM_H + +/* + * Copyright 2016 - Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include + +#include "ctf-notif-iter/ctf-notif-iter.h" + +struct ctf_fs_stream { + struct ctf_fs_file *file; + struct bt_ctf_stream *stream; + struct bt_ctf_notif_iter *notif_iter; + void *mmap_addr; + size_t mmap_len; + off_t mmap_offset; + off_t request_offset; +}; + +struct ctf_fs_data_stream { + GPtrArray *streams; +}; + +BT_HIDDEN +int ctf_fs_data_stream_init(struct ctf_fs *ctf_fs, + struct ctf_fs_data_stream *data_stream); + +BT_HIDDEN +void ctf_fs_data_stream_deinit(struct ctf_fs_data_stream *data_stream); + +BT_HIDDEN +int ctf_fs_data_stream_open_streams(struct ctf_fs *ctf_fs); + +BT_HIDDEN +int ctf_fs_data_stream_get_next_notification( + struct ctf_fs *ctf_fs, + struct bt_ctf_notif_iter_notif **notification); + +#endif /* CTF_FS_DATA_STREAM_H */ diff --git a/plugins/ctf/fs/file.c b/plugins/ctf/fs/file.c new file mode 100644 index 00000000..1d31bcfc --- /dev/null +++ b/plugins/ctf/fs/file.c @@ -0,0 +1,120 @@ +/* + * Copyright 2016 - Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#define PRINT_ERR_STREAM ctf_fs->error_fp +#define PRINT_PREFIX "ctf-fs-file" +#include "print.h" + +#include "file.h" + +void ctf_fs_file_destroy(struct ctf_fs_file *file) +{ + struct ctf_fs_component *ctf_fs = file->ctf_fs; + + if (!file) { + return; + } + + if (file->fp) { + PDBG("Closing file \"%s\" (%p)\n", file->path->str, file->fp); + + if (fclose(file->fp)) { + PERR("Cannot close file \"%s\": %s\n", file->path->str, + strerror(errno)); + } + } + + if (file->path) { + g_string_free(file->path, TRUE); + } + + g_free(file); +} + +struct ctf_fs_file *ctf_fs_file_create(struct ctf_fs_component *ctf_fs) +{ + struct ctf_fs_file *file = g_new0(struct ctf_fs_file, 1); + + if (!file) { + goto error; + } + + file->ctf_fs = ctf_fs; + file->path = g_string_new(NULL); + if (!file->path) { + goto error; + } + + goto end; + +error: + ctf_fs_file_destroy(file); + file = NULL; + +end: + return file; +} + +int ctf_fs_file_open(struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file, + const char *mode) +{ + int ret = 0; + struct stat stat; + + PDBG("Opening file \"%s\" with mode \"%s\"\n", file->path->str, mode); + file->fp = fopen(file->path->str, mode); + if (!file->fp) { + PERR("Cannot open file \"%s\" with mode \"%s\": %s", + file->path->str, mode, strerror(errno)); + goto error; + } + + PDBG("Opened file: %p\n", file->fp); + + if (fstat(fileno(file->fp), &stat)) { + PERR("Cannot get file informations: %s\n", strerror(errno)); + goto error; + } + + file->size = stat.st_size; + PDBG(" File is %zu bytes\n", file->size); + goto end; + +error: + ret = -1; + + if (file->fp) { + if (fclose(file->fp)) { + PERR("Cannot close file \"%s\": %s\n", file->path->str, + strerror(errno)); + } + } + +end: + return ret; +} diff --git a/plugins/ctf/fs/file.h b/plugins/ctf/fs/file.h new file mode 100644 index 00000000..59f3d0ec --- /dev/null +++ b/plugins/ctf/fs/file.h @@ -0,0 +1,41 @@ +#ifndef CTF_FS_FILE_H +#define CTF_FS_FILE_H + +/* + * Copyright 2016 - Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include "fs.h" + +BT_HIDDEN +void ctf_fs_file_destroy(struct ctf_fs_file *file); + +BT_HIDDEN +struct ctf_fs_file *ctf_fs_file_create(struct ctf_fs_component *ctf_fs); + +BT_HIDDEN +int ctf_fs_file_open(struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file, + const char *mode); + +#endif /* CTF_FS_FILE_H */ diff --git a/plugins/ctf/fs/fs-internal.h b/plugins/ctf/fs/fs-internal.h deleted file mode 100644 index d0a9f760..00000000 --- a/plugins/ctf/fs/fs-internal.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef BABELTRACE_PLUGIN_CTF_FS_INTERNAL_H -#define BABELTRACE_PLUGIN_CTF_FS_INTERNAL_H - -/* - * BabelTrace - CTF on File System Component - * - * Copyright 2016 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#define CTF_FS_COMPONENT_NAME "ctf" -#define CTF_FS_COMPONENT_DESCRIPTION \ - "Component used to read a CTF trace located on a file system." - -struct ctf_fs_iterator { - int dummy; -}; - -struct ctf_fs_component_options { - bool opt_dummy : 1; -}; - -struct ctf_fs_component { - struct ctf_fs_component_options options; -}; - -BT_HIDDEN -enum bt_component_status ctf_fs_init(struct bt_component *source, - struct bt_value *params); - -#endif /* BABELTRACE_PLUGIN_CTF_FS_INTERNAL_H */ diff --git a/plugins/ctf/fs/fs.c b/plugins/ctf/fs/fs.c index cd58753a..9019543e 100644 --- a/plugins/ctf/fs/fs.c +++ b/plugins/ctf/fs/fs.c @@ -30,7 +30,8 @@ #include #include #include -#include "fs-internal.h" +#include +#include "fs.h" static bool ctf_fs_debug; @@ -104,15 +105,15 @@ error: return ret; } -static -struct ctf_fs_component *ctf_fs_create(struct bt_value *params) -{ - return g_new0(struct ctf_fs_component, 1); -} - static void ctf_fs_destroy_data(struct ctf_fs_component *component) { + if (component->trace_path) { + g_string_free(component->trace_path, TRUE); + } + +// ctf_fs_metadata_fini(&component->metadata); +// ctf_fs_data_stream_fini(&component->data_stream); g_free(component); } @@ -124,6 +125,45 @@ void ctf_fs_destroy(struct bt_component *component) ctf_fs_destroy_data(data); } +static +struct ctf_fs_component *ctf_fs_create(struct bt_value *params) +{ + struct ctf_fs_component *ctf_fs; + struct bt_value *value; + const char *path; + enum bt_value_status ret; + + ctf_fs = g_new0(struct ctf_fs_component, 1); + if (!ctf_fs) { + goto end; + } + + /* FIXME: should probably look for a source URI */ + value = bt_value_map_get(params, "path"); + if (!value || bt_value_is_null(value) || !bt_value_is_string(value)) { + goto error; + } + + ret = bt_value_string_get(value, &path); + if (ret != BT_VALUE_STATUS_OK) { + goto error; + } + + ctf_fs->trace_path = g_string_new(path); + if (!ctf_fs->trace_path) { + goto error; + } + + ctf_fs->error_fp = stderr; + ctf_fs->page_size = (size_t) getpagesize(); + +end: + return ctf_fs; +error: + ctf_fs_destroy_data(ctf_fs); + return ctf_fs; +} + BT_HIDDEN enum bt_component_status ctf_fs_init(struct bt_component *source, struct bt_value *params) diff --git a/plugins/ctf/fs/fs.h b/plugins/ctf/fs/fs.h new file mode 100644 index 00000000..ff97b7a2 --- /dev/null +++ b/plugins/ctf/fs/fs.h @@ -0,0 +1,90 @@ +#ifndef BABELTRACE_PLUGIN_CTF_FS_INTERNAL_H +#define BABELTRACE_PLUGIN_CTF_FS_INTERNAL_H + +/* + * BabelTrace - CTF on File System Component + * + * Copyright 2016 Jérémie Galarneau + * Copyright 2016 Philippe Proulx + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + +#define CTF_FS_COMPONENT_NAME "fs" +#define CTF_FS_COMPONENT_DESCRIPTION \ + "Component used to read a CTF trace located on a file system." + +static bool ctf_fs_debug; + +struct ctf_fs_file { + struct ctf_fs_component *ctf_fs; + GString *path; + FILE *fp; + off_t size; +}; + +struct ctf_fs_metadata { + struct bt_ctf_trace *trace; + uint8_t uuid[16]; + bool is_uuid_set; + int bo; + char *text; +}; + +struct ctf_fs_stream { + struct ctf_fs_file *file; + struct bt_ctf_stream *stream; + struct bt_ctf_notif_iter *notif_iter; + void *mmap_addr; + size_t mmap_len; + off_t mmap_offset; + off_t request_offset; +}; + +struct ctf_fs_data_stream { + GPtrArray *streams; +}; + +struct ctf_fs_iterator { + int dummy; +}; + +struct ctf_fs_component_options { + bool opt_dummy : 1; +}; + +struct ctf_fs_component { + GString *trace_path; + FILE *error_fp; + size_t page_size; + struct ctf_fs_metadata metadata; + struct ctf_fs_data_stream data_stream; + struct ctf_fs_component_options options; +}; + +BT_HIDDEN +enum bt_component_status ctf_fs_init(struct bt_component *source, + struct bt_value *params); + +#endif /* BABELTRACE_PLUGIN_CTF_FS_INTERNAL_H */ diff --git a/plugins/ctf/fs/metadata.c b/plugins/ctf/fs/metadata.c new file mode 100644 index 00000000..967452f9 --- /dev/null +++ b/plugins/ctf/fs/metadata.c @@ -0,0 +1,405 @@ +/* + * Copyright 2016 - Philippe Proulx + * Copyright 2010-2011 - EfficiOS Inc. and Linux Foundation + * + * Some functions are based on older functions written by Mathieu Desnoyers. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define PRINT_ERR_STREAM ctf_fs->error_fp +#define PRINT_PREFIX "ctf-fs-metadata" +#include "print.h" + +#include "fs.h" +#include "file.h" +#include "metadata.h" +#include "../common/metadata/ast.h" +#include "../common/metadata/scanner.h" + +#define TSDL_MAGIC 0x75d11d57 + +struct packet_header { + uint32_t magic; + uint8_t uuid[16]; + uint32_t checksum; + uint32_t content_size; + uint32_t packet_size; + uint8_t compression_scheme; + uint8_t encryption_scheme; + uint8_t checksum_scheme; + uint8_t major; + uint8_t minor; +} __attribute__((__packed__)); + +static struct ctf_fs_file *get_file(struct ctf_fs_component *ctf_fs, + const char *trace_path) +{ + struct ctf_fs_file *file = ctf_fs_file_create(ctf_fs); + + if (!file) { + goto error; + } + + g_string_append(file->path, trace_path); + g_string_append(file->path, "/" CTF_FS_METADATA_FILENAME); + + if (ctf_fs_file_open(ctf_fs, file, "rb")) { + goto error; + } + + goto end; + +error: + if (file) { + ctf_fs_file_destroy(file); + file = NULL; + } + +end: + return file; +} + +static +bool is_packetized(struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file) +{ + uint32_t magic; + size_t len; + int ret = 0; + + len = fread(&magic, sizeof(magic), 1, file->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; + } + +end: + rewind(file->fp); + + return ret; +} + +static +bool is_version_valid(unsigned int major, unsigned int minor) +{ + return major == 1 && minor == 8; +} + +static +int decode_packet(struct ctf_fs_component *ctf_fs, FILE *in_fp, FILE *out_fp) +{ + struct packet_header header; + size_t readlen, writelen, toread; + uint8_t buf[512 + 1]; /* + 1 for debug-mode \0 */ + int ret = 0; + + readlen = fread(&header, sizeof(header), 1, in_fp); + if (feof(in_fp) != 0) { + goto end; + } + if (readlen < 1) { + goto error; + } + + if (ctf_fs->metadata.bo != 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); + header.packet_size = GUINT32_SWAP_LE_BE(header.packet_size); + } + + if (header.compression_scheme) { + PERR("Metadata packet compression not supported yet\n"); + goto error; + } + + if (header.encryption_scheme) { + PERR("Metadata packet encryption not supported yet\n"); + goto error; + } + + if (header.checksum || header.checksum_scheme) { + PERR("Metadata packet checksum verification not supported yet\n"); + goto error; + } + + if (!is_version_valid(header.major, header.minor)) { + PERR("Invalid metadata version: %u.%u\n", header.major, + header.minor); + goto error; + } + + /* 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 ((header.content_size / CHAR_BIT) < sizeof(header)) { + PERR("Bad metadata packet content size: %u\n", + header.content_size); + goto error; + } + + toread = header.content_size / CHAR_BIT - sizeof(header); + + for (;;) { + readlen = fread(buf, sizeof(uint8_t), + MIN(sizeof(buf) - 1, toread), in_fp); + if (ferror(in_fp)) { + PERR("Cannot read metadata packet buffer (at position %ld)\n", + ftell(in_fp)); + goto error; + } + + writelen = fwrite(buf, sizeof(uint8_t), readlen, out_fp); + if (writelen < readlen || ferror(out_fp)) { + PERR("Cannot write decoded metadata text to buffer\n"); + goto error; + } + + toread -= readlen; + if (toread == 0) { + int fseek_ret; + + /* Read leftover padding */ + toread = (header.packet_size - header.content_size) / + CHAR_BIT; + fseek_ret = fseek(in_fp, toread, SEEK_CUR); + if (fseek_ret < 0) { + PWARN("Missing padding at the end of the metadata file\n"); + } + + break; + } + } + + goto end; + +error: + ret = -1; + +end: + return ret; +} + +static +int packetized_file_to_buf(struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file, + uint8_t **buf) +{ + FILE *out_fp; + size_t size; + int ret = 0; + int tret; + size_t packet_index = 0; + + out_fp = babeltrace_open_memstream((char **) buf, &size); + if (out_fp == NULL) { + PERR("Cannot open memory stream: %s\n", strerror(errno)); + goto error; + } + + for (;;) { + if (feof(file->fp) != 0) { + break; + } + + tret = decode_packet(ctf_fs, file->fp, out_fp); + if (tret) { + PERR("Cannot decode packet #%zu\n", packet_index); + goto error; + } + + packet_index++; + } + + /* Make sure the whole string ends with a null character */ + tret = fputc('\0', out_fp); + if (tret == EOF) { + PERR("Cannot append '\\0' to the decoded metadata buffer\n"); + goto error; + } + + /* Close stream, which also flushes the buffer */ + ret = babeltrace_close_memstream((char **) buf, &size, out_fp); + if (ret < 0) { + PERR("Cannot close memory stream: %s\n", strerror(errno)); + goto error; + } + + goto end; + +error: + ret = -1; + + if (out_fp) { + babeltrace_close_memstream((char **) buf, &size, out_fp); + } + + if (*buf) { + free(*buf); + } + +end: + return ret; +} + +void ctf_fs_metadata_set_trace(struct ctf_fs_component *ctf_fs) +{ + int ret = 0; + struct ctf_fs_file *file = get_file(ctf_fs, ctf_fs->trace_path->str); + struct ctf_scanner *scanner = NULL; + uint8_t *buf = NULL; + char *cbuf; + + if (!file) { + PERR("Cannot create metadata file object\n"); + goto error; + } + + if (babeltrace_debug) { + // yydebug = 1; + } + + if (is_packetized(ctf_fs, file)) { + PDBG("Metadata file \"%s\" is packetized\n", file->path->str); + ret = packetized_file_to_buf(ctf_fs, file, &buf); + if (ret) { + // log: details + goto error; + } + + cbuf = (char *) buf; + ctf_fs->metadata.text = (char *) cbuf; + + /* Convert the real file pointer to a memory file pointer */ + ret = fclose(file->fp); + file->fp = NULL; + if (ret) { + PERR("Cannot close file \"%s\": %s\n", file->path->str, + strerror(errno)); + goto error; + } + + file->fp = babeltrace_fmemopen(cbuf, strlen(cbuf), "rb"); + if (!file->fp) { + PERR("Cannot memory-open metadata buffer: %s\n", + strerror(errno)); + goto error; + } + } else { + unsigned int major, minor; + ssize_t nr_items; + + PDBG("Metadata file \"%s\" is plain text\n", file->path->str); + + /* Check text-only metadata header and version */ + nr_items = fscanf(file->fp, "/* CTF %10u.%10u", &major, &minor); + if (nr_items < 2) { + PWARN("Ill-shapen or missing \"/* CTF major.minor\" header in plain text metadata file\n"); + } + PDBG("Metadata version: %u.%u\n", major, minor); + + if (!is_version_valid(major, minor)) { + PERR("Invalid metadata version: %u.%u\n", major, minor); + goto error; + } + + rewind(file->fp); + } + + /* Allocate a scanner and append the metadata text content */ + scanner = ctf_scanner_alloc(); + if (!scanner) { + PERR("Cannot allocate a metadata lexical scanner\n"); + goto error; + } + + ret = ctf_scanner_append_ast(scanner, file->fp); + if (ret) { + PERR("Cannot create the metadata AST\n"); + goto error; + } + + ret = ctf_visitor_semantic_check(stderr, 0, &scanner->ast->root); + if (ret) { + PERR("Metadata semantic validation failed\n"); + goto error; + } + + ret = ctf_visitor_generate_ir(ctf_fs->error_fp, &scanner->ast->root, + &ctf_fs->metadata.trace); + if (ret) { + PERR("Cannot create trace object from metadata AST\n"); + goto error; + } + + goto end; + +error: + if (ctf_fs->metadata.text) { + free(ctf_fs->metadata.text); + ctf_fs->metadata.text = NULL; + } + +end: + if (file) { + ctf_fs_file_destroy(file); + } + + if (scanner) { + ctf_scanner_free(scanner); + } +} + +int ctf_fs_metadata_init(struct ctf_fs_metadata *metadata) +{ + /* Nothing to initialize for the moment */ + return 0; +} + +void ctf_fs_metadata_deinit(struct ctf_fs_metadata *metadata) +{ + if (metadata->text) { + free(metadata->text); + } + + if (metadata->trace) { + BT_PUT(metadata->trace); + } +} diff --git a/plugins/ctf/fs/metadata.h b/plugins/ctf/fs/metadata.h new file mode 100644 index 00000000..eeccf848 --- /dev/null +++ b/plugins/ctf/fs/metadata.h @@ -0,0 +1,43 @@ +#ifndef CTF_FS_METADATA_H +#define CTF_FS_METADATA_H + +/* + * Copyright 2016 - Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include "fs.h" + +#define CTF_FS_METADATA_FILENAME "metadata" + +BT_HIDDEN +int ctf_fs_metadata_init(struct ctf_fs_metadata *metadata); + +BT_HIDDEN +void ctf_fs_metadata_deinit(struct ctf_fs_metadata *metadata); + +BT_HIDDEN +void ctf_fs_metadata_set_trace(struct ctf_fs_component *ctf_fs); + +#endif /* CTF_FS_METADATA_H */ diff --git a/plugins/ctf/fs/print.h b/plugins/ctf/fs/print.h new file mode 100644 index 00000000..9daf7ea4 --- /dev/null +++ b/plugins/ctf/fs/print.h @@ -0,0 +1,57 @@ +#ifndef CTF_FS_PRINT_H +#define CTF_FS_PRINT_H + +/* + * Define PRINT_PREFIX and PRINT_ERR_STREAM, then include this file. + * + * Copyright (c) 2016 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +#define PERR(fmt, ...) \ + do { \ + if (PRINT_ERR_STREAM) { \ + fprintf(PRINT_ERR_STREAM, \ + "Error: " PRINT_PREFIX ": " fmt, \ + ##__VA_ARGS__); \ + } \ + } while (0) + +#define PWARN(fmt, ...) \ + do { \ + if (PRINT_ERR_STREAM) { \ + fprintf(PRINT_ERR_STREAM, \ + "Warning: " PRINT_PREFIX ": " fmt, \ + ##__VA_ARGS__); \ + } \ + } while (0) + +#define PDBG(fmt, ...) \ + do { \ + if (ctf_fs_debug) { \ + fprintf(stderr, \ + "Debug: " PRINT_PREFIX ": " fmt, \ + ##__VA_ARGS__); \ + } \ + } while (0) + +#endif /* CTF_FS_PRINT_H */ diff --git a/plugins/ctf/plugin.c b/plugins/ctf/plugin.c index ef6ed2fd..f84f9ce0 100644 --- a/plugins/ctf/plugin.c +++ b/plugins/ctf/plugin.c @@ -27,19 +27,19 @@ */ #include -#include "fs/fs-internal.h" +#include "fs/fs.h" #include "lttng-live/lttng-live-internal.h" -/* Initialize plug-in entry points. */ +/* Initialize plug-in description. */ BT_PLUGIN_NAME("ctf"); -BT_PLUGIN_DESCRIPTION("Babeltrace CTF plug-in."); +BT_PLUGIN_DESCRIPTION("Built-in Babeltrace plug-in providing CTF read support."); BT_PLUGIN_AUTHOR("Jérémie Galarneau"); BT_PLUGIN_LICENSE("MIT"); +/* Declare component classes implemented by this plug-in. */ BT_PLUGIN_COMPONENT_CLASSES_BEGIN BT_PLUGIN_SOURCE_COMPONENT_CLASS_ENTRY(CTF_FS_COMPONENT_NAME, CTF_FS_COMPONENT_DESCRIPTION, ctf_fs_init); BT_PLUGIN_SOURCE_COMPONENT_CLASS_ENTRY(LTTNG_LIVE_COMPONENT_NAME, LTTNG_LIVE_COMPONENT_DESCRIPTION, lttng_live_init); BT_PLUGIN_COMPONENT_CLASSES_END - diff --git a/plugins/text/text.c b/plugins/text/text.c index a269fe16..9a31041e 100644 --- a/plugins/text/text.c +++ b/plugins/text/text.c @@ -155,7 +155,7 @@ error: } /* Initialize plug-in entry points. */ -BT_PLUGIN_NAME("ctf-text"); +BT_PLUGIN_NAME("text"); BT_PLUGIN_DESCRIPTION("Babeltrace text output plug-in."); BT_PLUGIN_AUTHOR("Jérémie Galarneau"); BT_PLUGIN_LICENSE("MIT");