X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Fplugins%2Fctf%2Ffs-src%2Ffs.c;h=1f4ea64b920d7761aa8fd69b5e10bf96ce4b287a;hb=b7d2695ae888cafb25084b2feaa4a770b3a540cd;hp=65d62f96e3b2fdbe117fb8c597a19b4be608c287;hpb=a0cd55adbf4e2cf50e153f96916c099dc9ff2399;p=babeltrace.git diff --git a/src/plugins/ctf/fs-src/fs.c b/src/plugins/ctf/fs-src/fs.c index 65d62f96..1f4ea64b 100644 --- a/src/plugins/ctf/fs-src/fs.c +++ b/src/plugins/ctf/fs-src/fs.c @@ -45,6 +45,7 @@ #include "../common/metadata/ctf-meta-configure-ir-trace.h" #include "../common/msg-iter/msg-iter.h" #include "query.h" +#include "plugins/common/param-validation/param-validation.h" struct tracer_info { const char *name; @@ -248,15 +249,16 @@ void ctf_fs_iterator_finalize(bt_self_message_iterator *it) } BT_HIDDEN -bt_component_class_message_iterator_init_method_status ctf_fs_iterator_init( +bt_component_class_message_iterator_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_init_method_status ret = - BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INIT_METHOD_STATUS_OK; + bt_component_class_message_iterator_initialize_method_status ret = + BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_OK; bt_logging_level log_level; bt_self_component *self_comp = bt_self_component_source_as_self_component(self_comp_src); @@ -268,7 +270,7 @@ bt_component_class_message_iterator_init_method_status ctf_fs_iterator_init( 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_INIT_METHOD_STATUS_MEMORY_ERROR; + ret = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_MEMORY_ERROR; goto error; } @@ -282,22 +284,30 @@ bt_component_class_message_iterator_init_method_status ctf_fs_iterator_init( self_comp); 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_INIT_METHOD_STATUS_MEMORY_ERROR; + 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_INIT_METHOD_STATUS_ERROR; + ret = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_ERROR; goto error; } + /* + * This iterator can seek forward if its stream class has a default + * clock class. + */ + if (msg_iter_data->ds_file_group->sc->default_clock_class) { + bt_self_message_iterator_configuration_set_can_seek_forward( + config, true); + } + bt_self_message_iterator_set_data(self_msg_iter, msg_iter_data); - if (ret != BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INIT_METHOD_STATUS_OK) { + if (ret != BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_OK) { goto error; } - msg_iter_data = NULL; goto end; @@ -705,6 +715,7 @@ int add_ds_file_to_ds_file_group(struct ctf_fs_trace *ctf_fs_trace, struct bt_msg_iter_packet_properties props; bt_logging_level log_level = ctf_fs_trace->log_level; bt_self_component *self_comp = ctf_fs_trace->self_comp; + bt_self_component_class *self_comp_class = ctf_fs_trace->self_comp_class; msg_iter = bt_msg_iter_create(ctf_fs_trace->metadata->tc, bt_common_get_page_size(log_level) * 8, @@ -722,7 +733,7 @@ int add_ds_file_to_ds_file_group(struct ctf_fs_trace *ctf_fs_trace, ret = bt_msg_iter_get_packet_properties(ds_file->msg_iter, &props); if (ret) { - BT_COMP_LOGE_APPEND_CAUSE(self_comp, + 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`).", path); goto error; @@ -741,7 +752,7 @@ int add_ds_file_to_ds_file_group(struct ctf_fs_trace *ctf_fs_trace, sc->default_clock_class->offset_seconds, sc->default_clock_class->offset_cycles, &begin_ns); if (ret) { - BT_COMP_LOGE_APPEND_CAUSE(self_comp, + BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, self_comp_class, "Cannot convert clock cycles to nanoseconds from origin (`%s`).", path); goto error; @@ -853,11 +864,13 @@ int create_ds_file_groups(struct ctf_fs_trace *ctf_fs_trace) GDir *dir = NULL; bt_logging_level log_level = ctf_fs_trace->log_level; bt_self_component *self_comp = ctf_fs_trace->self_comp; + bt_self_component_class *self_comp_class = ctf_fs_trace->self_comp_class; /* Check each file in the path directory, except specific ones */ dir = g_dir_open(ctf_fs_trace->path->str, 0, &error); if (!dir) { - BT_COMP_LOGE_APPEND_CAUSE(self_comp, "Cannot open directory `%s`: %s (code %d)", + BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, self_comp_class, + "Cannot open directory `%s`: %s (code %d)", ctf_fs_trace->path->str, error->message, error->code); goto error; @@ -882,7 +895,7 @@ int create_ds_file_groups(struct ctf_fs_trace *ctf_fs_trace) /* Create the file. */ file = ctf_fs_file_create(log_level, self_comp); if (!file) { - BT_COMP_LOGE_APPEND_CAUSE(self_comp, + BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, self_comp_class, "Cannot create stream file object for file `%s" G_DIR_SEPARATOR_S "%s`", ctf_fs_trace->path->str, basename); goto error; @@ -901,7 +914,8 @@ int create_ds_file_groups(struct ctf_fs_trace *ctf_fs_trace) ret = ctf_fs_file_open(file, "rb"); if (ret) { - BT_COMP_LOGE_APPEND_CAUSE(self_comp, "Cannot open stream file `%s`", + BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, self_comp_class, + "Cannot open stream file `%s`", file->path->str); goto error; } @@ -916,7 +930,7 @@ int create_ds_file_groups(struct ctf_fs_trace *ctf_fs_trace) ret = add_ds_file_to_ds_file_group(ctf_fs_trace, file->path->str); if (ret) { - BT_COMP_LOGE_APPEND_CAUSE(self_comp, + BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, self_comp_class, "Cannot add stream file `%s` to stream file group", file->path->str); ctf_fs_file_destroy(file); @@ -993,7 +1007,9 @@ end: } static -struct ctf_fs_trace *ctf_fs_trace_create(bt_self_component *self_comp, +struct ctf_fs_trace *ctf_fs_trace_create( + bt_self_component *self_comp, + bt_self_component_class *self_comp_class, const char *path, const char *name, struct ctf_fs_metadata_config *metadata_config, bt_logging_level log_level) @@ -1001,6 +1017,9 @@ struct ctf_fs_trace *ctf_fs_trace_create(bt_self_component *self_comp, struct ctf_fs_trace *ctf_fs_trace; int ret; + /* Only one of them must be set. */ + BT_ASSERT(!self_comp != !self_comp_class); + ctf_fs_trace = g_new0(struct ctf_fs_trace, 1); if (!ctf_fs_trace) { goto end; @@ -1008,6 +1027,7 @@ struct ctf_fs_trace *ctf_fs_trace_create(bt_self_component *self_comp, ctf_fs_trace->log_level = log_level; ctf_fs_trace->self_comp = self_comp; + ctf_fs_trace->self_comp_class = self_comp_class; ctf_fs_trace->path = g_string_new(path); if (!ctf_fs_trace->path) { goto error; @@ -1097,6 +1117,7 @@ static int ctf_fs_component_create_ctf_fs_trace_one_path( struct ctf_fs_component *ctf_fs, const char *path_param, + const char *trace_name, GPtrArray *traces, bt_self_component *self_comp, bt_self_component_class *self_comp_class) @@ -1109,18 +1130,21 @@ int ctf_fs_component_create_ctf_fs_trace_one_path( norm_path = bt_common_normalize_path(path_param, NULL); if (!norm_path) { BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, self_comp_class, - "Failed to normalize path: `%s`.", path_param); + "Failed to normalize path: `%s`.", + path_param); goto error; } ret = path_is_ctf_trace(norm_path->str); if (ret < 0) { BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, self_comp_class, - "Failed to check if path is a CTF trace: path=%s", norm_path->str); + "Failed to check if path is a CTF trace: path=%s", + norm_path->str); goto error; } else if (ret == 0) { BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, self_comp_class, - "Path is not a CTF trace (does not contain a metadata file): `%s`.", norm_path->str); + "Path is not a CTF trace (does not contain a metadata file): `%s`.", + norm_path->str); goto error; } @@ -1132,10 +1156,11 @@ int ctf_fs_component_create_ctf_fs_trace_one_path( goto end; } - ctf_fs_trace = ctf_fs_trace_create(self_comp, norm_path->str, - norm_path->str, &ctf_fs->metadata_config, log_level); + ctf_fs_trace = ctf_fs_trace_create(self_comp, self_comp_class, norm_path->str, + trace_name, &ctf_fs->metadata_config, log_level); if (!ctf_fs_trace) { - BT_COMP_LOGE_APPEND_CAUSE(self_comp, "Cannot create trace for `%s`.", + BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, self_comp_class, + "Cannot create trace for `%s`.", norm_path->str); goto error; } @@ -1908,7 +1933,8 @@ bool is_tracer_affected_by_lttng_crash_quirk( */ static int fix_packet_index_tracer_bugs(struct ctf_fs_component *ctf_fs, - bt_self_component *self_comp) + bt_self_component *self_comp, + bt_self_component_class *self_comp_class) { int ret = 0; struct tracer_info current_tracer_info; @@ -1934,7 +1960,8 @@ int fix_packet_index_tracer_bugs(struct ctf_fs_component *ctf_fs, BT_LOGI_STR("Trace may be affected by LTTng tracer packet timestamp bug. Fixing up."); ret = fix_index_lttng_event_after_packet_bug(ctf_fs->trace); if (ret) { - BT_COMP_LOGE_APPEND_CAUSE(self_comp, + BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + self_comp, self_comp_class, "Failed to fix LTTng event-after-packet bug."); goto end; } @@ -1946,7 +1973,8 @@ int fix_packet_index_tracer_bugs(struct ctf_fs_component *ctf_fs, BT_LOGI_STR("Trace may be affected by barectf tracer packet timestamp bug. Fixing up."); ret = fix_index_barectf_event_before_packet_bug(ctf_fs->trace); if (ret) { - BT_COMP_LOGE_APPEND_CAUSE(self_comp, + BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + self_comp, self_comp_class, "Failed to fix barectf event-before-packet bug."); goto end; } @@ -1957,7 +1985,8 @@ int fix_packet_index_tracer_bugs(struct ctf_fs_component *ctf_fs, ¤t_tracer_info)) { ret = fix_index_lttng_crash_quirk(ctf_fs->trace); if (ret) { - BT_COMP_LOGE_APPEND_CAUSE(self_comp, + BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + self_comp, self_comp_class, "Failed to fix lttng-crash timestamp quirks."); goto end; } @@ -1968,9 +1997,26 @@ end: return ret; } +static +gint compare_ds_file_groups_by_first_path(gconstpointer a, gconstpointer b) +{ + struct ctf_fs_ds_file_group * const *ds_file_group_a = a; + struct ctf_fs_ds_file_group * const *ds_file_group_b = b; + const struct ctf_fs_ds_file_info *first_ds_file_info_a; + const struct ctf_fs_ds_file_info *first_ds_file_info_b; + + BT_ASSERT((*ds_file_group_a)->ds_file_infos->len > 0); + BT_ASSERT((*ds_file_group_b)->ds_file_infos->len > 0); + first_ds_file_info_a = (*ds_file_group_a)->ds_file_infos->pdata[0]; + first_ds_file_info_b = (*ds_file_group_b)->ds_file_infos->pdata[0]; + return strcmp(first_ds_file_info_a->path->str, + first_ds_file_info_b->path->str); +} + int ctf_fs_component_create_ctf_fs_trace( struct ctf_fs_component *ctf_fs, const bt_value *paths_value, + const bt_value *trace_name_value, bt_self_component *self_comp, bt_self_component_class *self_comp_class) { @@ -1978,6 +2024,7 @@ int ctf_fs_component_create_ctf_fs_trace( uint64_t i; bt_logging_level log_level = ctf_fs->log_level; GPtrArray *traces; + const char *trace_name; BT_ASSERT(bt_value_get_type(paths_value) == BT_VALUE_TYPE_ARRAY); BT_ASSERT(!bt_value_array_is_empty(paths_value)); @@ -1989,13 +2036,15 @@ int ctf_fs_component_create_ctf_fs_trace( 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. */ 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 char *input = bt_value_string_get(path_value); ret = ctf_fs_component_create_ctf_fs_trace_one_path(ctf_fs, - input, traces, self_comp, self_comp_class); + input, trace_name, traces, self_comp, self_comp_class); if (ret) { goto end; } @@ -2054,12 +2103,26 @@ int ctf_fs_component_create_ctf_fs_trace( traces->pdata[0] = NULL; } - ret = fix_packet_index_tracer_bugs(ctf_fs, self_comp); + ret = fix_packet_index_tracer_bugs(ctf_fs, self_comp, self_comp_class); if (ret) { BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, self_comp_class, "Failed to fix packet index tracer bugs."); } + /* + * Sort data stream file groups by first data stream file info + * path to get a deterministic order. This order influences the + * order of the output ports. It also influences the order of + * the automatic stream IDs if the trace's packet headers do not + * contain a `stream_instance_id` field, in which case the data + * stream file to stream ID association is always the same, + * whatever the build and the system. + * + * Having a deterministic order here can help debugging and + * testing. + */ + g_ptr_array_sort(ctf_fs->trace->ds_file_groups, + compare_ds_file_groups_by_first_path); goto end; error: ret = -1; @@ -2170,87 +2233,55 @@ end: return ret; } -/* - * Validate the "paths" parameter passed to this component. It must be - * present, and it must be an array of strings. - */ - -static -bool validate_inputs_parameter(struct ctf_fs_component *ctf_fs, - const bt_value *inputs, bt_self_component *self_comp, - bt_self_component_class *self_comp_class) -{ - bool ret; - bt_value_type type; - uint64_t i; - bt_logging_level log_level = ctf_fs->log_level; - - if (!inputs) { - BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, - self_comp_class, "missing \"inputs\" parameter"); - goto error; - } - - type = bt_value_get_type(inputs); - if (type != BT_VALUE_TYPE_ARRAY) { - BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, - self_comp_class, "`inputs` parameter: expecting array value: type=%s", - bt_common_value_type_string(type)); - goto error; - } - - if (bt_value_array_is_empty(inputs)) { - BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, - self_comp_class, "`inputs` parameter must not be empty"); - goto error; - } - - for (i = 0; i < bt_value_array_get_length(inputs); i++) { - const bt_value *elem; +static const struct bt_param_validation_value_descr inputs_elem_descr = { + .type = BT_VALUE_TYPE_STRING, +}; - elem = bt_value_array_borrow_element_by_index_const(inputs, i); - type = bt_value_get_type(elem); - if (type != BT_VALUE_TYPE_STRING) { - BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, self_comp_class, - "`inputs` parameter: expecting string value: index=%" PRIu64 ", type=%s", - i, bt_common_value_type_string(type)); - goto error; +static const struct bt_param_validation_map_value_entry_descr fs_params_entries_descr[] = { + { "inputs", BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_MANDATORY, { + BT_VALUE_TYPE_ARRAY, + .array = { + .min_length = 1, + .max_length = BT_PARAM_VALIDATION_INFINITE, + .element_type = &inputs_elem_descr, } - } - - ret = true; - goto end; + }}, + { "trace-name", BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_OPTIONAL, { .type = BT_VALUE_TYPE_STRING } }, + { "clock-class-offset-s", BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_OPTIONAL, { .type = BT_VALUE_TYPE_SIGNED_INTEGER } }, + { "clock-class-offset-ns", BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_OPTIONAL, { .type = BT_VALUE_TYPE_SIGNED_INTEGER } }, + { "force-clock-class-origin-unix-epoch", BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_OPTIONAL, { .type = BT_VALUE_TYPE_BOOL } }, + BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_END +}; -error: - ret = false; - -end: - return ret; -} bool read_src_fs_parameters(const bt_value *params, - const bt_value **inputs, struct ctf_fs_component *ctf_fs, + const bt_value **inputs, + const bt_value **trace_name, + struct ctf_fs_component *ctf_fs, bt_self_component *self_comp, bt_self_component_class *self_comp_class) { bool ret; const bt_value *value; bt_logging_level log_level = ctf_fs->log_level; + enum bt_param_validation_status validate_value_status; + gchar *error = NULL; + + validate_value_status = bt_param_validation_validate(params, + fs_params_entries_descr, &error); + if (validate_value_status != BT_PARAM_VALIDATION_STATUS_OK) { + BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, self_comp_class, + "%s", error); + ret = false; + goto end; + } /* inputs parameter */ *inputs = bt_value_map_borrow_entry_value_const(params, "inputs"); - if (!validate_inputs_parameter(ctf_fs, *inputs, self_comp, self_comp_class)) { - goto error; - } /* clock-class-offset-s parameter */ value = bt_value_map_borrow_entry_value_const(params, "clock-class-offset-s"); if (value) { - if (!bt_value_is_signed_integer(value)) { - BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, self_comp_class, - "clock-class-offset-s must be an integer"); - goto error; - } ctf_fs->metadata_config.clock_class_offset_s = bt_value_integer_signed_get(value); } @@ -2259,34 +2290,36 @@ bool read_src_fs_parameters(const bt_value *params, value = bt_value_map_borrow_entry_value_const(params, "clock-class-offset-ns"); if (value) { - if (!bt_value_is_signed_integer(value)) { - BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(self_comp, self_comp_class, - "clock-class-offset-ns must be an integer"); - goto error; - } ctf_fs->metadata_config.clock_class_offset_ns = bt_value_integer_signed_get(value); } + /* force-clock-class-origin-unix-epoch parameter */ + value = bt_value_map_borrow_entry_value_const(params, + "force-clock-class-origin-unix-epoch"); + if (value) { + ctf_fs->metadata_config.force_clock_class_origin_unix_epoch = + bt_value_bool_get(value); + } + + /* trace-name parameter */ + *trace_name = bt_value_map_borrow_entry_value_const(params, "trace-name"); ret = true; - goto end; - -error: - ret = false; end: + g_free(error); return ret; } static struct ctf_fs_component *ctf_fs_create( const bt_value *params, - bt_self_component_source *self_comp_src, - bt_self_component_class *self_comp_class) + bt_self_component_source *self_comp_src) { struct ctf_fs_component *ctf_fs = NULL; const bt_value *inputs_value; + const bt_value *trace_name_value; bt_self_component *self_comp = bt_self_component_source_as_self_component(self_comp_src); @@ -2296,15 +2329,15 @@ struct ctf_fs_component *ctf_fs_create( goto error; } - if (!read_src_fs_parameters(params, &inputs_value, ctf_fs, - self_comp, self_comp_class)) { + if (!read_src_fs_parameters(params, &inputs_value, &trace_name_value, + ctf_fs, self_comp, NULL)) { goto error; } bt_self_component_set_data(self_comp, ctf_fs); if (ctf_fs_component_create_ctf_fs_trace(ctf_fs, inputs_value, - self_comp, self_comp_class)) { + trace_name_value, self_comp, NULL)) { goto error; } @@ -2328,17 +2361,18 @@ end: } BT_HIDDEN -bt_component_class_init_method_status ctf_fs_init( +bt_component_class_initialize_method_status ctf_fs_init( bt_self_component_source *self_comp_src, + bt_self_component_source_configuration *config, const bt_value *params, __attribute__((unused)) void *init_method_data) { struct ctf_fs_component *ctf_fs; - bt_component_class_init_method_status ret = - BT_COMPONENT_CLASS_INIT_METHOD_STATUS_OK; + bt_component_class_initialize_method_status ret = + BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK; - ctf_fs = ctf_fs_create(params, self_comp_src, NULL); + ctf_fs = ctf_fs_create(params, self_comp_src); if (!ctf_fs) { - ret = BT_COMPONENT_CLASS_INIT_METHOD_STATUS_ERROR; + ret = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; } return ret; @@ -2361,8 +2395,8 @@ bt_component_class_query_method_status ctf_fs_query( if (strcmp(object, "metadata-info") == 0) { status = metadata_info_query(comp_class, params, log_level, result); - } else if (strcmp(object, "babeltrace.trace-info") == 0) { - status = trace_info_query(comp_class, params, log_level, + } else if (strcmp(object, "babeltrace.trace-infos") == 0) { + status = trace_infos_query(comp_class, params, log_level, result); } else if (!strcmp(object, "babeltrace.support-info")) { status = support_info_query(comp_class, params, log_level, result);