X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=plugins%2Fctf%2Ffs-src%2Fdata-stream-file.c;h=52954bd247d7677f0c52e52b1d46c3f180bfafef;hb=89b08333996aedb3378fc37939d489a0768bd955;hp=94f2b9b3edfb1c563eaeb4d35801a71b5cd2cf89;hpb=d238196d1f1b84c98b3a2b8ca49ea83607eb2e9d;p=babeltrace.git diff --git a/plugins/ctf/fs-src/data-stream-file.c b/plugins/ctf/fs-src/data-stream-file.c index 94f2b9b3..52954bd2 100644 --- a/plugins/ctf/fs-src/data-stream-file.c +++ b/plugins/ctf/fs-src/data-stream-file.c @@ -29,22 +29,23 @@ #include #include #include -#include +#include +#include #include #include #include #include #include +#include #include "file.h" #include "metadata.h" #include "../common/notif-iter/notif-iter.h" #include #include "data-stream-file.h" +#include -#define PRINT_ERR_STREAM ctf_fs->error_fp -#define PRINT_PREFIX "ctf-fs-data-stream" -#define PRINT_DBG_CHECK ctf_fs_debug -#include "../print.h" +#define BT_LOG_TAG "PLUGIN-CTF-FS-SRC-DS" +#include "logging.h" static inline size_t remaining_mmap_bytes(struct ctf_fs_ds_file *ds_file) @@ -56,15 +57,13 @@ static int ds_file_munmap(struct ctf_fs_ds_file *ds_file) { int ret = 0; - struct ctf_fs_component *ctf_fs; if (!ds_file || !ds_file->mmap_addr) { goto end; } - ctf_fs = ds_file->file->ctf_fs; if (munmap(ds_file->mmap_addr, ds_file->mmap_len)) { - PERR("Cannot memory-unmap address %p (size %zu) of file \"%s\" (%p): %s\n", + BT_LOGE("Cannot memory-unmap address %p (size %zu) of file \"%s\" (%p): %s", ds_file->mmap_addr, ds_file->mmap_len, ds_file->file->path->str, ds_file->file->fp, strerror(errno)); @@ -82,9 +81,9 @@ static enum bt_ctf_notif_iter_medium_status ds_file_mmap_next( struct ctf_fs_ds_file *ds_file) { + const size_t page_size = bt_common_get_page_size(); enum bt_ctf_notif_iter_medium_status ret = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_OK; - struct ctf_fs_component *ctf_fs = ds_file->file->ctf_fs; /* Unmap old region */ if (ds_file->mmap_addr) { @@ -103,15 +102,15 @@ enum bt_ctf_notif_iter_medium_status ds_file_mmap_next( goto end; } /* Round up to next page, assuming page size being a power of 2. */ - ds_file->mmap_len = (ds_file->mmap_valid_len + ctf_fs->page_size - 1) - & ~(ctf_fs->page_size - 1); + ds_file->mmap_len = (ds_file->mmap_valid_len + page_size - 1) + & ~(page_size - 1); /* Map new region */ assert(ds_file->mmap_len); ds_file->mmap_addr = mmap((void *) 0, ds_file->mmap_len, PROT_READ, MAP_PRIVATE, fileno(ds_file->file->fp), ds_file->mmap_offset); if (ds_file->mmap_addr == MAP_FAILED) { - PERR("Cannot memory-map address (size %zu) of file \"%s\" (%p) at offset %zu: %s\n", + BT_LOGE("Cannot memory-map address (size %zu) of file \"%s\" (%p) at offset %zu: %s", ds_file->mmap_len, ds_file->file->path->str, ds_file->file->fp, ds_file->mmap_offset, strerror(errno)); @@ -134,7 +133,6 @@ enum bt_ctf_notif_iter_medium_status medop_request_bytes( enum bt_ctf_notif_iter_medium_status status = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_OK; struct ctf_fs_ds_file *ds_file = data; - struct ctf_fs_component *ctf_fs = ds_file->file->ctf_fs; if (request_sz == 0) { goto end; @@ -144,7 +142,7 @@ enum bt_ctf_notif_iter_medium_status medop_request_bytes( if (remaining_mmap_bytes(ds_file) == 0) { /* Are we at the end of the file? */ if (ds_file->mmap_offset >= ds_file->file->size) { - PDBG("Reached end of file \"%s\" (%p)\n", + BT_LOGD("Reached end of file \"%s\" (%p)", ds_file->file->path->str, ds_file->file->fp); status = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_EOF; goto end; @@ -157,7 +155,7 @@ enum bt_ctf_notif_iter_medium_status medop_request_bytes( case BT_CTF_NOTIF_ITER_MEDIUM_STATUS_EOF: goto end; default: - PERR("Cannot memory-map next region of file \"%s\" (%p)\n", + BT_LOGE("Cannot memory-map next region of file \"%s\" (%p)", ds_file->file->path->str, ds_file->file->fp); goto error; @@ -205,42 +203,191 @@ static struct bt_ctf_notif_iter_medium_ops medops = { .request_bytes = medop_request_bytes, .get_stream = medop_get_stream, }; +static +struct ctf_fs_ds_index *ctf_fs_ds_index_create(size_t length) +{ + struct ctf_fs_ds_index *index = g_new0(struct ctf_fs_ds_index, 1); + + if (!index) { + BT_LOGE_STR("Failed to allocate index"); + goto error; + } + + index->entries = g_array_sized_new(FALSE, TRUE, + sizeof(struct ctf_fs_ds_index_entry), length); + if (!index->entries) { + BT_LOGE("Failed to allocate %zu index entries.", length); + goto error; + } + g_array_set_size(index->entries, length); +end: + return index; +error: + ctf_fs_ds_index_destroy(index); + goto end; +} + +static +struct bt_ctf_clock_class *get_field_mapped_clock_class( + struct bt_ctf_field *field) +{ + struct bt_ctf_field_type *field_type; + struct bt_ctf_clock_class *clock_class = NULL; + + field_type = bt_ctf_field_get_type(field); + if (!field_type) { + goto end; + } + + clock_class = bt_ctf_field_type_integer_get_mapped_clock_class( + field_type); + if (!clock_class) { + goto end; + } +end: + bt_put(field_type); + return clock_class; +} + +static +int get_ds_file_packet_bounds_clock_classes(struct ctf_fs_ds_file *ds_file, + struct bt_ctf_clock_class **_timestamp_begin_cc, + struct bt_ctf_clock_class **_timestamp_end_cc) +{ + int ret; + struct bt_ctf_field *timestamp_field = NULL; + struct bt_ctf_field *packet_context_field = NULL; + struct bt_ctf_clock_class *timestamp_begin_cc = NULL; + struct bt_ctf_clock_class *timestamp_end_cc = NULL; + + ret = ctf_fs_ds_file_get_packet_header_context_fields(ds_file, + NULL, &packet_context_field); + if (ret || !packet_context_field) { + BT_LOGD("Cannot retrieve packet context field of stream \'%s\'", + ds_file->file->path->str); + ret = -1; + goto end; + } + + timestamp_field = bt_ctf_field_structure_get_field_by_name( + packet_context_field, "timestamp_begin"); + if (!timestamp_field) { + BT_LOGD("Cannot retrieve timestamp_begin field in packet context of stream \'%s\'", + ds_file->file->path->str); + ret = -1; + goto end; + } + + timestamp_begin_cc = get_field_mapped_clock_class(timestamp_field); + if (!timestamp_begin_cc) { + BT_LOGD("Cannot retrieve the clock mapped to timestamp_begin of stream \'%s\'", + ds_file->file->path->str); + } + BT_PUT(timestamp_field); + + timestamp_field = bt_ctf_field_structure_get_field_by_name( + packet_context_field, "timestamp_end"); + if (!timestamp_field) { + BT_LOGD("Cannot retrieve timestamp_end field in packet context of stream \'%s\'", + ds_file->file->path->str); + ret = -1; + goto end; + } + + timestamp_end_cc = get_field_mapped_clock_class(timestamp_field); + if (!timestamp_end_cc) { + BT_LOGD("Cannot retrieve the clock mapped to timestamp_end in stream \'%s\'", + ds_file->file->path->str); + } + + if (_timestamp_begin_cc) { + *_timestamp_begin_cc = bt_get(timestamp_begin_cc); + } + if (_timestamp_end_cc) { + *_timestamp_end_cc = bt_get(timestamp_end_cc); + } +end: + bt_put(packet_context_field); + bt_put(timestamp_field); + bt_put(timestamp_begin_cc); + bt_put(timestamp_end_cc); + return ret; +} static -int build_index_from_idx_file(struct ctf_fs_ds_file *ds_file) +int convert_cycles_to_ns(struct bt_ctf_clock_class *clock_class, + uint64_t cycles, int64_t *ns) { int ret = 0; + struct bt_ctf_clock_value *clock_value; + + assert(ns); + clock_value = bt_ctf_clock_value_create(clock_class, cycles); + if (!clock_value) { + ret = -1; + goto end; + } + + ret = bt_ctf_clock_value_get_value_ns_from_epoch(clock_value, ns); + if (ret) { + goto end; + } +end: + bt_put(clock_value); + return ret; +} + +static +struct ctf_fs_ds_index *build_index_from_idx_file( + struct ctf_fs_ds_file *ds_file) +{ + int ret; gchar *directory = NULL; gchar *basename = NULL; GString *index_basename = NULL; gchar *index_file_path = NULL; GMappedFile *mapped_file = NULL; gsize filesize; - const struct ctf_packet_index_file_hdr *header; - const char *mmap_begin, *file_pos; - struct index_entry *index; + const char *mmap_begin = NULL, *file_pos = NULL; + const struct ctf_packet_index_file_hdr *header = NULL; + struct ctf_fs_ds_index *index = NULL; + struct ctf_fs_ds_index_entry *index_entry = NULL; uint64_t total_packets_size = 0; size_t file_index_entry_size; size_t file_entry_count; size_t i; + struct bt_ctf_clock_class *timestamp_begin_cc = NULL; + struct bt_ctf_clock_class *timestamp_end_cc = NULL; + + BT_LOGD("Building index from .idx file of stream file %s", + ds_file->file->path->str); + + ret = get_ds_file_packet_bounds_clock_classes(ds_file, + ×tamp_begin_cc, ×tamp_end_cc); + if (ret) { + BT_LOGD("Cannot get clock classes of \"timestamp_begin\" and \"timestamp_end\" fields"); + goto error; + } /* Look for index file in relative path index/name.idx. */ basename = g_path_get_basename(ds_file->file->path->str); if (!basename) { - ret = -1; - goto end; + BT_LOGE("Cannot get the basename of datastream file %s", + ds_file->file->path->str); + goto error; } directory = g_path_get_dirname(ds_file->file->path->str); if (!directory) { - ret = -1; - goto end; + BT_LOGE("Cannot get dirname of datastream file %s", + ds_file->file->path->str); + goto error; } index_basename = g_string_new(basename); if (!index_basename) { - ret = -1; - goto end; + BT_LOGE("Cannot allocate index file basename string"); + goto error; } g_string_append(index_basename, ".idx"); @@ -248,14 +395,14 @@ int build_index_from_idx_file(struct ctf_fs_ds_file *ds_file) index_basename->str, NULL); mapped_file = g_mapped_file_new(index_file_path, FALSE, NULL); if (!mapped_file) { - ret = -1; - goto end; + BT_LOGD("Cannot create new mapped file %s", + index_file_path); + goto error; } filesize = g_mapped_file_get_length(mapped_file); if (filesize < sizeof(*header)) { - printf_error("Invalid LTTng trace index: file size < header size"); - ret = -1; - goto end; + BT_LOGW("Invalid LTTng trace index file: file size < header size"); + goto error; } mmap_begin = g_mapped_file_get_contents(mapped_file); @@ -263,66 +410,74 @@ int build_index_from_idx_file(struct ctf_fs_ds_file *ds_file) file_pos = g_mapped_file_get_contents(mapped_file) + sizeof(*header); if (be32toh(header->magic) != CTF_INDEX_MAGIC) { - printf_error("Invalid LTTng trace index: \"magic\" validation failed"); - ret = -1; - goto end; + BT_LOGW("Invalid LTTng trace index: \"magic\" validation failed"); + goto error; } file_index_entry_size = be32toh(header->packet_index_len); file_entry_count = (filesize - sizeof(*header)) / file_index_entry_size; - if ((filesize - sizeof(*header)) % (file_entry_count * file_index_entry_size)) { - printf_error("Invalid index file size; not a multiple of index entry size"); - ret = -1; - goto end; + if ((filesize - sizeof(*header)) % file_index_entry_size) { + BT_LOGW("Invalid index file size; not a multiple of index entry size"); + goto error; } - ds_file->index.entries = g_array_sized_new(FALSE, TRUE, - sizeof(struct index_entry), file_entry_count); - if (!ds_file->index.entries) { - ret = -1; - goto end; + index = ctf_fs_ds_index_create(file_entry_count); + if (!index) { + goto error; } - index = (struct index_entry *) ds_file->index.entries->data; + + index_entry = (struct ctf_fs_ds_index_entry *) &g_array_index( + index->entries, struct ctf_fs_ds_index_entry, 0); for (i = 0; i < file_entry_count; i++) { struct ctf_packet_index *file_index = (struct ctf_packet_index *) file_pos; uint64_t packet_size = be64toh(file_index->packet_size); if (packet_size % CHAR_BIT) { - ret = -1; - printf_error("Invalid packet size encountered in index file"); - goto invalid_index; + BT_LOGW("Invalid packet size encountered in index file"); + goto error; } /* Convert size in bits to bytes. */ packet_size /= CHAR_BIT; - index->packet_size = packet_size; + index_entry->packet_size = packet_size; - index->offset = be64toh(file_index->offset); - if (i != 0 && index->offset < (index - 1)->offset) { - printf_error("Invalid, non-monotonic, packet offset encountered in index file"); - ret = -1; - goto invalid_index; + index_entry->offset = be64toh(file_index->offset); + if (i != 0 && index_entry->offset < (index_entry - 1)->offset) { + BT_LOGW("Invalid, non-monotonic, packet offset encountered in index file"); + goto error; } - index->timestamp_begin = be64toh(file_index->timestamp_begin); - index->timestamp_end = be64toh(file_index->timestamp_end); - if (index->timestamp_end < index->timestamp_begin) { - printf_error("Invalid packet time bounds encountered in index file"); - ret = -1; - goto invalid_index; + index_entry->timestamp_begin = be64toh(file_index->timestamp_begin); + index_entry->timestamp_end = be64toh(file_index->timestamp_end); + if (index_entry->timestamp_end < index_entry->timestamp_begin) { + BT_LOGW("Invalid packet time bounds encountered in index file"); + goto error; + } + + /* Convert the packet's bound to nanoseconds since Epoch. */ + ret = convert_cycles_to_ns(timestamp_begin_cc, + index_entry->timestamp_begin, + &index_entry->timestamp_begin_ns); + if (ret) { + goto error; + } + ret = convert_cycles_to_ns(timestamp_end_cc, + index_entry->timestamp_end, + &index_entry->timestamp_end_ns); + if (ret) { + goto error; } total_packets_size += packet_size; file_pos += file_index_entry_size; - index++; + index_entry++; } /* Validate that the index addresses the complete stream. */ if (ds_file->file->size != total_packets_size) { - printf_error("Invalid index; indexed size != stream file size"); - ret = -1; - goto invalid_index; + BT_LOGW("Invalid index; indexed size != stream file size"); + goto error; } end: g_free(directory); @@ -334,47 +489,29 @@ end: if (mapped_file) { g_mapped_file_unref(mapped_file); } - return ret; -invalid_index: - g_array_free(ds_file->index.entries, TRUE); + bt_put(timestamp_begin_cc); + bt_put(timestamp_end_cc); + return index; +error: + ctf_fs_ds_index_destroy(index); + index = NULL; goto end; } -static -int build_index_from_data_stream_file(struct ctf_fs_ds_file *stream) -{ - return 0; -} - -static -int init_stream_index(struct ctf_fs_ds_file *ds_file) -{ - int ret; - - ret = build_index_from_idx_file(ds_file); - if (!ret) { - goto end; - } - - ret = build_index_from_data_stream_file(ds_file); -end: - return ret; -} - BT_HIDDEN struct ctf_fs_ds_file *ctf_fs_ds_file_create( struct ctf_fs_trace *ctf_fs_trace, - struct bt_ctf_stream *stream, const char *path, - bool build_index) + struct bt_ctf_stream *stream, const char *path) { int ret; + const size_t page_size = bt_common_get_page_size(); struct ctf_fs_ds_file *ds_file = g_new0(struct ctf_fs_ds_file, 1); if (!ds_file) { goto error; } - ds_file->file = ctf_fs_file_create(ctf_fs_trace->ctf_fs); + ds_file->file = ctf_fs_file_create(); if (!ds_file->file) { goto error; } @@ -382,27 +519,18 @@ struct ctf_fs_ds_file *ctf_fs_ds_file_create( ds_file->stream = bt_get(stream); ds_file->cc_prio_map = bt_get(ctf_fs_trace->cc_prio_map); g_string_assign(ds_file->file->path, path); - ret = ctf_fs_file_open(ctf_fs_trace->ctf_fs, ds_file->file, "rb"); + ret = ctf_fs_file_open(ds_file->file, "rb"); if (ret) { goto error; } ds_file->notif_iter = bt_ctf_notif_iter_create( - ctf_fs_trace->metadata->trace, - ctf_fs_trace->ctf_fs->page_size, medops, ds_file, - ctf_fs_trace->ctf_fs->error_fp); + ctf_fs_trace->metadata->trace, page_size, medops, ds_file); if (!ds_file->notif_iter) { goto error; } - ds_file->mmap_max_len = ctf_fs_trace->ctf_fs->page_size * 2048; - - if (build_index) { - ret = init_stream_index(ds_file); - if (ret) { - goto error; - } - } + ds_file->mmap_max_len = page_size * 2048; goto end; @@ -415,6 +543,13 @@ end: return ds_file; } +BT_HIDDEN +struct ctf_fs_ds_index *ctf_fs_ds_file_build_index( + struct ctf_fs_ds_file *ds_file) +{ + return build_index_from_idx_file(ds_file); +} + BT_HIDDEN void ctf_fs_ds_file_destroy(struct ctf_fs_ds_file *ds_file) { @@ -434,10 +569,6 @@ void ctf_fs_ds_file_destroy(struct ctf_fs_ds_file *ds_file) bt_ctf_notif_iter_destroy(ds_file->notif_iter); } - if (ds_file->index.entries) { - g_array_free(ds_file->index.entries, TRUE); - } - g_free(ds_file); } @@ -480,19 +611,14 @@ struct bt_notification_iterator_next_return ctf_fs_ds_file_next( BT_HIDDEN int ctf_fs_ds_file_get_packet_header_context_fields( - struct ctf_fs_trace *ctf_fs_trace, const char *path, + struct ctf_fs_ds_file *ds_file, struct bt_ctf_field **packet_header_field, struct bt_ctf_field **packet_context_field) { enum bt_ctf_notif_iter_status notif_iter_status; - struct ctf_fs_ds_file *ds_file; int ret = 0; - ds_file = ctf_fs_ds_file_create(ctf_fs_trace, NULL, path, false); - if (!ds_file) { - goto error; - } - + assert(ds_file); notif_iter_status = bt_ctf_notif_iter_get_packet_header_context_fields( ds_file->notif_iter, packet_header_field, packet_context_field); switch (notif_iter_status) { @@ -522,6 +648,18 @@ error: } end: - ctf_fs_ds_file_destroy(ds_file); return ret; } + +BT_HIDDEN +void ctf_fs_ds_index_destroy(struct ctf_fs_ds_index *index) +{ + if (!index) { + return; + } + + if (index->entries) { + g_array_free(index->entries, TRUE); + } + g_free(index); +}