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,
};
/* 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;
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:
{
struct bt_msg_iter *notit;
- BT_ASSERT(stack);
+ BT_ASSERT_DBG(stack);
notit = stack->notit;
BT_COMP_LOGD("Destroying stack: addr=%p", stack);
struct stack_entry *entry;
struct bt_msg_iter *notit;
- BT_ASSERT(stack);
+ BT_ASSERT_DBG(stack);
notit = stack->notit;
- BT_ASSERT(base);
+ BT_ASSERT_DBG(base);
BT_COMP_LOGT("Pushing base field on stack: stack-addr=%p, "
"stack-size-before=%zu, stack-size-after=%zu",
stack, stack->size, stack->size + 1);
static inline
unsigned int stack_size(struct stack *stack)
{
- BT_ASSERT(stack);
+ BT_ASSERT_DBG(stack);
return stack->size;
}
{
struct bt_msg_iter *notit;
- BT_ASSERT(stack);
- BT_ASSERT(stack_size(stack));
+ BT_ASSERT_DBG(stack);
+ BT_ASSERT_DBG(stack_size(stack));
notit = stack->notit;
BT_COMP_LOGT("Popping from stack: "
"stack-addr=%p, stack-size-before=%zu, stack-size-after=%zu",
static inline
struct stack_entry *stack_top(struct stack *stack)
{
- BT_ASSERT(stack);
- BT_ASSERT(stack_size(stack));
+ BT_ASSERT_DBG(stack);
+ BT_ASSERT_DBG(stack_size(stack));
return &g_array_index(stack->entries, struct stack_entry,
stack->size - 1);
}
static
void stack_clear(struct stack *stack)
{
- BT_ASSERT(stack);
+ BT_ASSERT_DBG(stack);
stack->size = 0;
}
struct bt_msg_iter *notit)
{
struct ctf_field_class *packet_header_fc = NULL;
- enum bt_msg_iter_status ret = BT_MSG_ITER_STATUS_OK;
+ enum bt_msg_iter_status status = BT_MSG_ITER_STATUS_OK;
/*
* Make sure at least one bit is available for this packet. An
* empty packet is impossible. If we reach the end of the medium
* at this point, then it's considered the end of the stream.
*/
- ret = buf_ensure_available_bits(notit);
- switch (ret) {
+ status = buf_ensure_available_bits(notit);
+ switch (status) {
case BT_MSG_ITER_STATUS_OK:
break;
case BT_MSG_ITER_STATUS_EOF:
- ret = BT_MSG_ITER_STATUS_OK;
+ status = BT_MSG_ITER_STATUS_OK;
notit->state = STATE_CHECK_EMIT_MSG_STREAM_END;
goto end;
default:
BT_COMP_LOGD("Decoding packet header field:"
"notit-addr=%p, trace-class-addr=%p, fc-addr=%p",
notit, notit->meta.tc, packet_header_fc);
- ret = read_dscope_begin_state(notit, packet_header_fc,
+ status = read_dscope_begin_state(notit, packet_header_fc,
STATE_AFTER_TRACE_PACKET_HEADER,
STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE, NULL);
- if (ret < 0) {
+ if (status < 0) {
BT_COMP_LOGW("Cannot decode packet header field: "
"notit-addr=%p, trace-class-addr=%p, "
"fc-addr=%p",
}
end:
- return ret;
+ return status;
}
static
enum bt_msg_iter_status status = BT_MSG_ITER_STATUS_OK;
bt_packet *packet = NULL;
- BT_COMP_LOGD("Creating packet for packet message: "
- "notit-addr=%p", notit);
BT_COMP_LOGD("Creating packet from stream: "
"notit-addr=%p, stream-addr=%p, "
"stream-class-addr=%p, "
enum bt_msg_iter_status status = BT_MSG_ITER_STATUS_OK;
bt_message *msg = NULL;
- BT_ASSERT(notit->meta.ec);
- BT_ASSERT(notit->packet);
+ BT_ASSERT_DBG(notit->meta.ec);
+ BT_ASSERT_DBG(notit->packet);
BT_COMP_LOGD("Creating event message from event class and packet: "
"notit-addr=%p, ec-addr=%p, ec-name=\"%s\", packet-addr=%p",
notit, notit->meta.ec,
notit->meta.ec->name->str,
notit->packet);
- BT_ASSERT(notit->msg_iter);
- BT_ASSERT(notit->meta.sc);
+ BT_ASSERT_DBG(notit->msg_iter);
+ BT_ASSERT_DBG(notit->meta.sc);
if (bt_stream_class_borrow_default_clock_class(notit->meta.sc->ir_sc)) {
msg = bt_message_event_create_with_packet_and_default_clock_snapshot(
notit->event = bt_message_event_borrow_event(
notit->event_msg);
- BT_ASSERT(notit->event);
+ BT_ASSERT_DBG(notit->event);
next_state:
notit->state = STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN;
}
if (event_common_context_fc->in_ir && !notit->dry_run) {
- BT_ASSERT(!notit->dscopes.event_common_context);
+ BT_ASSERT_DBG(!notit->dscopes.event_common_context);
notit->dscopes.event_common_context =
bt_event_borrow_common_context_field(
notit->event);
- BT_ASSERT(notit->dscopes.event_common_context);
+ BT_ASSERT_DBG(notit->dscopes.event_common_context);
}
BT_COMP_LOGT("Decoding event common context field: "
}
if (event_spec_context_fc->in_ir && !notit->dry_run) {
- BT_ASSERT(!notit->dscopes.event_spec_context);
+ BT_ASSERT_DBG(!notit->dscopes.event_spec_context);
notit->dscopes.event_spec_context =
bt_event_borrow_specific_context_field(
notit->event);
- BT_ASSERT(notit->dscopes.event_spec_context);
+ BT_ASSERT_DBG(notit->dscopes.event_spec_context);
}
BT_COMP_LOGT("Decoding event specific context field: "
}
if (event_payload_fc->in_ir && !notit->dry_run) {
- BT_ASSERT(!notit->dscopes.event_payload);
+ BT_ASSERT_DBG(!notit->dscopes.event_payload);
notit->dscopes.event_payload =
bt_event_borrow_payload_field(
notit->event);
- BT_ASSERT(notit->dscopes.event_payload);
+ BT_ASSERT_DBG(notit->dscopes.event_payload);
}
BT_COMP_LOGT("Decoding event payload field: "
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;
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;
bt_field *next_field = NULL;
bt_field *base_field;
const bt_field_class *base_fc;
+ bt_field_class_type base_fc_type;
size_t index;
- BT_ASSERT(!stack_empty(notit->stack));
+ BT_ASSERT_DBG(!stack_empty(notit->stack));
index = stack_top(notit->stack)->index;
base_field = stack_top(notit->stack)->base;
- BT_ASSERT(base_field);
+ BT_ASSERT_DBG(base_field);
base_fc = bt_field_borrow_class_const(base_field);
- BT_ASSERT(base_fc);
+ BT_ASSERT_DBG(base_fc);
+ base_fc_type = bt_field_class_get_type(base_fc);
- switch (bt_field_class_get_type(base_fc)) {
- case BT_FIELD_CLASS_TYPE_STRUCTURE:
- {
- BT_ASSERT(index <
+ if (base_fc_type == BT_FIELD_CLASS_TYPE_STRUCTURE) {
+ BT_ASSERT_DBG(index <
bt_field_class_structure_get_member_count(
bt_field_borrow_class_const(
base_field)));
next_field =
bt_field_structure_borrow_member_field_by_index(
base_field, index);
- break;
- }
- case BT_FIELD_CLASS_TYPE_STATIC_ARRAY:
- case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY:
- BT_ASSERT(index < bt_field_array_get_length(base_field));
+ } else if (bt_field_class_type_is(base_fc_type,
+ BT_FIELD_CLASS_TYPE_ARRAY)) {
+ BT_ASSERT_DBG(index < bt_field_array_get_length(base_field));
next_field = bt_field_array_borrow_element_field_by_index(
base_field, index);
- break;
- case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR:
- case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR:
- case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR:
- BT_ASSERT(index == 0);
+ } else if (bt_field_class_type_is(base_fc_type,
+ BT_FIELD_CLASS_TYPE_VARIANT)) {
+ BT_ASSERT_DBG(index == 0);
next_field = bt_field_variant_borrow_selected_option_field(
base_field);
- break;
- default:
+ } else {
abort();
}
- BT_ASSERT(next_field);
+ BT_ASSERT_DBG(next_field);
return next_field;
}
uint64_t new_val_mask;
uint64_t cur_value_masked;
- BT_ASSERT(new_val_size > 0);
+ BT_ASSERT_DBG(new_val_size > 0);
/*
* Special case for a 64-bit new value, which is the limit
}
field = borrow_next_field(notit);
- 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_UNSIGNED_INTEGER ||
- bt_field_get_class_type(field) ==
- BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION);
+ BT_ASSERT_DBG(field);
+ BT_ASSERT_DBG(bt_field_borrow_class_const(field) == fc->ir_fc);
+ BT_ASSERT_DBG(bt_field_class_type_is(bt_field_get_class_type(field),
+ BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER));
bt_field_integer_unsigned_set_value(field, value);
stack_top(notit->stack)->index++;
"notit-addr=%p, bfcr-addr=%p, fc-addr=%p, "
"fc-type=%d, fc-in-ir=%d, value=%" PRIu64,
notit, notit->bfcr, fc, fc->type, fc->in_ir, value);
- BT_ASSERT(int_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE);
- BT_ASSERT(!int_fc->mapped_clock_class);
- BT_ASSERT(int_fc->storing_index < 0);
+ BT_ASSERT_DBG(int_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE);
+ BT_ASSERT_DBG(!int_fc->mapped_clock_class);
+ BT_ASSERT_DBG(int_fc->storing_index < 0);
if (G_UNLIKELY(!fc->in_ir || notit->dry_run)) {
goto end;
}
string_field = stack_top(notit->stack)->base;
- BT_ASSERT(bt_field_get_class_type(string_field) ==
- BT_FIELD_CLASS_TYPE_STRING);
+ BT_ASSERT_DBG(bt_field_get_class_type(string_field) ==
+ BT_FIELD_CLASS_TYPE_STRING);
/* Append character */
str[0] = (char) value;
"notit-addr=%p, bfcr-addr=%p, fc-addr=%p, "
"fc-type=%d, fc-in-ir=%d, value=%" PRId64,
notit, notit->bfcr, fc, fc->type, fc->in_ir, value);
- BT_ASSERT(int_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE);
+ BT_ASSERT_DBG(int_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE);
if (G_UNLIKELY(int_fc->storing_index >= 0)) {
g_array_index(notit->stored_values, uint64_t,
}
field = borrow_next_field(notit);
- 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_SIGNED_INTEGER ||
- bt_field_get_class_type(field) ==
- BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION);
+ BT_ASSERT_DBG(field);
+ BT_ASSERT_DBG(bt_field_borrow_class_const(field) == fc->ir_fc);
+ BT_ASSERT_DBG(bt_field_class_type_is(bt_field_get_class_type(field),
+ BT_FIELD_CLASS_TYPE_SIGNED_INTEGER));
bt_field_integer_signed_set_value(field, value);
stack_top(notit->stack)->index++;
enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
bt_field *field = NULL;
struct bt_msg_iter *notit = data;
+ bt_field_class_type type;
BT_COMP_LOGT("Floating point number function called from BFCR: "
"notit-addr=%p, bfcr-addr=%p, fc-addr=%p, "
}
field = borrow_next_field(notit);
- 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);
+ type = bt_field_get_class_type(field);
+ BT_ASSERT_DBG(field);
+ BT_ASSERT_DBG(bt_field_borrow_class_const(field) == fc->ir_fc);
+ BT_ASSERT_DBG(bt_field_class_type_is(type, BT_FIELD_CLASS_TYPE_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:
}
field = borrow_next_field(notit);
- BT_ASSERT(field);
- BT_ASSERT(bt_field_borrow_class_const(field) == fc->ir_fc);
- BT_ASSERT(bt_field_get_class_type(field) ==
+ BT_ASSERT_DBG(field);
+ BT_ASSERT_DBG(bt_field_borrow_class_const(field) == fc->ir_fc);
+ BT_ASSERT_DBG(bt_field_get_class_type(field) ==
BT_FIELD_CLASS_TYPE_STRING);
bt_field_string_clear(field);
}
field = stack_top(notit->stack)->base;
- BT_ASSERT(field);
+ BT_ASSERT_DBG(field);
/* Append current substring */
ret = bt_field_string_append_with_length(field, value, len);
return BT_BFCR_STATUS_OK;
}
+static
enum bt_bfcr_status bfcr_compound_begin_cb(
struct ctf_field_class *fc, void *data)
{
field = notit->cur_dscope_field;
} else {
field = borrow_next_field(notit);
- BT_ASSERT(field);
+ BT_ASSERT_DBG(field);
}
/* Push field */
- BT_ASSERT(field);
- BT_ASSERT(bt_field_borrow_class_const(field) == fc->ir_fc);
+ BT_ASSERT_DBG(field);
+ BT_ASSERT_DBG(bt_field_borrow_class_const(field) == fc->ir_fc);
stack_push(notit->stack, field);
/*
struct ctf_field_class_array_base *array_fc = (void *) fc;
if (array_fc->is_text) {
- BT_ASSERT(bt_field_get_class_type(field) ==
+ BT_ASSERT_DBG(bt_field_get_class_type(field) ==
BT_FIELD_CLASS_TYPE_STRING);
notit->done_filling_string = false;
bt_field_string_clear(field);
return BT_BFCR_STATUS_OK;
}
+static
enum bt_bfcr_status bfcr_compound_end_cb(
struct ctf_field_class *fc, void *data)
{
goto end;
}
- BT_ASSERT(!stack_empty(notit->stack));
- BT_ASSERT(bt_field_borrow_class_const(stack_top(notit->stack)->base) ==
+ BT_ASSERT_DBG(!stack_empty(notit->stack));
+ BT_ASSERT_DBG(bt_field_borrow_class_const(stack_top(notit->stack)->base) ==
fc->ir_fc);
/*
struct ctf_field_class_array_base *array_fc = (void *) fc;
if (array_fc->is_text) {
- BT_ASSERT(bt_field_get_class_type(
+ BT_ASSERT_DBG(bt_field_get_class_type(
stack_top(notit->stack)->base) ==
BT_FIELD_CLASS_TYPE_STRING);
bt_bfcr_set_unsigned_int_cb(notit->bfcr,
}
seq_field = stack_top(notit->stack)->base;
- BT_ASSERT(seq_field);
+ BT_ASSERT_DBG(seq_field);
/*
* bfcr_get_sequence_length_cb() also gets called back for a
* is a sequence field.
*/
if (!seq_fc->base.is_text) {
- BT_ASSERT(bt_field_get_class_type(seq_field) ==
- BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY);
+ BT_ASSERT_DBG(bt_field_class_type_is(
+ bt_field_get_class_type(seq_field),
+ BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY));
ret = bt_field_array_dynamic_set_length(seq_field,
(uint64_t) length);
if (ret) {
}
static
-void create_msg_stream_beginning(struct bt_msg_iter *notit,
- bt_message **message)
+bt_message *create_msg_stream_beginning(struct bt_msg_iter *notit)
{
- bt_message *ret = NULL;
+ bt_message *msg;
BT_ASSERT(notit->stream);
BT_ASSERT(notit->msg_iter);
- ret = bt_message_stream_beginning_create(notit->msg_iter,
+ msg = bt_message_stream_beginning_create(notit->msg_iter,
notit->stream);
- if (!ret) {
+ if (!msg) {
BT_COMP_LOGE("Cannot create stream beginning message: "
"notit-addr=%p, stream-addr=%p",
notit, notit->stream);
- return;
}
- *message = ret;
+ return msg;
}
static
-void create_msg_stream_end(struct bt_msg_iter *notit, bt_message **message)
+bt_message *create_msg_stream_end(struct bt_msg_iter *notit)
{
- bt_message *ret;
+ bt_message *msg;
if (!notit->stream) {
BT_COMP_LOGE("Cannot create stream for stream message: "
"notit-addr=%p", notit);
- return;
+ msg = NULL;
+ goto end;
}
BT_ASSERT(notit->msg_iter);
- ret = bt_message_stream_end_create(notit->msg_iter,
+ msg = bt_message_stream_end_create(notit->msg_iter,
notit->stream);
- if (!ret) {
+ if (!msg) {
BT_COMP_LOGE("Cannot create stream end message: "
"notit-addr=%p, stream-addr=%p",
notit, notit->stream);
- return;
}
- *message = ret;
+end:
+ return msg;
}
static
-void create_msg_packet_beginning(struct bt_msg_iter *notit,
- bt_message **message)
+bt_message *create_msg_packet_beginning(struct bt_msg_iter *notit,
+ 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;
- }
+ bt_message *msg;
+ 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) {
ret = bt_packet_move_context_field(
notit->packet, notit->packet_context_field);
if (ret) {
+ msg = NULL;
goto end;
}
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);
goto end;
}
- *message = msg;
-
end:
- return;
+ return msg;
+}
+
+static
+bt_message *emit_delayed_packet_beg_msg(struct bt_msg_iter *notit)
+{
+ 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 */
+ return create_msg_packet_beginning(notit, packet_beg_ts_need_fix_up);
}
+
static
-void create_msg_packet_end(struct bt_msg_iter *notit, bt_message **message)
+bt_message *create_msg_packet_end(struct bt_msg_iter *notit)
{
bt_message *msg;
+ bool update_default_cs = true;
if (!notit->packet) {
- return;
+ msg = NULL;
+ goto end;
}
- /* 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)) {
+ msg = emit_delayed_packet_beg_msg(notit);
+ /* Don't forget to emit the packet end message. */
+ notit->state = STATE_EMIT_QUEUED_MSG_PACKET_END;
+ goto end;
+ }
+
+ /* 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;
}
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);
BT_COMP_LOGE("Cannot create packet end message: "
"notit-addr=%p, packet-addr=%p",
notit, notit->packet);
- return;
+ goto end;
}
BT_PACKET_PUT_REF_AND_RESET(notit->packet);
- *message = msg;
+
+end:
+ return msg;
}
static
-void create_msg_discarded_events(struct bt_msg_iter *notit,
- bt_message **message)
+bt_message *create_msg_discarded_events(struct bt_msg_iter *notit)
{
bt_message *msg;
uint64_t beginning_raw_value = UINT64_C(-1);
BT_COMP_LOGE("Cannot create discarded events message: "
"notit-addr=%p, stream-addr=%p",
notit, notit->stream);
- return;
+ goto end;
}
if (notit->prev_packet_snapshots.discarded_events != UINT64_C(-1)) {
notit->prev_packet_snapshots.discarded_events);
}
- *message = msg;
+end:
+ return msg;
}
static
-void create_msg_discarded_packets(struct bt_msg_iter *notit,
- bt_message **message)
+bt_message *create_msg_discarded_packets(struct bt_msg_iter *notit)
{
bt_message *msg;
BT_COMP_LOGE("Cannot create discarded packets message: "
"notit-addr=%p, stream-addr=%p",
notit, notit->stream);
- return;
+ goto end;
}
bt_message_discarded_packets_set_count(msg,
notit->snapshots.packets -
notit->prev_packet_snapshots.packets - 1);
- *message = msg;
+
+end:
+ return msg;
}
BT_HIDDEN
{
enum bt_msg_iter_status status = BT_MSG_ITER_STATUS_OK;
- BT_ASSERT(notit);
- BT_ASSERT(message);
+ BT_ASSERT_DBG(notit);
+ BT_ASSERT_DBG(message);
notit->msg_iter = msg_iter;
notit->set_stream = true;
BT_COMP_LOGD("Getting next message: notit-addr=%p", notit);
switch (notit->state) {
case STATE_EMIT_MSG_EVENT:
- BT_ASSERT(notit->event_msg);
- *message = notit->event_msg;
- notit->event_msg = NULL;
+ BT_ASSERT_DBG(notit->event_msg);
+
+ /*
+ * 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)) {
+ *message = emit_delayed_packet_beg_msg(notit);
+ 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 */
- create_msg_discarded_events(notit, message);
+ *message = create_msg_discarded_events(notit);
if (!*message) {
status = BT_MSG_ITER_STATUS_ERROR;
goto end;
case STATE_EMIT_MSG_DISCARDED_PACKETS:
/* create_msg_discared_packets() logs errors */
- create_msg_discarded_packets(notit, message);
+ *message = create_msg_discarded_packets(notit);
if (!*message) {
status = BT_MSG_ITER_STATUS_ERROR;
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 */
+ *message = create_msg_packet_beginning(notit, false);
+ if (!*message) {
+ status = BT_MSG_ITER_STATUS_ERROR;
+ }
}
goto end;
case STATE_EMIT_MSG_PACKET_END_SINGLE:
case STATE_EMIT_MSG_PACKET_END_MULTI:
/* create_msg_packet_end() logs errors */
- create_msg_packet_end(notit, message);
+ *message = create_msg_packet_end(notit);
if (!*message) {
status = BT_MSG_ITER_STATUS_ERROR;
goto end;
case STATE_EMIT_MSG_STREAM_BEGINNING:
/* create_msg_stream_beginning() logs errors */
- create_msg_stream_beginning(notit, message);
+ *message = create_msg_stream_beginning(notit);
if (!*message) {
status = BT_MSG_ITER_STATUS_ERROR;
goto end;
case STATE_EMIT_MSG_STREAM_END:
/* create_msg_stream_end() logs errors */
- create_msg_stream_end(notit, message);
+ *message = create_msg_stream_end(notit);
if (!*message) {
status = BT_MSG_ITER_STATUS_ERROR;
}
static
-enum bt_msg_iter_status read_packet_header_context_fields(
- struct bt_msg_iter *notit)
+enum bt_msg_iter_status decode_until_state( struct bt_msg_iter *notit,
+ enum state target_state_1, enum state target_state_2)
{
- int ret;
enum bt_msg_iter_status status = BT_MSG_ITER_STATUS_OK;
- BT_ASSERT(notit);
+ BT_ASSERT_DBG(notit);
notit->set_stream = false;
- if (notit->state == STATE_EMIT_MSG_PACKET_BEGINNING) {
- /* We're already there */
- goto end;
- }
+ do {
+ /*
+ * Check if we reached the state at which we want to stop
+ * decoding.
+ */
+ if (notit->state == target_state_1 ||
+ notit->state == target_state_2) {
+ goto end;
+ }
- while (true) {
status = handle_state(notit);
if (G_UNLIKELY(status == BT_MSG_ITER_STATUS_AGAIN)) {
BT_COMP_LOGD_STR("Medium returned BT_MSG_ITER_STATUS_AGAIN.");
}
switch (notit->state) {
- case STATE_EMIT_MSG_PACKET_BEGINNING:
- /*
- * Packet header and context fields are
- * potentially decoded (or they don't exist).
- */
- goto end;
case STATE_INIT:
case STATE_SWITCH_PACKET:
case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN:
case STATE_EMIT_MSG_DISCARDED_EVENTS:
case STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS:
case STATE_EMIT_MSG_DISCARDED_PACKETS:
- /* Non-emitting state: continue */
+ case STATE_EMIT_MSG_PACKET_BEGINNING:
+ case STATE_DSCOPE_EVENT_HEADER_BEGIN:
+ case STATE_DSCOPE_EVENT_HEADER_CONTINUE:
+ case STATE_AFTER_EVENT_HEADER:
+ case STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN:
+ case STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE:
+ case STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN:
+ case STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE:
+ 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;
+ case STATE_DONE:
+ /* fall-through */
default:
- /*
- * We should never get past the
- * STATE_EMIT_MSG_PACKET_BEGINNING state.
- */
+ /* We should never get to the STATE_DONE state. */
BT_COMP_LOGF("Unexpected state: notit-addr=%p, state=%s",
notit, state_string(notit->state));
abort();
}
- }
+ } while (true);
end:
+ return status;
+}
+
+static
+enum bt_msg_iter_status read_packet_header_context_fields(
+ struct bt_msg_iter *notit)
+{
+ int ret;
+ enum bt_msg_iter_status status = BT_MSG_ITER_STATUS_OK;
+
+ status = decode_until_state(notit, STATE_EMIT_MSG_PACKET_BEGINNING, -1);
+ if (status != BT_MSG_ITER_STATUS_OK) {
+ goto end;
+ }
+
ret = set_current_packet_content_sizes(notit);
if (ret) {
status = BT_MSG_ITER_STATUS_ERROR;
+ goto end;
}
+end:
return status;
}
enum bt_msg_iter_status bt_msg_iter_seek(struct bt_msg_iter *notit,
off_t offset)
{
- enum bt_msg_iter_status ret = BT_MSG_ITER_STATUS_OK;
+ enum bt_msg_iter_status status = BT_MSG_ITER_STATUS_OK;
enum bt_msg_iter_medium_status medium_status;
BT_ASSERT(notit);
if (offset < 0) {
BT_COMP_LOGE("Cannot seek to negative offset: offset=%jd", (intmax_t) offset);
- ret = BT_MSG_ITER_STATUS_INVAL;
+ status = BT_MSG_ITER_STATUS_INVAL;
goto end;
}
if (!notit->medium.medops.seek) {
- ret = BT_MSG_ITER_STATUS_UNSUPPORTED;
+ status = BT_MSG_ITER_STATUS_UNSUPPORTED;
BT_COMP_LOGD("Aborting seek as the iterator's underlying media does not implement seek support.");
goto end;
}
BT_MSG_ITER_SEEK_WHENCE_SET, offset, notit->medium.data);
if (medium_status != BT_MSG_ITER_MEDIUM_STATUS_OK) {
if (medium_status == BT_MSG_ITER_MEDIUM_STATUS_EOF) {
- ret = BT_MSG_ITER_STATUS_EOF;
+ status = BT_MSG_ITER_STATUS_EOF;
} else {
- ret = BT_MSG_ITER_STATUS_ERROR;
+ status = BT_MSG_ITER_STATUS_ERROR;
goto end;
}
}
notit->cur_packet_offset = offset;
end:
- return ret;
+ return status;
+}
+
+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_DBG(notit);
+ BT_ASSERT_DBG(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 status;
- BT_ASSERT(notit);
- BT_ASSERT(props);
+ BT_ASSERT_DBG(notit);
+ BT_ASSERT_DBG(props);
status = read_packet_header_context_fields(notit);
if (status != BT_MSG_ITER_STATUS_OK) {
goto end;