X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=src%2Fplugins%2Fctf%2Ffs-src%2Ffs.c;h=42956c22bf9fb38ed40299727c815f429175bcd0;hp=64fff672705f68ee4e2304c5739ab392a8721745;hb=0235b0db7de5bcacdb3650c92461f2ce5eb2143d;hpb=1505f33a1a42c691890dff61aea9762b43d1bca2 diff --git a/src/plugins/ctf/fs-src/fs.c b/src/plugins/ctf/fs-src/fs.c index 64fff672..42956c22 100644 --- a/src/plugins/ctf/fs-src/fs.c +++ b/src/plugins/ctf/fs-src/fs.c @@ -1,28 +1,10 @@ /* - * fs.c - * - * Babeltrace CTF file system Reader Component + * SPDX-License-Identifier: MIT * * Copyright 2015-2017 Philippe Proulx * Copyright 2016 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. + * Babeltrace CTF file system Reader Component */ #define BT_COMP_LOG_SELF_COMP self_comp @@ -54,33 +36,6 @@ struct tracer_info { int64_t patch; }; -static -int msg_iter_data_set_current_ds_file(struct ctf_fs_msg_iter_data *msg_iter_data) -{ - struct ctf_fs_ds_file_info *ds_file_info; - int ret = 0; - - BT_ASSERT(msg_iter_data->ds_file_info_index < - msg_iter_data->ds_file_group->ds_file_infos->len); - ds_file_info = g_ptr_array_index( - msg_iter_data->ds_file_group->ds_file_infos, - msg_iter_data->ds_file_info_index); - - ctf_fs_ds_file_destroy(msg_iter_data->ds_file); - msg_iter_data->ds_file = ctf_fs_ds_file_create( - msg_iter_data->ds_file_group->ctf_fs_trace, - msg_iter_data->self_msg_iter, - msg_iter_data->msg_iter, - msg_iter_data->ds_file_group->stream, - ds_file_info->path->str, - msg_iter_data->log_level); - if (!msg_iter_data->ds_file) { - ret = -1; - } - - return ret; -} - static void ctf_fs_msg_iter_data_destroy( struct ctf_fs_msg_iter_data *msg_iter_data) @@ -89,91 +44,74 @@ void ctf_fs_msg_iter_data_destroy( return; } - ctf_fs_ds_file_destroy(msg_iter_data->ds_file); - if (msg_iter_data->msg_iter) { ctf_msg_iter_destroy(msg_iter_data->msg_iter); } - g_free(msg_iter_data); -} + if (msg_iter_data->msg_iter_medops_data) { + ctf_fs_ds_group_medops_data_destroy( + msg_iter_data->msg_iter_medops_data); + } -static -void set_msg_iter_emits_stream_beginning_end_messages( - struct ctf_fs_msg_iter_data *msg_iter_data) -{ - ctf_msg_iter_set_emit_stream_beginning_message( - msg_iter_data->ds_file->msg_iter, - msg_iter_data->ds_file_info_index == 0); - ctf_msg_iter_set_emit_stream_end_message( - msg_iter_data->ds_file->msg_iter, - msg_iter_data->ds_file_info_index == - msg_iter_data->ds_file_group->ds_file_infos->len - 1); + g_free(msg_iter_data); } static -bt_component_class_message_iterator_next_method_status ctf_fs_iterator_next_one( +bt_message_iterator_class_next_method_status ctf_fs_iterator_next_one( struct ctf_fs_msg_iter_data *msg_iter_data, const bt_message **out_msg) { - bt_component_class_message_iterator_next_method_status status; + bt_message_iterator_class_next_method_status status; + enum ctf_msg_iter_status msg_iter_status; + bt_logging_level log_level = msg_iter_data->log_level; - BT_ASSERT_DBG(msg_iter_data->ds_file); + msg_iter_status = ctf_msg_iter_get_next_message( + msg_iter_data->msg_iter, out_msg); - while (true) { - bt_message *msg; + switch (msg_iter_status) { + case CTF_MSG_ITER_STATUS_OK: + /* Cool, message has been written to *out_msg. */ + status = BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK; + break; - status = ctf_fs_ds_file_next(msg_iter_data->ds_file, &msg); - switch (status) { - case BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK: - *out_msg = msg; - msg = NULL; - goto end; - case BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_END: - { - int ret; + case CTF_MSG_ITER_STATUS_EOF: + status = BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_END; + break; - if (msg_iter_data->ds_file_info_index == - msg_iter_data->ds_file_group->ds_file_infos->len - 1) { - /* End of all group's stream files */ - goto end; - } + case CTF_MSG_ITER_STATUS_AGAIN: + /* + * Should not make it this far as this is + * medium-specific; there is nothing for the user to do + * and it should have been handled upstream. + */ + bt_common_abort(); - msg_iter_data->ds_file_info_index++; - ctf_msg_iter_reset_for_next_stream_file( - msg_iter_data->msg_iter); - set_msg_iter_emits_stream_beginning_end_messages( - msg_iter_data); + case CTF_MSG_ITER_MEDIUM_STATUS_ERROR: + BT_MSG_ITER_LOGE_APPEND_CAUSE(msg_iter_data->self_msg_iter, + "Failed to get next message from CTF message iterator."); + status = BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR; + break; - /* - * Open and start reading the next stream file - * within our stream file group. - */ - ret = msg_iter_data_set_current_ds_file(msg_iter_data); - if (ret) { - status = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_ERROR; - goto end; - } + case CTF_MSG_ITER_MEDIUM_STATUS_MEMORY_ERROR: + BT_MSG_ITER_LOGE_APPEND_CAUSE(msg_iter_data->self_msg_iter, + "Failed to get next message from CTF message iterator."); + status = BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_MEMORY_ERROR; + break; - /* Continue the loop to get the next message */ - break; - } - default: - goto end; - } + default: + bt_common_abort(); } -end: return status; } BT_HIDDEN -bt_component_class_message_iterator_next_method_status ctf_fs_iterator_next( +bt_message_iterator_class_next_method_status ctf_fs_iterator_next( bt_self_message_iterator *iterator, bt_message_array_const msgs, uint64_t capacity, uint64_t *count) { - bt_component_class_message_iterator_next_method_status status; + bt_message_iterator_class_next_method_status status; struct ctf_fs_msg_iter_data *msg_iter_data = bt_self_message_iterator_get_data(iterator); uint64_t i = 0; @@ -191,19 +129,19 @@ bt_component_class_message_iterator_next_method_status ctf_fs_iterator_next( do { status = ctf_fs_iterator_next_one(msg_iter_data, &msgs[i]); - if (status == BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK) { + if (status == BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK) { i++; } } while (i < capacity && - status == BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK); + status == BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK); if (i > 0) { /* * Even if ctf_fs_iterator_next_one() returned something - * else than BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK, we + * else than BT_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK, we * accumulated message objects in the output * message array, so we need to return - * BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK so that they are + * BT_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK so that they are * transfered to downstream. This other status occurs * again the next time muxer_msg_iter_do_next() is * called, possibly without any accumulated @@ -222,46 +160,26 @@ bt_component_class_message_iterator_next_method_status ctf_fs_iterator_next( } *count = i; - status = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK; + status = BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK; } end: return status; } -static -int ctf_fs_iterator_reset(struct ctf_fs_msg_iter_data *msg_iter_data) -{ - int ret; - - msg_iter_data->ds_file_info_index = 0; - ret = msg_iter_data_set_current_ds_file(msg_iter_data); - if (ret) { - goto end; - } - - ctf_msg_iter_reset(msg_iter_data->msg_iter); - set_msg_iter_emits_stream_beginning_end_messages(msg_iter_data); - -end: - return ret; -} - BT_HIDDEN -bt_component_class_message_iterator_seek_beginning_method_status +bt_message_iterator_class_seek_beginning_method_status ctf_fs_iterator_seek_beginning(bt_self_message_iterator *it) { struct ctf_fs_msg_iter_data *msg_iter_data = bt_self_message_iterator_get_data(it); - bt_component_class_message_iterator_seek_beginning_method_status status = - BT_COMPONENT_CLASS_MESSAGE_ITERATOR_SEEK_BEGINNING_METHOD_STATUS_OK; BT_ASSERT(msg_iter_data); - if (ctf_fs_iterator_reset(msg_iter_data)) { - status = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_SEEK_BEGINNING_METHOD_STATUS_ERROR; - } - return status; + ctf_msg_iter_reset(msg_iter_data->msg_iter); + ctf_fs_ds_group_medops_data_reset(msg_iter_data->msg_iter_medops_data); + + return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_OK; } BT_HIDDEN @@ -272,19 +190,18 @@ void ctf_fs_iterator_finalize(bt_self_message_iterator *it) } BT_HIDDEN -bt_component_class_message_iterator_initialize_method_status ctf_fs_iterator_init( +bt_message_iterator_class_initialize_method_status ctf_fs_iterator_init( bt_self_message_iterator *self_msg_iter, bt_self_message_iterator_configuration *config, - bt_self_component_source *self_comp_src, bt_self_component_port_output *self_port) { struct ctf_fs_port_data *port_data; struct ctf_fs_msg_iter_data *msg_iter_data = NULL; - bt_component_class_message_iterator_initialize_method_status ret = - BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_OK; + bt_message_iterator_class_initialize_method_status status; bt_logging_level log_level; + enum ctf_msg_iter_medium_status medium_status; bt_self_component *self_comp = - bt_self_component_source_as_self_component(self_comp_src); + bt_self_message_iterator_borrow_component(self_msg_iter); port_data = bt_self_component_port_get_data( bt_self_component_port_output_as_self_component_port( @@ -293,27 +210,39 @@ bt_component_class_message_iterator_initialize_method_status ctf_fs_iterator_ini log_level = port_data->ctf_fs->log_level; msg_iter_data = g_new0(struct ctf_fs_msg_iter_data, 1); if (!msg_iter_data) { - ret = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_MEMORY_ERROR; + status = BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR; goto error; } msg_iter_data->log_level = log_level; msg_iter_data->self_comp = self_comp; msg_iter_data->self_msg_iter = self_msg_iter; + msg_iter_data->ds_file_group = port_data->ds_file_group; + + medium_status = ctf_fs_ds_group_medops_data_create( + msg_iter_data->ds_file_group, self_msg_iter, log_level, + &msg_iter_data->msg_iter_medops_data); + BT_ASSERT( + medium_status == CTF_MSG_ITER_MEDIUM_STATUS_OK || + medium_status == CTF_MSG_ITER_MEDIUM_STATUS_ERROR || + medium_status == CTF_MSG_ITER_MEDIUM_STATUS_MEMORY_ERROR); + if (medium_status != CTF_MSG_ITER_MEDIUM_STATUS_OK) { + BT_MSG_ITER_LOGE_APPEND_CAUSE(self_msg_iter, + "Failed to create ctf_fs_ds_group_medops"); + status = (int) medium_status; + goto error; + } + msg_iter_data->msg_iter = ctf_msg_iter_create( - port_data->ds_file_group->ctf_fs_trace->metadata->tc, + msg_iter_data->ds_file_group->ctf_fs_trace->metadata->tc, bt_common_get_page_size(msg_iter_data->log_level) * 8, - ctf_fs_ds_file_medops, NULL, msg_iter_data->log_level, + ctf_fs_ds_group_medops, + msg_iter_data->msg_iter_medops_data, + msg_iter_data->log_level, self_comp, self_msg_iter); if (!msg_iter_data->msg_iter) { BT_COMP_LOGE_APPEND_CAUSE(self_comp, "Cannot create a CTF message iterator."); - ret = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_MEMORY_ERROR; - goto error; - } - - msg_iter_data->ds_file_group = port_data->ds_file_group; - if (ctf_fs_iterator_reset(msg_iter_data)) { - ret = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_ERROR; + status = BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR; goto error; } @@ -328,10 +257,9 @@ bt_component_class_message_iterator_initialize_method_status ctf_fs_iterator_ini bt_self_message_iterator_set_data(self_msg_iter, msg_iter_data); - if (ret != BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_OK) { - goto error; - } msg_iter_data = NULL; + + status = BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_OK; goto end; error: @@ -339,7 +267,7 @@ error: end: ctf_fs_msg_iter_data_destroy(msg_iter_data); - return ret; + return status; } static @@ -607,12 +535,7 @@ void ctf_fs_ds_file_group_destroy(struct ctf_fs_ds_file_group *ds_file_group) g_ptr_array_free(ds_file_group->ds_file_infos, TRUE); } - if (ds_file_group->index) { - if (ds_file_group->index->entries) { - g_ptr_array_free(ds_file_group->index->entries, TRUE); - } - g_free(ds_file_group->index); - } + ctf_fs_ds_index_destroy(ds_file_group->index); bt_stream_put_ref(ds_file_group->stream); g_free(ds_file_group); @@ -739,7 +662,7 @@ void ds_index_insert_ds_index_entry_sorted( struct ctf_fs_ds_index_entry *entry) { guint i; - struct ctf_fs_ds_index_entry *other_entry; + struct ctf_fs_ds_index_entry *other_entry = NULL; /* Find the spot where to insert this index entry. */ for (i = 0; i < index->entries->len; i++) { @@ -803,21 +726,28 @@ int add_ds_file_to_ds_file_group(struct ctf_fs_trace *ctf_fs_trace, bt_self_component *self_comp = ctf_fs_trace->self_comp; bt_self_component_class *self_comp_class = ctf_fs_trace->self_comp_class; + /* + * Create a temporary ds_file to read some properties about the data + * stream file. + */ + ds_file = ctf_fs_ds_file_create(ctf_fs_trace, NULL, NULL, path, + log_level); + if (!ds_file) { + goto error; + } + + /* Create a temporary iterator to read the ds_file. */ msg_iter = ctf_msg_iter_create(ctf_fs_trace->metadata->tc, bt_common_get_page_size(log_level) * 8, - ctf_fs_ds_file_medops, NULL, log_level, self_comp, NULL); + ctf_fs_ds_file_medops, ds_file, log_level, self_comp, NULL); if (!msg_iter) { BT_COMP_LOGE_STR("Cannot create a CTF message iterator."); goto error; } - ds_file = ctf_fs_ds_file_create(ctf_fs_trace, NULL, msg_iter, - NULL, path, log_level); - if (!ds_file) { - goto error; - } + ctf_msg_iter_set_dry_run(msg_iter, true); - ret = ctf_msg_iter_get_packet_properties(ds_file->msg_iter, &props); + ret = ctf_msg_iter_get_packet_properties(msg_iter, &props); if (ret) { BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, self_comp_class, "Cannot get stream file's first packet's header and context fields (`%s`).", @@ -850,7 +780,7 @@ int add_ds_file_to_ds_file_group(struct ctf_fs_trace *ctf_fs_trace, goto error; } - index = ctf_fs_ds_file_build_index(ds_file, ds_file_info); + index = ctf_fs_ds_file_build_index(ds_file, ds_file_info, msg_iter); if (!index) { BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( self_comp, self_comp_class, @@ -861,7 +791,7 @@ int add_ds_file_to_ds_file_group(struct ctf_fs_trace *ctf_fs_trace, if (begin_ns == -1) { /* - * No beggining timestamp to sort the stream files + * No beginning timestamp to sort the stream files * within a stream file group, so consider that this * file must be the only one within its group. */ @@ -1504,29 +1434,29 @@ int decode_clock_snapshot_after_event(struct ctf_fs_trace *ctf_fs_trace, int ret = 0; BT_ASSERT(ctf_fs_trace); + BT_ASSERT(index_entry); + BT_ASSERT(index_entry->path); + + ds_file = ctf_fs_ds_file_create(ctf_fs_trace, NULL, + NULL, index_entry->path, log_level); + if (!ds_file) { + BT_COMP_LOGE_APPEND_CAUSE(self_comp, "Failed to create a ctf_fs_ds_file"); + ret = -1; + goto end; + } + BT_ASSERT(ctf_fs_trace->metadata); BT_ASSERT(ctf_fs_trace->metadata->tc); msg_iter = ctf_msg_iter_create(ctf_fs_trace->metadata->tc, bt_common_get_page_size(log_level) * 8, ctf_fs_ds_file_medops, - NULL, log_level, self_comp, NULL); + ds_file, log_level, self_comp, NULL); if (!msg_iter) { /* ctf_msg_iter_create() logs errors. */ ret = -1; goto end; } - BT_ASSERT(index_entry); - BT_ASSERT(index_entry->path); - - ds_file = ctf_fs_ds_file_create(ctf_fs_trace, NULL, msg_iter, - NULL, index_entry->path, log_level); - if (!ds_file) { - BT_COMP_LOGE_APPEND_CAUSE(self_comp, "Failed to create a ctf_fs_ds_file"); - ret = -1; - goto end; - } - /* * Turn on dry run mode to prevent the creation and usage of Babeltrace * library objects (bt_field, bt_message_*, etc.). @@ -1534,7 +1464,7 @@ int decode_clock_snapshot_after_event(struct ctf_fs_trace *ctf_fs_trace, ctf_msg_iter_set_dry_run(msg_iter, true); /* Seek to the beginning of the target packet. */ - iter_status = ctf_msg_iter_seek(ds_file->msg_iter, index_entry->offset); + iter_status = ctf_msg_iter_seek(msg_iter, index_entry->offset); if (iter_status) { /* ctf_msg_iter_seek() logs errors. */ ret = -1; @@ -1549,12 +1479,12 @@ int decode_clock_snapshot_after_event(struct ctf_fs_trace *ctf_fs_trace, * snapshot. */ iter_status = ctf_msg_iter_curr_packet_first_event_clock_snapshot( - ds_file->msg_iter, cs); + msg_iter, cs); break; case LAST_EVENT: /* Decode the packet to extract the last event's clock snapshot. */ iter_status = ctf_msg_iter_curr_packet_last_event_clock_snapshot( - ds_file->msg_iter, cs); + msg_iter, cs); break; default: bt_common_abort(); @@ -2096,6 +2026,15 @@ gint compare_ds_file_groups_by_first_path(gconstpointer a, gconstpointer b) first_ds_file_info_b->path->str); } +static +gint compare_strings(gconstpointer p_a, gconstpointer p_b) +{ + const char *a = *((const char **) p_a); + const char *b = *((const char **) p_b); + + return strcmp(a, b); +} + int ctf_fs_component_create_ctf_fs_trace( struct ctf_fs_component *ctf_fs, const bt_value *paths_value, @@ -2106,6 +2045,7 @@ int ctf_fs_component_create_ctf_fs_trace( int ret = 0; uint64_t i; bt_logging_level log_level = ctf_fs->log_level; + GPtrArray *paths = NULL; GPtrArray *traces; const char *trace_name; @@ -2119,15 +2059,43 @@ int ctf_fs_component_create_ctf_fs_trace( goto error; } + paths = g_ptr_array_new_with_free_func(g_free); + if (!paths) { + BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, self_comp_class, + "Failed to allocate a GPtrArray."); + goto error; + } + trace_name = trace_name_value ? bt_value_string_get(trace_name_value) : NULL; - /* Start by creating a separate ctf_fs_trace object for each path. */ + /* + * Create a sorted array of the paths, to make the execution of this + * component deterministic. + */ for (i = 0; i < bt_value_array_get_length(paths_value); i++) { - const bt_value *path_value = bt_value_array_borrow_element_by_index_const(paths_value, i); + const bt_value *path_value = + bt_value_array_borrow_element_by_index_const(paths_value, i); const char *input = bt_value_string_get(path_value); + gchar *input_copy; + + input_copy = g_strdup(input); + if (!input_copy) { + BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, self_comp_class, + "Failed to copy a string."); + goto error; + } + + g_ptr_array_add(paths, input_copy); + } + + g_ptr_array_sort(paths, compare_strings); + + /* Create a separate ctf_fs_trace object for each path. */ + for (i = 0; i < paths->len; i++) { + const char *path = g_ptr_array_index(paths, i); ret = ctf_fs_component_create_ctf_fs_trace_one_path(ctf_fs, - input, trace_name, traces, self_comp, self_comp_class); + path, trace_name, traces, self_comp, self_comp_class); if (ret) { goto end; } @@ -2211,7 +2179,14 @@ error: ret = -1; end: - g_ptr_array_free(traces, TRUE); + if (traces) { + g_ptr_array_free(traces, TRUE); + } + + if (paths) { + g_ptr_array_free(paths, TRUE); + } + return ret; }