X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=src%2Fplugins%2Fctf%2Fcommon%2Fmsg-iter%2Fmsg-iter.c;h=dd350c75ecfe4bb52f7b3b3904aeff1a5fed0334;hb=fe4df857056b4a03898f1031f136359ce733b0f5;hp=4d99d8145fe5a9a164fabef40f67a8bbba70a8bb;hpb=3682dd062f77d3fcb2637f600d9b93011a02e28c;p=babeltrace.git diff --git a/src/plugins/ctf/common/msg-iter/msg-iter.c b/src/plugins/ctf/common/msg-iter/msg-iter.c index 4d99d814..dd350c75 100644 --- a/src/plugins/ctf/common/msg-iter/msg-iter.c +++ b/src/plugins/ctf/common/msg-iter/msg-iter.c @@ -104,10 +104,12 @@ enum state { STATE_DSCOPE_EVENT_PAYLOAD_BEGIN, STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE, STATE_EMIT_MSG_EVENT, + STATE_EMIT_QUEUED_MSG_EVENT, STATE_SKIP_PACKET_PADDING, STATE_EMIT_MSG_PACKET_END_MULTI, STATE_EMIT_MSG_PACKET_END_SINGLE, STATE_CHECK_EMIT_MSG_STREAM_END, + STATE_EMIT_QUEUED_MSG_PACKET_END, STATE_EMIT_MSG_STREAM_END, STATE_DONE, }; @@ -181,6 +183,12 @@ struct bt_msg_iter { /* Current event message (NULL if not created yet) */ bt_message *event_msg; + /* + * True if we need to emit a packet beginning message before we emit + * the next event message or the packet end message. + */ + bool emit_delayed_packet_beginning_msg; + /* Database of current dynamic scopes */ struct { bt_field *stream_packet_context; @@ -308,12 +316,16 @@ const char *state_string(enum state state) return "DSCOPE_EVENT_PAYLOAD_CONTINUE"; case STATE_EMIT_MSG_EVENT: return "EMIT_MSG_EVENT"; + case STATE_EMIT_QUEUED_MSG_EVENT: + return "EMIT_QUEUED_MSG_EVENT"; case STATE_SKIP_PACKET_PADDING: return "SKIP_PACKET_PADDING"; case STATE_EMIT_MSG_PACKET_END_MULTI: return "EMIT_MSG_PACKET_END_MULTI"; case STATE_EMIT_MSG_PACKET_END_SINGLE: return "EMIT_MSG_PACKET_END_SINGLE"; + case STATE_EMIT_QUEUED_MSG_PACKET_END: + return "EMIT_QUEUED_MSG_PACKET_END"; case STATE_EMIT_MSG_STREAM_END: return "EMIT_MSG_STREAM_END"; case STATE_DONE: @@ -1731,6 +1743,9 @@ enum bt_msg_iter_status handle_state(struct bt_msg_iter *notit) case STATE_EMIT_MSG_EVENT: notit->state = STATE_DSCOPE_EVENT_HEADER_BEGIN; break; + case STATE_EMIT_QUEUED_MSG_EVENT: + notit->state = STATE_EMIT_MSG_EVENT; + break; case STATE_SKIP_PACKET_PADDING: status = skip_packet_padding_state(notit); break; @@ -1743,6 +1758,9 @@ enum bt_msg_iter_status handle_state(struct bt_msg_iter *notit) case STATE_CHECK_EMIT_MSG_STREAM_END: status = check_emit_msg_stream_end(notit); break; + case STATE_EMIT_QUEUED_MSG_PACKET_END: + notit->state = STATE_EMIT_MSG_PACKET_END_SINGLE; + break; case STATE_EMIT_MSG_STREAM_END: notit->state = STATE_DONE; break; @@ -2095,11 +2113,17 @@ enum bt_bfcr_status bfcr_floating_point_cb(double value, } field = borrow_next_field(notit); + bt_field_class_type type = bt_field_get_class_type(field); BT_ASSERT(field); BT_ASSERT(bt_field_borrow_class_const(field) == fc->ir_fc); - BT_ASSERT(bt_field_get_class_type(field) == - BT_FIELD_CLASS_TYPE_REAL); - bt_field_real_set_value(field, value); + BT_ASSERT(type == BT_FIELD_CLASS_TYPE_DOUBLE_PRECISION_REAL || + type == BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL); + + if (type == BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL) { + bt_field_real_single_precision_set_value(field, (float) value); + } else { + bt_field_real_double_precision_set_value(field, value); + } stack_top(notit->stack)->index++; end: @@ -2465,20 +2489,13 @@ void create_msg_stream_end(struct bt_msg_iter *notit, bt_message **message) static void create_msg_packet_beginning(struct bt_msg_iter *notit, - bt_message **message) + bt_message **message, bool use_default_cs) { int ret; - enum bt_msg_iter_status status; bt_message *msg = NULL; - const bt_stream_class *sc; - - status = set_current_packet(notit); - if (status != BT_MSG_ITER_STATUS_OK) { - goto end; - } + const bt_stream_class *sc = notit->meta.sc->ir_sc; BT_ASSERT(notit->packet); - sc = notit->meta.sc->ir_sc; BT_ASSERT(sc); if (notit->packet_context_field) { @@ -2504,9 +2521,21 @@ void create_msg_packet_beginning(struct bt_msg_iter *notit, if (notit->meta.sc->packets_have_ts_begin) { BT_ASSERT(notit->snapshots.beginning_clock != UINT64_C(-1)); + uint64_t raw_cs_value; + + /* + * Either use the decoded packet `timestamp_begin` field or the + * current stream's default clock_snapshot. + */ + if (use_default_cs) { + raw_cs_value = notit->default_clock_snapshot; + } else { + raw_cs_value = notit->snapshots.beginning_clock; + } + msg = bt_message_packet_beginning_create_with_default_clock_snapshot( notit->msg_iter, notit->packet, - notit->snapshots.beginning_clock); + raw_cs_value); } else { msg = bt_message_packet_beginning_create(notit->msg_iter, notit->packet); @@ -2525,17 +2554,86 @@ end: return; } +static +void emit_delayed_packet_beg_msg(struct bt_msg_iter *notit, + bt_message **message) +{ + bool packet_beg_ts_need_fix_up; + + notit->emit_delayed_packet_beginning_msg = false; + + /* + * Only fix the packet's timestamp_begin if it's larger than the first + * event of the packet. If there was no event in the packet, the + * `default_clock_snapshot` field will be either equal or greater than + * `snapshots.beginning_clock` so there is not fix needed. + */ + packet_beg_ts_need_fix_up = + notit->default_clock_snapshot < notit->snapshots.beginning_clock; + + /* create_msg_packet_beginning() logs errors */ + create_msg_packet_beginning(notit, message, packet_beg_ts_need_fix_up); + + return; +} + + static void create_msg_packet_end(struct bt_msg_iter *notit, bt_message **message) { bt_message *msg; + bool update_default_cs = true; if (!notit->packet) { return; } - /* Update default clock from packet's end time */ - if (notit->snapshots.end_clock != UINT64_C(-1)) { + /* + * Check if we need to emit the delayed packet + * beginning message instead of the packet end message. + */ + if (G_UNLIKELY(notit->emit_delayed_packet_beginning_msg)) { + emit_delayed_packet_beg_msg(notit, message); + /* Don't forget to emit the packet end message. */ + notit->state = STATE_EMIT_QUEUED_MSG_PACKET_END; + return; + } + + /* Check if may be affected by lttng-crash timestamp_end quirk. */ + if (G_UNLIKELY(notit->meta.tc->quirks.lttng_crash)) { + /* + * Check if the `timestamp_begin` field is non-zero but + * `timestamp_end` is zero. It means the trace is affected by + * the lttng-crash packet `timestamp_end` quirk and must be + * fixed up by omitting to update the default clock snapshot to + * the `timestamp_end` as is typically done. + */ + if (notit->snapshots.beginning_clock != 0 && + notit->snapshots.end_clock == 0) { + update_default_cs = false; + } + } + + /* + * Check if may be affected by lttng event-after-packet `timestamp_end` + * quirk. + */ + if (notit->meta.tc->quirks.lttng_event_after_packet) { + /* + * Check if `timestamp_end` is smaller then the current + * default_clock_snapshot (which is set to the last event + * decoded). It means the trace is affected by the lttng + * `event-after-packet` packet `timestamp_end` quirk and must + * be fixed up by omitting to update the default clock snapshot + * to the `timestamp_end` as is typically done. + */ + if (notit->snapshots.end_clock < notit->default_clock_snapshot) { + update_default_cs = false; + } + } + + /* Update default clock from packet's end time. */ + if (notit->snapshots.end_clock != UINT64_C(-1) && update_default_cs) { notit->default_clock_snapshot = notit->snapshots.end_clock; } @@ -2545,7 +2643,7 @@ void create_msg_packet_end(struct bt_msg_iter *notit, bt_message **message) BT_ASSERT(notit->snapshots.end_clock != UINT64_C(-1)); msg = bt_message_packet_end_create_with_default_clock_snapshot( notit->msg_iter, notit->packet, - notit->snapshots.end_clock); + notit->default_clock_snapshot); } else { msg = bt_message_packet_end_create(notit->msg_iter, notit->packet); @@ -2779,8 +2877,27 @@ enum bt_msg_iter_status bt_msg_iter_get_next_message( switch (notit->state) { case STATE_EMIT_MSG_EVENT: BT_ASSERT(notit->event_msg); - *message = notit->event_msg; - notit->event_msg = NULL; + + /* + * Check if we need to emit the delayed packet + * beginning message instead of the event message. + */ + if (G_UNLIKELY(notit->emit_delayed_packet_beginning_msg)) { + emit_delayed_packet_beg_msg(notit, message); + if (!*message) { + status = BT_MSG_ITER_STATUS_ERROR; + } + + /* + * Don't forget to emit the event message of + * the event record that was just decoded. + */ + notit->state = STATE_EMIT_QUEUED_MSG_EVENT; + + } else { + *message = notit->event_msg; + notit->event_msg = NULL; + } goto end; case STATE_EMIT_MSG_DISCARDED_EVENTS: /* create_msg_discared_events() logs errors */ @@ -2801,11 +2918,26 @@ enum bt_msg_iter_status bt_msg_iter_get_next_message( goto end; case STATE_EMIT_MSG_PACKET_BEGINNING: - /* create_msg_packet_beginning() logs errors */ - create_msg_packet_beginning(notit, message); + status = set_current_packet(notit); + if (status != BT_MSG_ITER_STATUS_OK) { + goto end; + } - if (!*message) { - status = BT_MSG_ITER_STATUS_ERROR; + if (G_UNLIKELY(notit->meta.tc->quirks.barectf_event_before_packet)) { + notit->emit_delayed_packet_beginning_msg = true; + /* + * There is no message to return yet as this + * packet beginning message is delayed until we + * decode the first event message of the + * packet. + */ + break; + } else { + /* create_msg_packet_beginning() logs errors */ + create_msg_packet_beginning(notit, message, false); + if (!*message) { + status = BT_MSG_ITER_STATUS_ERROR; + } } goto end; @@ -2851,9 +2983,8 @@ end: } static -enum bt_msg_iter_status decode_until_state( - struct bt_msg_iter *notit, enum state target_state_1, - enum state target_state_2) +enum bt_msg_iter_status decode_until_state( struct bt_msg_iter *notit, + enum state target_state_1, enum state target_state_2) { enum bt_msg_iter_status status = BT_MSG_ITER_STATUS_OK; @@ -2906,9 +3037,11 @@ enum bt_msg_iter_status decode_until_state( case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN: case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE: case STATE_EMIT_MSG_EVENT: + case STATE_EMIT_QUEUED_MSG_EVENT: case STATE_SKIP_PACKET_PADDING: case STATE_EMIT_MSG_PACKET_END_MULTI: case STATE_EMIT_MSG_PACKET_END_SINGLE: + case STATE_EMIT_QUEUED_MSG_PACKET_END: case STATE_CHECK_EMIT_MSG_STREAM_END: case STATE_EMIT_MSG_STREAM_END: break; @@ -2994,6 +3127,42 @@ end: return ret; } +static +enum bt_msg_iter_status clock_snapshot_at_msg_iter_state( + struct bt_msg_iter *notit, enum state target_state_1, + enum state target_state_2, uint64_t *clock_snapshot) +{ + enum bt_msg_iter_status status = BT_MSG_ITER_STATUS_OK; + + BT_ASSERT(notit); + BT_ASSERT(clock_snapshot); + status = decode_until_state(notit, target_state_1, target_state_2); + if (status != BT_MSG_ITER_STATUS_OK) { + goto end; + } + + *clock_snapshot = notit->default_clock_snapshot; +end: + return status; +} + +BT_HIDDEN +enum bt_msg_iter_status bt_msg_iter_curr_packet_first_event_clock_snapshot( + struct bt_msg_iter *notit, uint64_t *first_clock_snapshot) +{ + return clock_snapshot_at_msg_iter_state(notit, + STATE_AFTER_EVENT_HEADER, -1, first_clock_snapshot); +} + +BT_HIDDEN +enum bt_msg_iter_status bt_msg_iter_curr_packet_last_event_clock_snapshot( + struct bt_msg_iter *notit, uint64_t *last_clock_snapshot) +{ + return clock_snapshot_at_msg_iter_state(notit, + STATE_EMIT_MSG_PACKET_END_SINGLE, + STATE_EMIT_MSG_PACKET_END_MULTI, last_clock_snapshot); +} + BT_HIDDEN enum bt_msg_iter_status bt_msg_iter_get_packet_properties( struct bt_msg_iter *notit,