X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Fplugins%2Futils%2Fmuxer%2Fmuxer.c;h=3e4d42057b1d49e0a00814cdd6f063f9f11da634;hb=c49bf79b7d7e87cc21d065a7d208bcc238fb0800;hp=f92f8326b14c8bfc9c5254940358371ef665bb6c;hpb=c3923e1ffbb10370c0133db1e5b08cdc6080bdd3;p=babeltrace.git diff --git a/src/plugins/utils/muxer/muxer.c b/src/plugins/utils/muxer/muxer.c index f92f8326..3e4d4205 100644 --- a/src/plugins/utils/muxer/muxer.c +++ b/src/plugins/utils/muxer/muxer.c @@ -36,9 +36,9 @@ #include #include -#include "muxer.h" +#include "plugins/common/muxing/muxing.h" -#define ASSUME_ABSOLUTE_CLOCK_CLASSES_PARAM_NAME "assume-absolute-clock-classes" +#include "muxer.h" struct muxer_comp { /* Weak refs */ @@ -48,7 +48,6 @@ struct muxer_comp { unsigned int next_port_num; size_t available_input_ports; bool initializing_muxer_msg_iter; - bool assume_absolute_clock_classes; bt_logging_level log_level; }; @@ -247,96 +246,14 @@ void destroy_muxer_comp(struct muxer_comp *muxer_comp) g_free(muxer_comp); } -static -bt_value *get_default_params(struct muxer_comp *muxer_comp) -{ - bt_value *params; - int ret; - - params = bt_value_map_create(); - if (!params) { - BT_COMP_LOGE_STR("Cannot create a map value object."); - goto error; - } - - ret = bt_value_map_insert_bool_entry(params, - ASSUME_ABSOLUTE_CLOCK_CLASSES_PARAM_NAME, false); - if (ret) { - BT_COMP_LOGE_STR("Cannot add boolean value to map value object."); - goto error; - } - - goto end; - -error: - BT_VALUE_PUT_REF_AND_RESET(params); - -end: - return params; -} - -static -int configure_muxer_comp(struct muxer_comp *muxer_comp, - const bt_value *params) -{ - bt_value *default_params = NULL; - bt_value *real_params = NULL; - const bt_value *assume_absolute_clock_classes = NULL; - int ret = 0; - bt_bool bool_val; - - default_params = get_default_params(muxer_comp); - if (!default_params) { - BT_COMP_LOGE("Cannot get default parameters: " - "muxer-comp-addr=%p", muxer_comp); - goto error; - } - - ret = bt_value_map_extend(default_params, params, &real_params); - if (ret) { - BT_COMP_LOGE("Cannot extend default parameters map value: " - "muxer-comp-addr=%p, def-params-addr=%p, " - "params-addr=%p", muxer_comp, default_params, - params); - goto error; - } - - assume_absolute_clock_classes = bt_value_map_borrow_entry_value(real_params, - ASSUME_ABSOLUTE_CLOCK_CLASSES_PARAM_NAME); - if (assume_absolute_clock_classes && - !bt_value_is_bool(assume_absolute_clock_classes)) { - BT_COMP_LOGE("Expecting a boolean value for the `%s` parameter: " - "muxer-comp-addr=%p, value-type=%s", - ASSUME_ABSOLUTE_CLOCK_CLASSES_PARAM_NAME, muxer_comp, - bt_common_value_type_string( - bt_value_get_type(assume_absolute_clock_classes))); - goto error; - } - - bool_val = bt_value_bool_get(assume_absolute_clock_classes); - muxer_comp->assume_absolute_clock_classes = (bool) bool_val; - BT_COMP_LOGI("Configured muxer component: muxer-comp-addr=%p, " - "assume-absolute-clock-classes=%d", - muxer_comp, muxer_comp->assume_absolute_clock_classes); - goto end; - -error: - ret = -1; - -end: - bt_value_put_ref(default_params); - bt_value_put_ref(real_params); - return ret; -} - BT_HIDDEN -bt_component_class_init_method_status muxer_init( +bt_component_class_initialize_method_status muxer_init( bt_self_component_filter *self_comp_flt, + bt_self_component_filter_configuration *config, const bt_value *params, void *init_data) { - int ret; - bt_component_class_init_method_status status = - BT_COMPONENT_CLASS_INIT_METHOD_STATUS_OK; + bt_component_class_initialize_method_status status = + BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK; bt_self_component_add_port_status add_port_status; bt_self_component *self_comp = bt_self_component_filter_as_self_component(self_comp_flt); @@ -357,13 +274,6 @@ bt_component_class_init_method_status muxer_init( muxer_comp->log_level = log_level; muxer_comp->self_comp = self_comp; muxer_comp->self_comp_flt = self_comp_flt; - ret = configure_muxer_comp(muxer_comp, params); - if (ret) { - BT_COMP_LOGE("Cannot configure muxer component: " - "muxer-comp-addr=%p, params-addr=%p", - muxer_comp, params); - goto error; - } bt_self_component_set_data(self_comp, muxer_comp); add_port_status = add_available_input_port(self_comp_flt); @@ -374,9 +284,9 @@ bt_component_class_init_method_status muxer_init( bt_common_func_status_string(add_port_status)); if (add_port_status == BT_SELF_COMPONENT_ADD_PORT_STATUS_MEMORY_ERROR) { - status = BT_COMPONENT_CLASS_INIT_METHOD_STATUS_MEMORY_ERROR; + status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR; } else { - status = BT_COMPONENT_CLASS_INIT_METHOD_STATUS_ERROR; + status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; } goto error; @@ -390,9 +300,9 @@ bt_component_class_init_method_status muxer_init( bt_common_func_status_string(add_port_status)); if (add_port_status == BT_SELF_COMPONENT_ADD_PORT_STATUS_MEMORY_ERROR) { - status = BT_COMPONENT_CLASS_INIT_METHOD_STATUS_MEMORY_ERROR; + status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR; } else { - status = BT_COMPONENT_CLASS_INIT_METHOD_STATUS_ERROR; + status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; } goto error; @@ -408,8 +318,8 @@ error: destroy_muxer_comp(muxer_comp); bt_self_component_set_data(self_comp, NULL); - if (status == BT_COMPONENT_CLASS_INIT_METHOD_STATUS_OK) { - status = BT_COMPONENT_CLASS_INIT_METHOD_STATUS_ERROR; + if (status == BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK) { + status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; } end: @@ -428,16 +338,17 @@ void muxer_finalize(bt_self_component_filter *self_comp) } static -bt_self_component_port_input_message_iterator * +bt_self_component_port_input_message_iterator_create_from_message_iterator_status create_msg_iter_on_input_port(struct muxer_comp *muxer_comp, struct muxer_msg_iter *muxer_msg_iter, - bt_self_component_port_input *self_port) + bt_self_component_port_input *self_port, + bt_self_component_port_input_message_iterator **msg_iter) { const bt_port *port = bt_self_component_port_as_port( bt_self_component_port_input_as_self_component_port( self_port)); - bt_self_component_port_input_message_iterator *msg_iter = - NULL; + bt_self_component_port_input_message_iterator_create_from_message_iterator_status + status; BT_ASSERT(port); BT_ASSERT(bt_port_is_connected(port)); @@ -445,9 +356,9 @@ create_msg_iter_on_input_port(struct muxer_comp *muxer_comp, // TODO: Advance the iterator to >= the time of the latest // returned message by the muxer message // iterator which creates it. - msg_iter = bt_self_component_port_input_message_iterator_create_from_message_iterator( - muxer_msg_iter->self_msg_iter, self_port); - if (!msg_iter) { + status = bt_self_component_port_input_message_iterator_create_from_message_iterator( + muxer_msg_iter->self_msg_iter, self_port, msg_iter); + if (status != BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_CREATE_FROM_MESSAGE_ITERATOR_STATUS_OK) { BT_COMP_LOGE("Cannot create upstream message iterator on input port: " "port-addr=%p, port-name=\"%s\"", port, bt_port_get_name(port)); @@ -459,7 +370,7 @@ create_msg_iter_on_input_port(struct muxer_comp *muxer_comp, port, bt_port_get_name(port), msg_iter); end: - return msg_iter; + return status; } static @@ -609,1130 +520,238 @@ int get_msg_ts_ns(struct muxer_comp *muxer_comp, { enum bt_message_stream_clock_snapshot_state snapshot_state = bt_message_stream_beginning_borrow_default_clock_snapshot_const( - msg, &clock_snapshot); - if (snapshot_state == BT_MESSAGE_STREAM_CLOCK_SNAPSHOT_STATE_UNKNOWN) { - goto no_clock_snapshot; - } - - break; - } - case BT_MESSAGE_TYPE_STREAM_END: - { - enum bt_message_stream_clock_snapshot_state snapshot_state = - bt_message_stream_end_borrow_default_clock_snapshot_const( - msg, &clock_snapshot); - if (snapshot_state == BT_MESSAGE_STREAM_CLOCK_SNAPSHOT_STATE_UNKNOWN) { - goto no_clock_snapshot; - } - - break; - } - case BT_MESSAGE_TYPE_DISCARDED_EVENTS: - if (bt_stream_class_discarded_events_have_default_clock_snapshots( - stream_class)) { - clock_snapshot = bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const( - msg); - } else { - goto no_clock_snapshot; - } - - break; - case BT_MESSAGE_TYPE_DISCARDED_PACKETS: - if (bt_stream_class_discarded_packets_have_default_clock_snapshots( - stream_class)) { - clock_snapshot = bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const( - msg); - } else { - goto no_clock_snapshot; - } - - break; - case BT_MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY: - clock_snapshot = bt_message_message_iterator_inactivity_borrow_default_clock_snapshot_const( - msg); - break; - default: - /* All the other messages have a higher priority */ - BT_COMP_LOGD_STR("Message has no timestamp: using the last returned timestamp."); - *ts_ns = last_returned_ts_ns; - goto end; - } - - ret = bt_clock_snapshot_get_ns_from_origin(clock_snapshot, ts_ns); - if (ret) { - BT_COMP_LOGE("Cannot get nanoseconds from Epoch of clock snapshot: " - "clock-snapshot-addr=%p", clock_snapshot); - goto error; - } - - goto end; - -no_clock_snapshot: - BT_COMP_LOGD_STR("Message's default clock snapshot is missing: " - "using the last returned timestamp."); - *ts_ns = last_returned_ts_ns; - goto end; - -error: - ret = -1; - -end: - if (ret == 0) { - BT_COMP_LOGD("Found message's timestamp: " - "muxer-msg-iter-addr=%p, msg-addr=%p, " - "last-returned-ts=%" PRId64 ", ts=%" PRId64, - muxer_msg_iter, msg, last_returned_ts_ns, - *ts_ns); - } - - return ret; -} - -static inline -int validate_clock_class(struct muxer_msg_iter *muxer_msg_iter, - struct muxer_comp *muxer_comp, - const bt_clock_class *clock_class) -{ - int ret = 0; - const uint8_t *cc_uuid; - const char *cc_name; - - BT_ASSERT(clock_class); - cc_uuid = bt_clock_class_get_uuid(clock_class); - cc_name = bt_clock_class_get_name(clock_class); - - if (muxer_msg_iter->clock_class_expectation == - MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_ANY) { - /* - * This is the first clock class that this muxer - * message iterator encounters. Its properties - * determine what to expect for the whole lifetime of - * the iterator without a true - * `assume-absolute-clock-classes` parameter. - */ - if (bt_clock_class_origin_is_unix_epoch(clock_class)) { - /* Expect absolute clock classes */ - muxer_msg_iter->clock_class_expectation = - MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_ABSOLUTE; - } else { - if (cc_uuid) { - /* - * Expect non-absolute clock classes - * with a specific UUID. - */ - muxer_msg_iter->clock_class_expectation = - MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_NOT_ABS_SPEC_UUID; - bt_uuid_copy(muxer_msg_iter->expected_clock_class_uuid, cc_uuid); - } else { - /* - * Expect non-absolute clock classes - * with no UUID. - */ - muxer_msg_iter->clock_class_expectation = - MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_NOT_ABS_NO_UUID; - } - } - } - - if (!muxer_comp->assume_absolute_clock_classes) { - switch (muxer_msg_iter->clock_class_expectation) { - case MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_ABSOLUTE: - if (!bt_clock_class_origin_is_unix_epoch(clock_class)) { - BT_COMP_LOGE("Expecting an absolute clock class, " - "but got a non-absolute one: " - "clock-class-addr=%p, clock-class-name=\"%s\"", - clock_class, cc_name); - goto error; - } - break; - case MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_NOT_ABS_NO_UUID: - if (bt_clock_class_origin_is_unix_epoch(clock_class)) { - BT_COMP_LOGE("Expecting a non-absolute clock class with no UUID, " - "but got an absolute one: " - "clock-class-addr=%p, clock-class-name=\"%s\"", - clock_class, cc_name); - goto error; - } - - if (cc_uuid) { - BT_COMP_LOGE("Expecting a non-absolute clock class with no UUID, " - "but got one with a UUID: " - "clock-class-addr=%p, clock-class-name=\"%s\", " - "uuid=\"" BT_UUID_FMT "\"", - clock_class, cc_name, BT_UUID_FMT_VALUES(cc_uuid)); - goto error; - } - break; - case MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_NOT_ABS_SPEC_UUID: - if (bt_clock_class_origin_is_unix_epoch(clock_class)) { - BT_COMP_LOGE("Expecting a non-absolute clock class with a specific UUID, " - "but got an absolute one: " - "clock-class-addr=%p, clock-class-name=\"%s\"", - clock_class, cc_name); - goto error; - } - - if (!cc_uuid) { - BT_COMP_LOGE("Expecting a non-absolute clock class with a specific UUID, " - "but got one with no UUID: " - "clock-class-addr=%p, clock-class-name=\"%s\"", - clock_class, cc_name); - goto error; - } - - if (bt_uuid_compare(muxer_msg_iter->expected_clock_class_uuid, cc_uuid) != 0) { - BT_COMP_LOGE("Expecting a non-absolute clock class with a specific UUID, " - "but got one with different UUID: " - "clock-class-addr=%p, clock-class-name=\"%s\", " - "expected-uuid=\"" BT_UUID_FMT "\", " - "uuid=\"" BT_UUID_FMT "\"", - clock_class, cc_name, - BT_UUID_FMT_VALUES(muxer_msg_iter->expected_clock_class_uuid), - BT_UUID_FMT_VALUES(cc_uuid)); - goto error; - } - break; - case MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_NONE: - BT_COMP_LOGE("Expecting no clock class, but got one: " - "clock-class-addr=%p, clock-class-name=\"%s\"", - clock_class, cc_name); - goto error; - default: - /* Unexpected */ - BT_COMP_LOGF("Unexpected clock class expectation: " - "expectation-code=%d", - muxer_msg_iter->clock_class_expectation); - abort(); - } - } - - goto end; - -error: - ret = -1; - -end: - return ret; -} - -static inline -int validate_new_stream_clock_class(struct muxer_msg_iter *muxer_msg_iter, - struct muxer_comp *muxer_comp, const bt_stream *stream) -{ - int ret = 0; - const bt_stream_class *stream_class = - bt_stream_borrow_class_const(stream); - const bt_clock_class *clock_class = - bt_stream_class_borrow_default_clock_class_const(stream_class); - - if (!clock_class) { - if (muxer_msg_iter->clock_class_expectation == - MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_ANY) { - /* Expect no clock class */ - muxer_msg_iter->clock_class_expectation = - MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_NONE; - } else { - BT_COMP_LOGE("Expecting stream class with a default clock class: " - "stream-class-addr=%p, stream-class-name=\"%s\", " - "stream-class-id=%" PRIu64, - stream_class, bt_stream_class_get_name(stream_class), - bt_stream_class_get_id(stream_class)); - ret = -1; - } - - goto end; - } - - ret = validate_clock_class(muxer_msg_iter, muxer_comp, clock_class); - -end: - return ret; -} - -struct message_to_compare { - const bt_message *msg; - const bt_trace *trace; - const bt_stream *stream; -}; - -struct messages_to_compare { - struct message_to_compare left; - struct message_to_compare right; -}; - -static -int message_type_weight(const bt_message_type msg_type) -{ - int weight; - - switch (msg_type) { - case BT_MESSAGE_TYPE_STREAM_BEGINNING: - weight = 7; - break; - case BT_MESSAGE_TYPE_PACKET_BEGINNING: - weight = 6; - break; - case BT_MESSAGE_TYPE_EVENT: - weight = 5; - break; - case BT_MESSAGE_TYPE_DISCARDED_EVENTS: - weight = 4; - break; - case BT_MESSAGE_TYPE_PACKET_END: - weight = 3; - break; - case BT_MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY: - weight = 2; - break; - case BT_MESSAGE_TYPE_DISCARDED_PACKETS: - weight = 1; - break; - case BT_MESSAGE_TYPE_STREAM_END: - weight = 0; - break; - default: - abort(); - } - - return weight; -} - -/* - * Compare 2 messages to order them in a determinitic way based on their - * types. - * Returns -1 is left mesage must go first - * Returns 1 is right mesage must go first - */ -static -int compare_messages_by_type(struct messages_to_compare *msgs) -{ - bt_message_type left_msg_type = bt_message_get_type(msgs->left.msg); - bt_message_type right_msg_type = bt_message_get_type(msgs->right.msg); - - return message_type_weight(right_msg_type) - - message_type_weight(left_msg_type); -} - -static -int compare_events(const bt_event *left_event, const bt_event *right_event) -{ - int ret; - const bt_event_class *left_event_class, *right_event_class; - uint64_t left_event_class_id, right_event_class_id; - const char *left_event_class_name, *right_event_class_name, - *left_event_class_emf_uri, *right_event_class_emf_uri; - bt_event_class_log_level left_event_class_log_level, right_event_class_log_level; - bt_property_availability left_log_level_avail, right_log_level_avail; - - left_event_class = bt_event_borrow_class_const(left_event); - right_event_class = bt_event_borrow_class_const(right_event); - - left_event_class_id = bt_event_class_get_id(left_event_class); - right_event_class_id = bt_event_class_get_id(right_event_class); - - if (left_event_class_id > right_event_class_id) { - ret = 1; - goto end; - } else if (left_event_class_id < right_event_class_id) { - ret = -1; - goto end; - } - - left_event_class_name = bt_event_class_get_name(left_event_class); - right_event_class_name = bt_event_class_get_name(right_event_class); - if (left_event_class_name && right_event_class_name) { - ret = strcmp(left_event_class_name, right_event_class_name); - if (ret != 0) { - goto end; - } - } else if (!left_event_class_name && right_event_class_name) { - ret = -1; - goto end; - } else if (left_event_class_name && !right_event_class_name) { - ret = 1; - goto end; - } - - left_log_level_avail = bt_event_class_get_log_level(left_event_class, - &left_event_class_log_level); - right_log_level_avail = bt_event_class_get_log_level(right_event_class, - &right_event_class_log_level); - - if (left_log_level_avail == BT_PROPERTY_AVAILABILITY_AVAILABLE && - right_log_level_avail == BT_PROPERTY_AVAILABILITY_AVAILABLE) { - ret = left_event_class_log_level - right_event_class_log_level; - if (ret) { - goto end; - } - } else if (left_log_level_avail == BT_PROPERTY_AVAILABILITY_AVAILABLE && - right_log_level_avail == BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE) { - ret = -1; - goto end; - } else if (left_log_level_avail == BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE && - right_log_level_avail == BT_PROPERTY_AVAILABILITY_AVAILABLE) { - ret = 1; - goto end; - } - - left_event_class_emf_uri = bt_event_class_get_emf_uri(left_event_class); - right_event_class_emf_uri = bt_event_class_get_emf_uri(right_event_class); - if (left_event_class_emf_uri && right_event_class_emf_uri) { - ret = strcmp(left_event_class_emf_uri, right_event_class_emf_uri); - if (ret != 0) { - goto end; - } - } else if (!left_event_class_emf_uri && right_event_class_emf_uri) { - ret = -1; - goto end; - } else if (left_event_class_emf_uri && !right_event_class_emf_uri) { - ret = 1; - goto end; - } - -end: - return ret; -} - -static -int compare_streams(const bt_stream *left_stream, const bt_stream *right_stream) -{ - int ret = 0; - const char *left_stream_name, *right_stream_name, - *left_stream_class_name, *right_stream_class_name; - const bt_stream_class *left_stream_class, *right_stream_class; - - /* - * No need to compare stream id as it was checked earlier and if we are - * here it means they are identical or both absent. - */ - BT_ASSERT(bt_stream_get_id(left_stream) == - bt_stream_get_id(right_stream)); - - /* Compare stream name. */ - left_stream_name = bt_stream_get_name(left_stream); - right_stream_name = bt_stream_get_name(right_stream); - - if (left_stream_name && right_stream_name) { - ret = strcmp(left_stream_name, right_stream_name); - if (ret != 0) { - goto end; - } - } else if (!left_stream_name && right_stream_name) { - ret = -1; - goto end; - } else if (left_stream_name && !right_stream_name) { - ret = 1; - goto end; - } - - left_stream_class = bt_stream_borrow_class_const(left_stream); - right_stream_class = bt_stream_borrow_class_const(right_stream); - - /* - * No need to compare stream class id as it was checked earlier and if - * we are here it means they are identical. - */ - BT_ASSERT(bt_stream_class_get_id(left_stream_class) == - bt_stream_class_get_id(right_stream_class)); - - /* Compare stream class name. */ - left_stream_class_name = bt_stream_class_get_name(left_stream_class); - right_stream_class_name = bt_stream_class_get_name(right_stream_class); - - if (left_stream_class_name && right_stream_class_name) { - ret = strcmp(left_stream_class_name, right_stream_class_name); - if (ret != 0) { - goto end; - } - } else if (!left_stream_class_name && right_stream_class_name) { - ret = -1; - goto end; - } else if (left_stream_class_name && !right_stream_class_name) { - ret = 1; - goto end; - } - - /* Compare stream class automatic event class id assignment. */ - if (bt_stream_class_assigns_automatic_event_class_id(left_stream_class) && - !bt_stream_class_assigns_automatic_event_class_id(right_stream_class)) { - ret = 1; - goto end; - } else if (!bt_stream_class_assigns_automatic_event_class_id(left_stream_class) && - bt_stream_class_assigns_automatic_event_class_id(right_stream_class)) { - ret = -1; - goto end; - } - - /* Compare stream class automatic stream id assignment. */ - if (bt_stream_class_assigns_automatic_stream_id(left_stream_class) && - !bt_stream_class_assigns_automatic_stream_id(right_stream_class)) { - ret = 1; - goto end; - } else if (!bt_stream_class_assigns_automatic_stream_id(left_stream_class) && - bt_stream_class_assigns_automatic_stream_id(right_stream_class)) { - ret = -1; - goto end; - } - - /* Compare stream class support of discarded events. */ - if (bt_stream_class_supports_discarded_events(left_stream_class) && - !bt_stream_class_supports_discarded_events(right_stream_class)) { - ret = 1; - goto end; - } else if (!bt_stream_class_supports_discarded_events(left_stream_class) && - bt_stream_class_supports_discarded_events(right_stream_class)) { - ret = -1; - goto end; - } - - /* Compare stream class discarded events default clock snapshot. */ - if (bt_stream_class_discarded_events_have_default_clock_snapshots(left_stream_class) && - !bt_stream_class_discarded_events_have_default_clock_snapshots(right_stream_class)) { - ret = 1; - goto end; - } else if (!bt_stream_class_discarded_events_have_default_clock_snapshots(left_stream_class) && - bt_stream_class_discarded_events_have_default_clock_snapshots(right_stream_class)) { - ret = -1; - goto end; - } - - /* Compare stream class support of packets. */ - if (bt_stream_class_supports_packets(left_stream_class) && - !bt_stream_class_supports_packets(right_stream_class)) { - ret = 1; - goto end; - } else if (!bt_stream_class_supports_packets(left_stream_class) && - bt_stream_class_supports_packets(right_stream_class)) { - ret = -1; - goto end; - } - - if (!bt_stream_class_supports_packets(left_stream_class)) { - /* Skip all packet related checks. */ - goto end; - } - - /* - * Compare stream class presence of discarded packets beginning default - * clock snapshot. - */ - if (bt_stream_class_packets_have_beginning_default_clock_snapshot(left_stream_class) && - !bt_stream_class_packets_have_beginning_default_clock_snapshot(right_stream_class)) { - ret = 1; - goto end; - } else if (!bt_stream_class_packets_have_beginning_default_clock_snapshot(left_stream_class) && - bt_stream_class_packets_have_beginning_default_clock_snapshot(right_stream_class)) { - ret = -1; - goto end; - } - - /* - * Compare stream class presence of discarded packets end default clock - * snapshot. - */ - if (bt_stream_class_packets_have_end_default_clock_snapshot(left_stream_class) && - !bt_stream_class_packets_have_end_default_clock_snapshot(right_stream_class)) { - ret = 1; - goto end; - } else if (!bt_stream_class_packets_have_end_default_clock_snapshot(left_stream_class) && - bt_stream_class_packets_have_end_default_clock_snapshot(right_stream_class)) { - ret = -1; - goto end; - } - - /* Compare stream class support of discarded packets. */ - if (bt_stream_class_supports_discarded_packets(left_stream_class) && - !bt_stream_class_supports_discarded_packets(right_stream_class)) { - ret = 1; - goto end; - } else if (!bt_stream_class_supports_discarded_packets(left_stream_class) && - bt_stream_class_supports_discarded_packets(right_stream_class)) { - ret = -1; - goto end; - } - - /* Compare stream class discarded packets default clock snapshot. */ - if (bt_stream_class_discarded_packets_have_default_clock_snapshots(left_stream_class) && - !bt_stream_class_discarded_packets_have_default_clock_snapshots(right_stream_class)) { - ret = 1; - goto end; - } else if (!bt_stream_class_discarded_packets_have_default_clock_snapshots(left_stream_class) && - bt_stream_class_discarded_packets_have_default_clock_snapshots(right_stream_class)) { - ret = -1; - goto end; - } - -end: - return ret; -} - -static -int compare_clock_snapshots_and_clock_classes(const bt_clock_snapshot *left_cs, - const bt_clock_snapshot *right_cs) -{ - int ret; - uint64_t left_freq, right_freq, left_prec, right_prec; - uint64_t left_cs_value, right_cs_value; - const bt_clock_class *left_clock_class, *right_clock_class; - const char *left_clock_class_name, *right_clock_class_name; - left_cs_value = bt_clock_snapshot_get_value(left_cs); - right_cs_value = bt_clock_snapshot_get_value(right_cs); - bt_uuid left_clock_class_uuid, right_clock_class_uuid; - - ret = left_cs_value - right_cs_value; - if (ret != 0) { - goto end; - } - - left_clock_class = bt_clock_snapshot_borrow_clock_class_const(left_cs); - right_clock_class = bt_clock_snapshot_borrow_clock_class_const(right_cs); - - left_clock_class_uuid = bt_clock_class_get_uuid(left_clock_class); - right_clock_class_uuid = bt_clock_class_get_uuid(right_clock_class); - - if (left_clock_class_uuid && !right_clock_class_uuid) { - ret = -1; - goto end; - } else if (!left_clock_class_uuid && right_clock_class_uuid) { - ret = 1; - goto end; - } else if (left_clock_class_uuid && right_clock_class_uuid) { - ret = bt_uuid_compare(left_clock_class_uuid, - right_clock_class_uuid); - if (ret != 0) { - goto end; - } - } - - - left_clock_class_name = bt_clock_class_get_name(left_clock_class); - right_clock_class_name = bt_clock_class_get_name(right_clock_class); - - if (left_clock_class_name && !right_clock_class_name) { - ret = -1; - goto end; - } else if (!left_clock_class_name && right_clock_class_name) { - ret = 1; - goto end; - } else if (left_clock_class_name && right_clock_class_name) { - ret = strcmp(left_clock_class_name, right_clock_class_name); - if (ret != 0) { - goto end; - } - } - - left_freq = bt_clock_class_get_frequency(left_clock_class); - right_freq = bt_clock_class_get_frequency(right_clock_class); - - ret = right_freq - left_freq; - if (ret != 0) { - goto end; - } - - left_prec = bt_clock_class_get_precision(left_clock_class); - right_prec = bt_clock_class_get_precision(right_clock_class); - - ret = right_prec - left_prec; - if (ret != 0) { - goto end; - } - -end: - return ret; -} - -static -const bt_stream *borrow_stream(const bt_message *msg) -{ - bt_message_type msg_type = bt_message_get_type(msg); - const bt_stream *stream = NULL; - const bt_packet *packet = NULL; - const bt_event *event = NULL; - - switch (msg_type) { - case BT_MESSAGE_TYPE_STREAM_BEGINNING: - stream = bt_message_stream_beginning_borrow_stream_const(msg); - break; - case BT_MESSAGE_TYPE_STREAM_END: - stream = bt_message_stream_end_borrow_stream_const(msg); - break; - case BT_MESSAGE_TYPE_PACKET_BEGINNING: - packet = bt_message_packet_beginning_borrow_packet_const(msg); - stream = bt_packet_borrow_stream_const(packet); - break; - case BT_MESSAGE_TYPE_PACKET_END: - packet = bt_message_packet_end_borrow_packet_const(msg); - stream = bt_packet_borrow_stream_const(packet); - break; - case BT_MESSAGE_TYPE_EVENT: - event = bt_message_event_borrow_event_const(msg); - stream = bt_event_borrow_stream_const(event); - break; - case BT_MESSAGE_TYPE_DISCARDED_EVENTS: - stream = bt_message_discarded_events_borrow_stream_const(msg); - break; - case BT_MESSAGE_TYPE_DISCARDED_PACKETS: - stream = bt_message_discarded_packets_borrow_stream_const(msg); - break; - case BT_MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY: - goto end; - default: - abort(); - } - -end: - return stream; -} - -static -const bt_trace *borrow_trace(const bt_message *msg) -{ - const bt_trace *trace = NULL; - const bt_stream *stream = NULL; - - stream = borrow_stream(msg); - if (stream) { - trace = bt_stream_borrow_trace_const(stream); - } - - return trace; -} - -static -int compare_messages_by_trace_name(struct messages_to_compare *msgs) -{ - int ret = 0; - const char *left_trace_name = NULL, *right_trace_name = NULL; - - if (msgs->left.trace && !msgs->right.trace) { - ret = -1; - goto end; - } - - if (!msgs->left.trace && msgs->right.trace) { - ret = 1; - goto end; - } - - if (!msgs->left.trace && !msgs->right.trace) { - ret = 0; - goto end; - } - - left_trace_name = bt_trace_get_name(msgs->left.trace); - right_trace_name = bt_trace_get_name(msgs->right.trace); - - if (left_trace_name && !right_trace_name) { - ret = -1; - goto end; - } - - if (!left_trace_name && right_trace_name) { - ret = 1; - goto end; - } - - if (!left_trace_name && !right_trace_name) { - ret = 0; - goto end; - } - - ret = strcmp(left_trace_name, right_trace_name); -end: - return ret; -} - -static -int compare_messages_by_trace_uuid(struct messages_to_compare *msgs) -{ - int ret = 0; - bt_uuid left_trace_uuid = NULL, right_trace_uuid = NULL; - - if (msgs->left.trace && !msgs->right.trace) { - ret = -1; - goto end; - } - - if (!msgs->left.trace && msgs->right.trace) { - ret = 1; - goto end; - } - - if (!msgs->left.trace && !msgs->right.trace) { - ret = 0; - goto end; - } - - left_trace_uuid = bt_trace_get_uuid(msgs->left.trace); - right_trace_uuid = bt_trace_get_uuid(msgs->right.trace); - - if (left_trace_uuid && !right_trace_uuid) { - ret = -1; - goto end; - } - - if (!left_trace_uuid && right_trace_uuid) { - ret = 1; - goto end; - } - - if (!left_trace_uuid && !right_trace_uuid) { - ret = 0; - goto end; - } - - ret = bt_uuid_compare(left_trace_uuid, right_trace_uuid); -end: - return ret; -} - -static -int compare_messages_by_stream_class_id(struct messages_to_compare *msgs) -{ - int ret = 0; - uint64_t left_stream_class_id = 0, right_stream_class_id = 0; - - if (msgs->left.stream && !msgs->right.stream) { - ret = -1; - goto end; - } - - if (!msgs->left.stream && msgs->right.stream) { - ret = 1; - goto end; - } - - if (!msgs->left.stream && !msgs->right.stream) { - ret = 0; - goto end; - } - - left_stream_class_id = bt_stream_class_get_id( - bt_stream_borrow_class_const(msgs->left.stream)); - - right_stream_class_id = bt_stream_class_get_id( - bt_stream_borrow_class_const(msgs->right.stream)); - - if (left_stream_class_id == right_stream_class_id) { - ret = 0; - goto end; - } - - ret = (left_stream_class_id < right_stream_class_id) ? -1 : 1; - -end: - return ret; -} - -static -int compare_messages_by_stream_id(struct messages_to_compare *msgs) -{ - int ret = 0; - uint64_t left_stream_id = 0, right_stream_id = 0; - - if (msgs->left.stream && !msgs->right.stream) { - ret = -1; - goto end; - } - - if (!msgs->left.stream && msgs->right.stream) { - ret = 1; - goto end; - } - - if (!msgs->left.stream && !msgs->right.stream) { - ret = 0; - goto end; - } - - left_stream_id = bt_stream_get_id(msgs->left.stream); - right_stream_id = bt_stream_get_id(msgs->right.stream); - - if (left_stream_id == right_stream_id) { - ret = 0; - goto end; - } - - ret = (left_stream_id < right_stream_id) ? -1 : 1; - -end: - return ret; -} - -static -int compare_messages_same_type(struct messages_to_compare *msgs) -{ - int ret = 0; - - /* - * Both messages are of the same type, we must compare characterics of - * the messages such as the attributes of the event in a event message. - */ - BT_ASSERT(bt_message_get_type(msgs->left.msg) == - bt_message_get_type(msgs->right.msg)); - - switch (bt_message_get_type(msgs->left.msg)) { - case BT_MESSAGE_TYPE_STREAM_BEGINNING: - ret = compare_streams(msgs->left.stream, msgs->right.stream); - if (ret) { - goto end; - } - case BT_MESSAGE_TYPE_STREAM_END: - ret = compare_streams(msgs->left.stream, msgs->right.stream); - if (ret) { - goto end; + msg, &clock_snapshot); + if (snapshot_state == BT_MESSAGE_STREAM_CLOCK_SNAPSHOT_STATE_UNKNOWN) { + goto no_clock_snapshot; } break; - case BT_MESSAGE_TYPE_PACKET_BEGINNING: - ret = compare_streams(msgs->left.stream, msgs->right.stream); - if (ret) { - goto end; + } + case BT_MESSAGE_TYPE_STREAM_END: + { + enum bt_message_stream_clock_snapshot_state snapshot_state = + bt_message_stream_end_borrow_default_clock_snapshot_const( + msg, &clock_snapshot); + if (snapshot_state == BT_MESSAGE_STREAM_CLOCK_SNAPSHOT_STATE_UNKNOWN) { + goto no_clock_snapshot; } break; - case BT_MESSAGE_TYPE_PACKET_END: - ret = compare_streams(msgs->left.stream, msgs->right.stream); - if (ret) { - goto end; + } + case BT_MESSAGE_TYPE_DISCARDED_EVENTS: + if (bt_stream_class_discarded_events_have_default_clock_snapshots( + stream_class)) { + clock_snapshot = bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const( + msg); + } else { + goto no_clock_snapshot; } break; - case BT_MESSAGE_TYPE_EVENT: - { - const bt_event *left_event, *right_event; - left_event = bt_message_event_borrow_event_const(msgs->left.msg); - right_event = bt_message_event_borrow_event_const(msgs->right.msg); - - ret = compare_events(left_event, right_event); - if (ret) { - goto end; + case BT_MESSAGE_TYPE_DISCARDED_PACKETS: + if (bt_stream_class_discarded_packets_have_default_clock_snapshots( + stream_class)) { + clock_snapshot = bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const( + msg); + } else { + goto no_clock_snapshot; } - ret = compare_streams(msgs->left.stream, msgs->right.stream); - if (ret) { - goto end; - } break; + case BT_MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY: + clock_snapshot = bt_message_message_iterator_inactivity_borrow_default_clock_snapshot_const( + msg); + break; + default: + /* All the other messages have a higher priority */ + BT_COMP_LOGD_STR("Message has no timestamp: using the last returned timestamp."); + *ts_ns = last_returned_ts_ns; + goto end; } - case BT_MESSAGE_TYPE_DISCARDED_EVENTS: - { - const bt_stream_class *left_stream_class; - bt_property_availability left_event_count_avail, - right_event_count_avail; - uint64_t left_event_count, right_event_count; - /* - * Compare streams first to check if there is a - * mismatch about discarded event related configuration - * in the stream class. - */ - ret = compare_streams(msgs->left.stream, msgs->right.stream); - if (ret) { - goto end; - } + ret = bt_clock_snapshot_get_ns_from_origin(clock_snapshot, ts_ns); + if (ret) { + BT_COMP_LOGE("Cannot get nanoseconds from Epoch of clock snapshot: " + "clock-snapshot-addr=%p", clock_snapshot); + goto error; + } - left_stream_class = bt_stream_borrow_class_const(msgs->left.stream); - if (bt_stream_class_discarded_events_have_default_clock_snapshots( - left_stream_class)) { - const bt_clock_snapshot *left_beg_cs = - bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const(msgs->left.msg); - const bt_clock_snapshot *right_beg_cs = - bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const(msgs->right.msg); - const bt_clock_snapshot *left_end_cs = - bt_message_discarded_events_borrow_end_default_clock_snapshot_const(msgs->left.msg); - const bt_clock_snapshot *right_end_cs = - bt_message_discarded_events_borrow_end_default_clock_snapshot_const(msgs->right.msg); - - ret = compare_clock_snapshots_and_clock_classes( - left_beg_cs, right_beg_cs); - if (ret) { - goto end; - } + goto end; - ret = compare_clock_snapshots_and_clock_classes( - left_end_cs, right_end_cs); - if (ret) { - goto end; - } - } +no_clock_snapshot: + BT_COMP_LOGD_STR("Message's default clock snapshot is missing: " + "using the last returned timestamp."); + *ts_ns = last_returned_ts_ns; + goto end; - left_event_count_avail = - bt_message_discarded_events_get_count( - msgs->left.msg, &left_event_count); - right_event_count_avail = - bt_message_discarded_events_get_count( - msgs->right.msg, &right_event_count); - if (left_event_count_avail == BT_PROPERTY_AVAILABILITY_AVAILABLE && - right_event_count_avail == BT_PROPERTY_AVAILABILITY_AVAILABLE) { - ret = left_event_count - right_event_count; - if (ret != 0) { - goto end; - } - } else if (left_event_count_avail == BT_PROPERTY_AVAILABILITY_AVAILABLE && - right_event_count_avail == BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE) { - ret = -1; - goto end; - } else if (left_event_count_avail == BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE && - right_event_count_avail == BT_PROPERTY_AVAILABILITY_AVAILABLE) { - ret = 1; - goto end; - } +error: + ret = -1; - break; +end: + if (ret == 0) { + BT_COMP_LOGD("Found message's timestamp: " + "muxer-msg-iter-addr=%p, msg-addr=%p, " + "last-returned-ts=%" PRId64 ", ts=%" PRId64, + muxer_msg_iter, msg, last_returned_ts_ns, + *ts_ns); } - case BT_MESSAGE_TYPE_DISCARDED_PACKETS: - { - const bt_stream_class *left_stream_class; - bt_property_availability left_packet_count_avail, - right_packet_count_avail; - uint64_t left_packet_count, right_packet_count; - /* - * Compare streams first to check if there is a - * mismatch about discarded packets related - * configuration in the stream class. - */ - ret = compare_streams(msgs->left.stream, msgs->right.stream); - if (ret) { - goto end; - } + return ret; +} - left_stream_class = bt_stream_borrow_class_const(msgs->left.stream); +static inline +int validate_clock_class(struct muxer_msg_iter *muxer_msg_iter, + struct muxer_comp *muxer_comp, + const bt_clock_class *clock_class) +{ + int ret = 0; + const uint8_t *cc_uuid; + const char *cc_name; - if (bt_stream_class_discarded_packets_have_default_clock_snapshots( - left_stream_class)) { - const bt_clock_snapshot *left_beg_cs = - bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const(msgs->left.msg); - const bt_clock_snapshot *right_beg_cs = - bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const(msgs->right.msg); - const bt_clock_snapshot *left_end_cs = - bt_message_discarded_packets_borrow_end_default_clock_snapshot_const(msgs->left.msg); - const bt_clock_snapshot *right_end_cs = - bt_message_discarded_packets_borrow_end_default_clock_snapshot_const(msgs->right.msg); - - ret = compare_clock_snapshots_and_clock_classes( - left_beg_cs, right_beg_cs); - if (ret) { - goto end; - } + BT_ASSERT(clock_class); + cc_uuid = bt_clock_class_get_uuid(clock_class); + cc_name = bt_clock_class_get_name(clock_class); - ret = compare_clock_snapshots_and_clock_classes( - left_end_cs, right_end_cs); - if (ret) { - goto end; + if (muxer_msg_iter->clock_class_expectation == + MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_ANY) { + /* + * This is the first clock class that this muxer message + * iterator encounters. Its properties determine what to expect + * for the whole lifetime of the iterator. + */ + if (bt_clock_class_origin_is_unix_epoch(clock_class)) { + /* Expect absolute clock classes */ + muxer_msg_iter->clock_class_expectation = + MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_ABSOLUTE; + } else { + if (cc_uuid) { + /* + * Expect non-absolute clock classes + * with a specific UUID. + */ + muxer_msg_iter->clock_class_expectation = + MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_NOT_ABS_SPEC_UUID; + bt_uuid_copy(muxer_msg_iter->expected_clock_class_uuid, cc_uuid); + } else { + /* + * Expect non-absolute clock classes + * with no UUID. + */ + muxer_msg_iter->clock_class_expectation = + MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_NOT_ABS_NO_UUID; } } + } - left_packet_count_avail = bt_message_discarded_packets_get_count( - msgs->left.msg, &left_packet_count); - right_packet_count_avail = bt_message_discarded_packets_get_count( - msgs->right.msg, &right_packet_count); - if (left_packet_count_avail == BT_PROPERTY_AVAILABILITY_AVAILABLE && - right_packet_count_avail == BT_PROPERTY_AVAILABILITY_AVAILABLE) { - ret = left_packet_count - right_packet_count; - if (ret != 0) { - goto end; - } - } else if (left_packet_count_avail == BT_PROPERTY_AVAILABILITY_AVAILABLE && - right_packet_count_avail == BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE) { - ret = -1; - goto end; - } else if (left_packet_count_avail == BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE && - right_packet_count_avail == BT_PROPERTY_AVAILABILITY_AVAILABLE) { - ret = 1; - goto end; + switch (muxer_msg_iter->clock_class_expectation) { + case MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_ABSOLUTE: + if (!bt_clock_class_origin_is_unix_epoch(clock_class)) { + BT_COMP_LOGE("Expecting an absolute clock class, " + "but got a non-absolute one: " + "clock-class-addr=%p, clock-class-name=\"%s\"", + clock_class, cc_name); + goto error; + } + break; + case MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_NOT_ABS_NO_UUID: + if (bt_clock_class_origin_is_unix_epoch(clock_class)) { + BT_COMP_LOGE("Expecting a non-absolute clock class with no UUID, " + "but got an absolute one: " + "clock-class-addr=%p, clock-class-name=\"%s\"", + clock_class, cc_name); + goto error; } + if (cc_uuid) { + BT_COMP_LOGE("Expecting a non-absolute clock class with no UUID, " + "but got one with a UUID: " + "clock-class-addr=%p, clock-class-name=\"%s\", " + "uuid=\"" BT_UUID_FMT "\"", + clock_class, cc_name, BT_UUID_FMT_VALUES(cc_uuid)); + goto error; + } break; - } - case BT_MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY: - { - const bt_clock_snapshot *left_cs = - bt_message_message_iterator_inactivity_borrow_default_clock_snapshot_const(msgs->left.msg); - const bt_clock_snapshot *right_cs = - bt_message_message_iterator_inactivity_borrow_default_clock_snapshot_const(msgs->right.msg); - - ret = compare_clock_snapshots_and_clock_classes( - left_cs, right_cs); - if (ret != 0) { - goto end; + case MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_NOT_ABS_SPEC_UUID: + if (bt_clock_class_origin_is_unix_epoch(clock_class)) { + BT_COMP_LOGE("Expecting a non-absolute clock class with a specific UUID, " + "but got an absolute one: " + "clock-class-addr=%p, clock-class-name=\"%s\"", + clock_class, cc_name); + goto error; + } + + if (!cc_uuid) { + BT_COMP_LOGE("Expecting a non-absolute clock class with a specific UUID, " + "but got one with no UUID: " + "clock-class-addr=%p, clock-class-name=\"%s\"", + clock_class, cc_name); + goto error; } + if (bt_uuid_compare(muxer_msg_iter->expected_clock_class_uuid, cc_uuid) != 0) { + BT_COMP_LOGE("Expecting a non-absolute clock class with a specific UUID, " + "but got one with different UUID: " + "clock-class-addr=%p, clock-class-name=\"%s\", " + "expected-uuid=\"" BT_UUID_FMT "\", " + "uuid=\"" BT_UUID_FMT "\"", + clock_class, cc_name, + BT_UUID_FMT_VALUES(muxer_msg_iter->expected_clock_class_uuid), + BT_UUID_FMT_VALUES(cc_uuid)); + goto error; + } break; - } + case MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_NONE: + BT_COMP_LOGE("Expecting no clock class, but got one: " + "clock-class-addr=%p, clock-class-name=\"%s\"", + clock_class, cc_name); + goto error; default: + /* Unexpected */ + BT_COMP_LOGF("Unexpected clock class expectation: " + "expectation-code=%d", + muxer_msg_iter->clock_class_expectation); abort(); } + goto end; + +error: + ret = -1; + end: return ret; } -static -int compare_messages(const bt_message *left_msg, const bt_message *right_msg) +static inline +int validate_new_stream_clock_class(struct muxer_msg_iter *muxer_msg_iter, + struct muxer_comp *muxer_comp, const bt_stream *stream) { int ret = 0; - struct messages_to_compare msgs; - - BT_ASSERT(left_msg != right_msg); - - msgs.left.msg = left_msg; - msgs.left.trace = borrow_trace(left_msg); - msgs.left.stream = borrow_stream(left_msg); - - msgs.right.msg = right_msg; - msgs.right.trace = borrow_trace(right_msg); - msgs.right.stream = borrow_stream(right_msg); - - /* Same timestamp: compare trace names. */ - ret = compare_messages_by_trace_name(&msgs); - if (ret) { - goto end; - } - - /* Same timestamp and trace name: compare trace UUIDs. */ - ret = compare_messages_by_trace_uuid(&msgs); - if (ret) { - goto end; - } + const bt_stream_class *stream_class = + bt_stream_borrow_class_const(stream); + const bt_clock_class *clock_class = + bt_stream_class_borrow_default_clock_class_const(stream_class); - /* - * Same timestamp, trace name, and trace UUID: compare stream class - * IDs. - */ - ret = compare_messages_by_stream_class_id(&msgs); - if (ret) { - goto end; - } + if (!clock_class) { + if (muxer_msg_iter->clock_class_expectation == + MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_ANY) { + /* Expect no clock class */ + muxer_msg_iter->clock_class_expectation = + MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_NONE; + } else if (muxer_msg_iter->clock_class_expectation != + MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_NONE) { + BT_COMP_LOGE("Expecting stream class without a default clock class: " + "stream-class-addr=%p, stream-class-name=\"%s\", " + "stream-class-id=%" PRIu64, + stream_class, bt_stream_class_get_name(stream_class), + bt_stream_class_get_id(stream_class)); + ret = -1; + } - /* - * Same timestamp, trace name, trace UUID, and stream class ID: compare - * stream IDs. - */ - ret = compare_messages_by_stream_id(&msgs); - if (ret) { goto end; } - if (bt_message_get_type(msgs.left.msg) != - bt_message_get_type(msgs.right.msg)) { - /* - * The messages are of different type, we order (arbitrarily) - * in the following way: - * SB < PB < EV < DE < MI < PE < DP < SE - */ - ret = compare_messages_by_type(&msgs); - if (ret) { - goto end; - } - } else { - /* The messages are of the same type. */ - ret = compare_messages_same_type(&msgs); - if (ret) { - goto end; - } - } + ret = validate_clock_class(muxer_msg_iter, muxer_comp, clock_class); end: return ret; @@ -1832,7 +851,13 @@ muxer_msg_iter_youngest_upstream_msg_iter( goto end; } - if (msg_ts_ns < youngest_ts_ns) { + /* + * Update the current message iterator if it has not been set + * yet, or if its current message has a timestamp smaller than + * the previously selected youngest message. + */ + if (G_UNLIKELY(*muxer_upstream_msg_iter == NULL) || + msg_ts_ns < youngest_ts_ns) { *muxer_upstream_msg_iter = cur_muxer_upstream_msg_iter; youngest_ts_ns = msg_ts_ns; @@ -1852,7 +877,7 @@ muxer_msg_iter_youngest_upstream_msg_iter( * Order the messages in an arbitrary but determinitic * way. */ - ret = compare_messages(msg, selected_msg); + ret = common_muxing_compare_messages(msg, selected_msg); if (ret < 0) { /* * The `msg` should go first. Update the next @@ -2121,12 +1146,15 @@ void destroy_muxer_msg_iter(struct muxer_msg_iter *muxer_msg_iter) } static -int muxer_msg_iter_init_upstream_iterators(struct muxer_comp *muxer_comp, - struct muxer_msg_iter *muxer_msg_iter) +bt_component_class_message_iterator_initialize_method_status +muxer_msg_iter_init_upstream_iterators(struct muxer_comp *muxer_comp, + struct muxer_msg_iter *muxer_msg_iter, + struct bt_self_message_iterator_configuration *config) { int64_t count; int64_t i; - int ret = 0; + bt_component_class_message_iterator_initialize_method_status status; + bool can_seek_forward = true; count = bt_component_filter_get_input_port_count( bt_self_component_filter_as_component_filter( @@ -2135,6 +1163,7 @@ int muxer_msg_iter_init_upstream_iterators(struct muxer_comp *muxer_comp, BT_COMP_LOGD("No input port to initialize for muxer component's message iterator: " "muxer-comp-addr=%p, muxer-msg-iter-addr=%p", muxer_comp, muxer_msg_iter); + status = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_OK; goto end; } @@ -2144,6 +1173,9 @@ int muxer_msg_iter_init_upstream_iterators(struct muxer_comp *muxer_comp, bt_self_component_filter_borrow_input_port_by_index( muxer_comp->self_comp_flt, i); const bt_port *port; + bt_self_component_port_input_message_iterator_create_from_message_iterator_status + msg_iter_status; + int int_status; BT_ASSERT(self_port); port = bt_self_component_port_as_port( @@ -2156,40 +1188,52 @@ int muxer_msg_iter_init_upstream_iterators(struct muxer_comp *muxer_comp, continue; } - upstream_msg_iter = create_msg_iter_on_input_port(muxer_comp, - muxer_msg_iter, self_port); - if (!upstream_msg_iter) { + msg_iter_status = create_msg_iter_on_input_port(muxer_comp, + muxer_msg_iter, self_port, &upstream_msg_iter); + if (msg_iter_status != BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_CREATE_FROM_MESSAGE_ITERATOR_STATUS_OK) { /* create_msg_iter_on_input_port() logs errors */ - BT_ASSERT(!upstream_msg_iter); - ret = -1; + status = (int) msg_iter_status; goto end; } - ret = muxer_msg_iter_add_upstream_msg_iter(muxer_msg_iter, + int_status = muxer_msg_iter_add_upstream_msg_iter(muxer_msg_iter, upstream_msg_iter); bt_self_component_port_input_message_iterator_put_ref( upstream_msg_iter); - if (ret) { + if (int_status) { + status = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_ERROR; /* muxer_msg_iter_add_upstream_msg_iter() logs errors */ goto end; } + + can_seek_forward = can_seek_forward && + bt_self_component_port_input_message_iterator_can_seek_forward( + upstream_msg_iter); } + /* + * This iterator can seek forward if all of its iterators can seek + * forward. + */ + bt_self_message_iterator_configuration_set_can_seek_forward( + config, can_seek_forward); + + status = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_OK; + end: - return ret; + return status; } BT_HIDDEN -bt_component_class_message_iterator_init_method_status muxer_msg_iter_init( +bt_component_class_message_iterator_initialize_method_status muxer_msg_iter_init( bt_self_message_iterator *self_msg_iter, + bt_self_message_iterator_configuration *config, bt_self_component_filter *self_comp, bt_self_component_port_output *port) { struct muxer_comp *muxer_comp = NULL; struct muxer_msg_iter *muxer_msg_iter = NULL; - bt_component_class_message_iterator_init_method_status status = - BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INIT_METHOD_STATUS_OK; - int ret; + bt_component_class_message_iterator_initialize_method_status status; muxer_comp = bt_self_component_get_data( bt_self_component_filter_as_self_component(self_comp)); @@ -2207,6 +1251,7 @@ bt_component_class_message_iterator_init_method_status muxer_msg_iter_init( BT_COMP_LOGE("Recursive initialization of muxer component's message iterator: " "comp-addr=%p, muxer-comp-addr=%p, msg-iter-addr=%p", self_comp, muxer_comp, self_msg_iter); + status = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_ERROR; goto error; } @@ -2214,6 +1259,7 @@ bt_component_class_message_iterator_init_method_status muxer_msg_iter_init( muxer_msg_iter = g_new0(struct muxer_msg_iter, 1); if (!muxer_msg_iter) { BT_COMP_LOGE_STR("Failed to allocate one muxer component's message iterator."); + status = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_MEMORY_ERROR; goto error; } @@ -2225,6 +1271,7 @@ bt_component_class_message_iterator_init_method_status muxer_msg_iter_init( (GDestroyNotify) destroy_muxer_upstream_msg_iter); if (!muxer_msg_iter->active_muxer_upstream_msg_iters) { BT_COMP_LOGE_STR("Failed to allocate a GPtrArray."); + status = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_MEMORY_ERROR; goto error; } @@ -2233,17 +1280,18 @@ bt_component_class_message_iterator_init_method_status muxer_msg_iter_init( (GDestroyNotify) destroy_muxer_upstream_msg_iter); if (!muxer_msg_iter->ended_muxer_upstream_msg_iters) { BT_COMP_LOGE_STR("Failed to allocate a GPtrArray."); + status = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_MEMORY_ERROR; goto error; } - ret = muxer_msg_iter_init_upstream_iterators(muxer_comp, - muxer_msg_iter); - if (ret) { + status = muxer_msg_iter_init_upstream_iterators(muxer_comp, + muxer_msg_iter, config); + if (status) { BT_COMP_LOGE("Cannot initialize connected input ports for muxer component's message iterator: " "comp-addr=%p, muxer-comp-addr=%p, " "muxer-msg-iter-addr=%p, msg-iter-addr=%p, ret=%d", self_comp, muxer_comp, muxer_msg_iter, - self_msg_iter, ret); + self_msg_iter, status); goto error; } @@ -2257,7 +1305,6 @@ bt_component_class_message_iterator_init_method_status muxer_msg_iter_init( error: destroy_muxer_msg_iter(muxer_msg_iter); bt_self_message_iterator_set_data(self_msg_iter, NULL); - status = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INIT_METHOD_STATUS_ERROR; end: muxer_comp->initializing_muxer_msg_iter = false; @@ -2359,49 +1406,58 @@ end: } static inline -bt_bool muxer_upstream_msg_iters_can_all_seek_beginning( - GPtrArray *muxer_upstream_msg_iters) +bt_component_class_message_iterator_can_seek_beginning_method_status +muxer_upstream_msg_iters_can_all_seek_beginning( + GPtrArray *muxer_upstream_msg_iters, bt_bool *can_seek) { + bt_component_class_message_iterator_can_seek_beginning_method_status status = + BT_COMPONENT_CLASS_MESSAGE_ITERATOR_CAN_SEEK_BEGINNING_METHOD_STATUS_OK; uint64_t i; - bt_bool ret = BT_TRUE; for (i = 0; i < muxer_upstream_msg_iters->len; i++) { struct muxer_upstream_msg_iter *upstream_msg_iter = muxer_upstream_msg_iters->pdata[i]; + status = (int) bt_self_component_port_input_message_iterator_can_seek_beginning( + upstream_msg_iter->msg_iter, can_seek); + if (status != BT_COMPONENT_CLASS_MESSAGE_ITERATOR_CAN_SEEK_BEGINNING_METHOD_STATUS_OK) { + goto end; + } - if (!bt_self_component_port_input_message_iterator_can_seek_beginning( - upstream_msg_iter->msg_iter)) { - ret = BT_FALSE; + if (!*can_seek) { goto end; } } + *can_seek = BT_TRUE; + end: - return ret; + return status; } BT_HIDDEN -bt_bool muxer_msg_iter_can_seek_beginning( - bt_self_message_iterator *self_msg_iter) +bt_component_class_message_iterator_can_seek_beginning_method_status +muxer_msg_iter_can_seek_beginning( + bt_self_message_iterator *self_msg_iter, bt_bool *can_seek) { struct muxer_msg_iter *muxer_msg_iter = bt_self_message_iterator_get_data(self_msg_iter); - bt_bool ret = BT_TRUE; + bt_component_class_message_iterator_can_seek_beginning_method_status status; - if (!muxer_upstream_msg_iters_can_all_seek_beginning( - muxer_msg_iter->active_muxer_upstream_msg_iters)) { - ret = BT_FALSE; + status = muxer_upstream_msg_iters_can_all_seek_beginning( + muxer_msg_iter->active_muxer_upstream_msg_iters, can_seek); + if (status != BT_COMPONENT_CLASS_MESSAGE_ITERATOR_CAN_SEEK_BEGINNING_METHOD_STATUS_OK) { goto end; } - if (!muxer_upstream_msg_iters_can_all_seek_beginning( - muxer_msg_iter->ended_muxer_upstream_msg_iters)) { - ret = BT_FALSE; + if (!*can_seek) { goto end; } + status = muxer_upstream_msg_iters_can_all_seek_beginning( + muxer_msg_iter->ended_muxer_upstream_msg_iters, can_seek); + end: - return ret; + return status; } BT_HIDDEN