2 * SPDX-License-Identifier: MIT
4 * Copyright (c) 2015-2018 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2015-2018 Philippe Proulx <pproulx@efficios.com>
7 * Babeltrace - CTF message iterator
14 #include "common/assert.h"
15 #include "common/common.h"
16 #include "cpp-common/bt2c/fmt.hpp"
17 #include "cpp-common/bt2c/logging.hpp"
18 #include "cpp-common/bt2c/make-span.hpp"
19 #include "cpp-common/vendor/fmt/format.h"
21 #include "../bfcr/bfcr.hpp"
22 #include "msg-iter.hpp"
24 /* A visit stack entry */
28 * Current base field, one of:
40 /* Index of next field to set */
47 struct ctf_msg_iter
*msg_it
;
49 /* Entries (struct stack_entry) */
52 /* Number of active entries */
61 STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
,
62 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
,
63 STATE_AFTER_TRACE_PACKET_HEADER
,
64 STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
,
65 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
,
66 STATE_AFTER_STREAM_PACKET_CONTEXT
,
67 STATE_EMIT_MSG_STREAM_BEGINNING
,
68 STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS
,
69 STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS
,
70 STATE_EMIT_MSG_DISCARDED_EVENTS
,
71 STATE_EMIT_MSG_DISCARDED_PACKETS
,
72 STATE_EMIT_MSG_PACKET_BEGINNING
,
73 STATE_DSCOPE_EVENT_HEADER_BEGIN
,
74 STATE_DSCOPE_EVENT_HEADER_CONTINUE
,
75 STATE_AFTER_EVENT_HEADER
,
76 STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN
,
77 STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE
,
78 STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN
,
79 STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE
,
80 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
,
81 STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
,
83 STATE_EMIT_QUEUED_MSG_EVENT
,
84 STATE_SKIP_PACKET_PADDING
,
85 STATE_EMIT_MSG_PACKET_END_MULTI
,
86 STATE_EMIT_MSG_PACKET_END_SINGLE
,
87 STATE_EMIT_QUEUED_MSG_PACKET_END
,
88 STATE_CHECK_EMIT_MSG_STREAM_END
,
89 STATE_EMIT_MSG_STREAM_END
,
93 static __attribute__((used
)) const char *format_as(state state
)
99 case STATE_SWITCH_PACKET
:
100 return "STATE_SWITCH_PACKET";
102 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
:
103 return "STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN";
105 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
:
106 return "STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE";
108 case STATE_AFTER_TRACE_PACKET_HEADER
:
109 return "STATE_AFTER_TRACE_PACKET_HEADER";
111 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
:
112 return "STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN";
114 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
:
115 return "STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE";
117 case STATE_AFTER_STREAM_PACKET_CONTEXT
:
118 return "STATE_AFTER_STREAM_PACKET_CONTEXT";
120 case STATE_EMIT_MSG_STREAM_BEGINNING
:
121 return "STATE_EMIT_MSG_STREAM_BEGINNING";
123 case STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS
:
124 return "STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS";
126 case STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS
:
127 return "STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS";
129 case STATE_EMIT_MSG_DISCARDED_EVENTS
:
130 return "STATE_EMIT_MSG_DISCARDED_EVENTS";
132 case STATE_EMIT_MSG_DISCARDED_PACKETS
:
133 return "STATE_EMIT_MSG_DISCARDED_PACKETS";
135 case STATE_EMIT_MSG_PACKET_BEGINNING
:
136 return "STATE_EMIT_MSG_PACKET_BEGINNING";
138 case STATE_DSCOPE_EVENT_HEADER_BEGIN
:
139 return "STATE_DSCOPE_EVENT_HEADER_BEGIN";
141 case STATE_DSCOPE_EVENT_HEADER_CONTINUE
:
142 return "STATE_DSCOPE_EVENT_HEADER_CONTINUE";
144 case STATE_AFTER_EVENT_HEADER
:
145 return "STATE_AFTER_EVENT_HEADER";
147 case STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN
:
148 return "STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN";
150 case STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE
:
151 return "STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE";
153 case STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN
:
154 return "STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN";
156 case STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE
:
157 return "STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE";
159 case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
:
160 return "STATE_DSCOPE_EVENT_PAYLOAD_BEGIN";
162 case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
:
163 return "STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE";
165 case STATE_EMIT_MSG_EVENT
:
166 return "STATE_EMIT_MSG_EVENT";
168 case STATE_EMIT_QUEUED_MSG_EVENT
:
169 return "STATE_EMIT_QUEUED_MSG_EVENT";
171 case STATE_SKIP_PACKET_PADDING
:
172 return "STATE_SKIP_PACKET_PADDING";
174 case STATE_EMIT_MSG_PACKET_END_MULTI
:
175 return "STATE_EMIT_MSG_PACKET_END_MULTI";
177 case STATE_EMIT_MSG_PACKET_END_SINGLE
:
178 return "STATE_EMIT_MSG_PACKET_END_SINGLE";
180 case STATE_EMIT_QUEUED_MSG_PACKET_END
:
181 return "STATE_EMIT_QUEUED_MSG_PACKET_END";
183 case STATE_CHECK_EMIT_MSG_STREAM_END
:
184 return "STATE_CHECK_EMIT_MSG_STREAM_END";
186 case STATE_EMIT_MSG_STREAM_END
:
187 return "STATE_EMIT_MSG_STREAM_END";
196 struct end_of_packet_snapshots
198 uint64_t discarded_events
= 0;
199 uint64_t packets
= 0;
200 uint64_t beginning_clock
= 0;
201 uint64_t end_clock
= 0;
204 /* CTF message iterator */
207 explicit ctf_msg_iter(bt2c::Logger loggerParam
) noexcept
: logger
{std::move(loggerParam
)}
212 struct stack
*stack
= nullptr;
214 /* Current message iterator to create messages (weak) */
215 bt_self_message_iterator
*self_msg_iter
= nullptr;
218 * True if library objects are unavailable during the decoding and
219 * should not be created/used.
221 bool dry_run
= false;
224 * Current dynamic scope field pointer.
226 * This is set by read_dscope_begin_state() and contains the
227 * value of one of the pointers in `dscopes` below.
229 bt_field
*cur_dscope_field
= nullptr;
232 * True if we're done filling a string field from a text
233 * array/sequence payload.
235 bool done_filling_string
= false;
237 /* Trace and classes */
238 /* True to set IR fields */
239 bool set_ir_fields
= false;
243 struct ctf_trace_class
*tc
= nullptr;
244 struct ctf_stream_class
*sc
= nullptr;
245 struct ctf_event_class
*ec
= nullptr;
248 /* Current packet (NULL if not created yet) */
249 bt_packet
*packet
= nullptr;
251 /* Current stream (NULL if not set yet) */
252 bt_stream
*stream
= nullptr;
254 /* Current event (NULL if not created yet) */
255 bt_event
*event
= nullptr;
257 /* Current event message (NULL if not created yet) */
258 bt_message
*event_msg
= nullptr;
261 * True if we need to emit a packet beginning message before we emit
262 * the next event message or the packet end message.
264 bool emit_delayed_packet_beginning_msg
= false;
267 * True if this is the first packet we are reading, and therefore if we
268 * should emit a stream beginning message.
270 bool emit_stream_beginning_message
= false;
273 * True if we need to emit a stream end message at the end of the
274 * current stream. A live stream may never receive any data and thus
275 * never send a stream beginning message which removes the need to emit
276 * a stream end message.
278 bool emit_stream_end_message
= false;
280 /* Database of current dynamic scopes */
283 bt_field
*stream_packet_context
= nullptr;
284 bt_field
*event_common_context
= nullptr;
285 bt_field
*event_spec_context
= nullptr;
286 bt_field
*event_payload
= nullptr;
290 enum state state
= STATE_INIT
;
292 /* Current medium buffer data */
295 /* Last address provided by medium */
296 const uint8_t *addr
= nullptr;
298 /* Buffer size provided by medium (bytes) */
301 /* Offset within whole packet of addr (bits) */
302 size_t packet_offset
= 0;
304 /* Current position from addr (bits) */
307 /* Position of the last event header from addr (bits) */
308 size_t last_eh_at
= 0;
311 /* Binary type reader */
312 struct bt_bfcr
*bfcr
= nullptr;
314 /* Current medium data */
317 struct ctf_msg_iter_medium_ops medops
;
318 size_t max_request_sz
= 0;
319 void *data
= nullptr;
322 /* Current packet size (bits) (-1 if unknown) */
323 int64_t cur_exp_packet_total_size
= 0;
325 /* Current content size (bits) (-1 if unknown) */
326 int64_t cur_exp_packet_content_size
= 0;
328 /* Current stream class ID */
329 int64_t cur_stream_class_id
= 0;
331 /* Current event class ID */
332 int64_t cur_event_class_id
= 0;
334 /* Current data stream ID */
335 int64_t cur_data_stream_id
= 0;
338 * Offset, in the underlying media, of the current packet's
339 * start (-1 if unknown).
341 off_t cur_packet_offset
= 0;
343 /* Default clock's current value */
344 uint64_t default_clock_snapshot
= 0;
346 /* End of current packet snapshots */
347 struct end_of_packet_snapshots snapshots
;
349 /* End of previous packet snapshots */
350 struct end_of_packet_snapshots prev_packet_snapshots
;
352 /* Stored values (for sequence lengths, variant tags) */
353 GArray
*stored_values
= nullptr;
358 static struct stack
*stack_new(struct ctf_msg_iter
*msg_it
)
360 struct stack
*stack
= NULL
;
362 stack
= g_new0(struct stack
, 1);
364 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
, "Failed to allocate one stack.");
368 stack
->msg_it
= msg_it
;
369 stack
->entries
= g_array_new(FALSE
, TRUE
, sizeof(struct stack_entry
));
370 if (!stack
->entries
) {
371 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
, "Failed to allocate a GArray.");
375 BT_CPPLOGD_SPEC(msg_it
->logger
, "Created stack: msg-it-addr={}, stack-addr={}",
376 fmt::ptr(msg_it
), fmt::ptr(stack
));
387 static void stack_destroy(struct stack
*stack
)
389 struct ctf_msg_iter
*msg_it
;
391 BT_ASSERT_DBG(stack
);
392 msg_it
= stack
->msg_it
;
393 BT_CPPLOGD_SPEC(msg_it
->logger
, "Destroying stack: addr={}", fmt::ptr(stack
));
395 if (stack
->entries
) {
396 g_array_free(stack
->entries
, TRUE
);
402 static void stack_push(struct stack
*stack
, bt_field
*base
)
404 struct stack_entry
*entry
;
405 struct ctf_msg_iter
*msg_it
;
407 BT_ASSERT_DBG(stack
);
408 msg_it
= stack
->msg_it
;
410 BT_CPPLOGT_SPEC(msg_it
->logger
,
411 "Pushing base field on stack: stack-addr={}, "
412 "stack-size-before={}, stack-size-after={}",
413 fmt::ptr(stack
), stack
->size
, stack
->size
+ 1);
415 if (stack
->entries
->len
== stack
->size
) {
416 g_array_set_size(stack
->entries
, stack
->size
+ 1);
419 entry
= &bt_g_array_index(stack
->entries
, struct stack_entry
, stack
->size
);
425 static inline unsigned int stack_size(struct stack
*stack
)
427 BT_ASSERT_DBG(stack
);
431 static void stack_pop(struct stack
*stack
)
433 struct ctf_msg_iter
*msg_it
;
435 BT_ASSERT_DBG(stack
);
436 BT_ASSERT_DBG(stack_size(stack
));
437 msg_it
= stack
->msg_it
;
438 BT_CPPLOGT_SPEC(msg_it
->logger
,
439 "Popping from stack: "
440 "stack-addr={}, stack-size-before={}, stack-size-after={}",
441 fmt::ptr(stack
), stack
->size
, stack
->size
- 1);
445 static inline struct stack_entry
*stack_top(struct stack
*stack
)
447 BT_ASSERT_DBG(stack
);
448 BT_ASSERT_DBG(stack_size(stack
));
449 return &bt_g_array_index(stack
->entries
, struct stack_entry
, stack
->size
- 1);
452 static inline bool stack_empty(struct stack
*stack
)
454 return stack_size(stack
) == 0;
457 static void stack_clear(struct stack
*stack
)
459 BT_ASSERT_DBG(stack
);
463 static inline enum ctf_msg_iter_status
464 msg_iter_status_from_m_status(enum ctf_msg_iter_medium_status m_status
)
466 /* They are the same */
467 return (ctf_msg_iter_status
) m_status
;
470 static inline size_t buf_size_bits(struct ctf_msg_iter
*msg_it
)
472 return msg_it
->buf
.sz
* 8;
475 static inline size_t buf_available_bits(struct ctf_msg_iter
*msg_it
)
477 return buf_size_bits(msg_it
) - msg_it
->buf
.at
;
480 static inline size_t packet_at(struct ctf_msg_iter
*msg_it
)
482 return msg_it
->buf
.packet_offset
+ msg_it
->buf
.at
;
485 static inline void buf_consume_bits(struct ctf_msg_iter
*msg_it
, size_t incr
)
487 BT_CPPLOGT_SPEC(msg_it
->logger
, "Advancing cursor: msg-it-addr={}, cur-before={}, cur-after={}",
488 fmt::ptr(msg_it
), msg_it
->buf
.at
, msg_it
->buf
.at
+ incr
);
489 msg_it
->buf
.at
+= incr
;
492 static enum ctf_msg_iter_status
request_medium_bytes(struct ctf_msg_iter
*msg_it
)
494 uint8_t *buffer_addr
= NULL
;
495 size_t buffer_sz
= 0;
496 enum ctf_msg_iter_medium_status m_status
;
498 BT_CPPLOGD_SPEC(msg_it
->logger
,
499 "Calling user function (request bytes): msg-it-addr={}, "
501 fmt::ptr(msg_it
), msg_it
->medium
.max_request_sz
);
502 m_status
= msg_it
->medium
.medops
.request_bytes(msg_it
->medium
.max_request_sz
, &buffer_addr
,
503 &buffer_sz
, msg_it
->medium
.data
);
504 BT_CPPLOGD_SPEC(msg_it
->logger
, "User function returned: status={}, buf-addr={}, buf-size={}",
505 m_status
, fmt::ptr(buffer_addr
), buffer_sz
);
506 if (m_status
== CTF_MSG_ITER_MEDIUM_STATUS_OK
) {
507 BT_ASSERT(buffer_sz
!= 0);
509 /* New packet offset is old one + old size (in bits) */
510 msg_it
->buf
.packet_offset
+= buf_size_bits(msg_it
);
512 /* Restart at the beginning of the new medium buffer */
514 msg_it
->buf
.last_eh_at
= SIZE_MAX
;
516 /* New medium buffer size */
517 msg_it
->buf
.sz
= buffer_sz
;
519 /* New medium buffer address */
520 msg_it
->buf
.addr
= buffer_addr
;
522 BT_CPPLOGD_SPEC(msg_it
->logger
,
523 "User function returned new bytes: "
524 "packet-offset={}, cur={}, size={}, addr={}",
525 msg_it
->buf
.packet_offset
, msg_it
->buf
.at
, msg_it
->buf
.sz
,
526 fmt::ptr(msg_it
->buf
.addr
));
527 BT_CPPLOGT_MEM_SPEC(msg_it
->logger
, bt2c::makeSpan(buffer_addr
, buffer_sz
),
528 "Returned bytes at {}:", fmt::ptr(buffer_addr
));
529 } else if (m_status
== CTF_MSG_ITER_MEDIUM_STATUS_EOF
) {
531 * User returned end of stream: validate that we're not
532 * in the middle of a packet header, packet context, or
535 if (msg_it
->cur_exp_packet_total_size
>= 0) {
536 if (packet_at(msg_it
) == msg_it
->cur_exp_packet_total_size
) {
540 if (packet_at(msg_it
) == 0) {
544 if (msg_it
->buf
.last_eh_at
!= SIZE_MAX
&& msg_it
->buf
.at
== msg_it
->buf
.last_eh_at
) {
549 /* All other states are invalid */
550 BT_CPPLOGE_APPEND_CAUSE_SPEC(
552 "User function returned {}, but message iterator is in an unexpected state: "
553 "state={}, cur-packet-size={}, cur={}, "
554 "packet-cur={}, last-eh-at={}",
555 m_status
, msg_it
->state
, msg_it
->cur_exp_packet_total_size
, msg_it
->buf
.at
,
556 packet_at(msg_it
), msg_it
->buf
.last_eh_at
);
557 m_status
= CTF_MSG_ITER_MEDIUM_STATUS_ERROR
;
558 } else if (m_status
< 0) {
559 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
560 "User function failed: "
566 return msg_iter_status_from_m_status(m_status
);
569 static inline enum ctf_msg_iter_status
buf_ensure_available_bits(struct ctf_msg_iter
*msg_it
)
571 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
573 if (G_UNLIKELY(buf_available_bits(msg_it
) == 0)) {
575 * This _cannot_ return CTF_MSG_ITER_STATUS_OK
578 status
= request_medium_bytes(msg_it
);
584 static enum ctf_msg_iter_status
585 read_dscope_begin_state(struct ctf_msg_iter
*msg_it
, struct ctf_field_class
*dscope_fc
,
586 enum state done_state
, enum state continue_state
, bt_field
*dscope_field
)
588 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
589 enum bt_bfcr_status bfcr_status
;
590 size_t consumed_bits
;
592 msg_it
->cur_dscope_field
= dscope_field
;
593 BT_CPPLOGT_SPEC(msg_it
->logger
, "Starting BFCR: msg-it-addr={}, bfcr-addr={}, fc-addr={}",
594 fmt::ptr(msg_it
), fmt::ptr(msg_it
->bfcr
), fmt::ptr(dscope_fc
));
595 consumed_bits
= bt_bfcr_start(msg_it
->bfcr
, dscope_fc
, msg_it
->buf
.addr
, msg_it
->buf
.at
,
596 packet_at(msg_it
), msg_it
->buf
.sz
, &bfcr_status
);
597 BT_CPPLOGT_SPEC(msg_it
->logger
, "BFCR consumed bits: size={}", consumed_bits
);
599 switch (bfcr_status
) {
600 case BT_BFCR_STATUS_OK
:
601 /* Field class was read completely */
602 BT_CPPLOGT_SPEC(msg_it
->logger
, "Field was completely decoded.");
603 msg_it
->state
= done_state
;
605 case BT_BFCR_STATUS_EOF
:
606 BT_CPPLOGT_SPEC(msg_it
->logger
, "BFCR needs more data to decode field completely.");
607 msg_it
->state
= continue_state
;
610 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
611 "BFCR failed to start: msg-it-addr={}, bfcr-addr={}, "
613 fmt::ptr(msg_it
), fmt::ptr(msg_it
->bfcr
), bfcr_status
);
614 status
= CTF_MSG_ITER_STATUS_ERROR
;
618 /* Consume bits now since we know we're not in an error state */
619 buf_consume_bits(msg_it
, consumed_bits
);
625 static enum ctf_msg_iter_status
read_dscope_continue_state(struct ctf_msg_iter
*msg_it
,
626 enum state done_state
)
628 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
629 enum bt_bfcr_status bfcr_status
;
630 size_t consumed_bits
;
632 BT_CPPLOGT_SPEC(msg_it
->logger
, "Continuing BFCR: msg-it-addr={}, bfcr-addr={}",
633 fmt::ptr(msg_it
), fmt::ptr(msg_it
->bfcr
));
635 status
= buf_ensure_available_bits(msg_it
);
636 if (status
!= CTF_MSG_ITER_STATUS_OK
) {
638 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
639 "Cannot ensure that buffer has at least one byte: "
640 "msg-addr={}, status={}",
641 fmt::ptr(msg_it
), status
);
643 BT_CPPLOGT_SPEC(msg_it
->logger
,
644 "Cannot ensure that buffer has at least one byte: "
645 "msg-addr={}, status={}",
646 fmt::ptr(msg_it
), status
);
652 consumed_bits
= bt_bfcr_continue(msg_it
->bfcr
, msg_it
->buf
.addr
, msg_it
->buf
.sz
, &bfcr_status
);
653 BT_CPPLOGT_SPEC(msg_it
->logger
, "BFCR consumed bits: size={}", consumed_bits
);
655 switch (bfcr_status
) {
656 case BT_BFCR_STATUS_OK
:
657 /* Type was read completely. */
658 BT_CPPLOGT_SPEC(msg_it
->logger
, "Field was completely decoded.");
659 msg_it
->state
= done_state
;
661 case BT_BFCR_STATUS_EOF
:
662 /* Stay in this continue state. */
663 BT_CPPLOGT_SPEC(msg_it
->logger
, "BFCR needs more data to decode field completely.");
666 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
667 "BFCR failed to continue: msg-it-addr={}, bfcr-addr={}, "
669 fmt::ptr(msg_it
), fmt::ptr(msg_it
->bfcr
), bfcr_status
);
670 status
= CTF_MSG_ITER_STATUS_ERROR
;
674 /* Consume bits now since we know we're not in an error state. */
675 buf_consume_bits(msg_it
, consumed_bits
);
680 static void release_event_dscopes(struct ctf_msg_iter
*msg_it
)
682 msg_it
->dscopes
.event_common_context
= NULL
;
683 msg_it
->dscopes
.event_spec_context
= NULL
;
684 msg_it
->dscopes
.event_payload
= NULL
;
687 static void release_all_dscopes(struct ctf_msg_iter
*msg_it
)
689 msg_it
->dscopes
.stream_packet_context
= NULL
;
691 release_event_dscopes(msg_it
);
694 static enum ctf_msg_iter_status
switch_packet_state(struct ctf_msg_iter
*msg_it
)
696 enum ctf_msg_iter_status status
;
699 * We don't put the stream class here because we need to make
700 * sure that all the packets processed by the same message
701 * iterator refer to the same stream class (the first one).
705 if (msg_it
->cur_exp_packet_total_size
!= -1) {
706 msg_it
->cur_packet_offset
+= msg_it
->cur_exp_packet_total_size
;
709 BT_CPPLOGD_SPEC(msg_it
->logger
,
710 "Switching packet: msg-it-addr={}, cur={}, "
712 fmt::ptr(msg_it
), msg_it
->buf
.at
, msg_it
->cur_packet_offset
);
713 stack_clear(msg_it
->stack
);
714 msg_it
->meta
.ec
= NULL
;
715 BT_PACKET_PUT_REF_AND_RESET(msg_it
->packet
);
716 BT_MESSAGE_PUT_REF_AND_RESET(msg_it
->event_msg
);
717 release_all_dscopes(msg_it
);
718 msg_it
->cur_dscope_field
= NULL
;
720 if (msg_it
->medium
.medops
.switch_packet
) {
721 enum ctf_msg_iter_medium_status medium_status
;
723 medium_status
= msg_it
->medium
.medops
.switch_packet(msg_it
->medium
.data
);
724 if (medium_status
== CTF_MSG_ITER_MEDIUM_STATUS_EOF
) {
725 /* No more packets. */
726 msg_it
->state
= STATE_CHECK_EMIT_MSG_STREAM_END
;
727 status
= CTF_MSG_ITER_STATUS_OK
;
729 } else if (medium_status
!= CTF_MSG_ITER_MEDIUM_STATUS_OK
) {
730 status
= msg_iter_status_from_m_status(medium_status
);
735 * After the packet switch, the medium might want to give us a
736 * different buffer for the new packet.
738 status
= request_medium_bytes(msg_it
);
739 if (status
!= CTF_MSG_ITER_STATUS_OK
) {
745 * Adjust current buffer so that addr points to the beginning of the new
748 if (msg_it
->buf
.addr
) {
749 size_t consumed_bytes
= (size_t) (msg_it
->buf
.at
/ CHAR_BIT
);
751 /* Packets are assumed to start on a byte frontier. */
752 if (msg_it
->buf
.at
% CHAR_BIT
) {
753 BT_CPPLOGE_APPEND_CAUSE_SPEC(
755 "Cannot switch packet: current position is not a multiple of 8: "
756 "msg-it-addr={}, cur={}",
757 fmt::ptr(msg_it
), msg_it
->buf
.at
);
758 status
= CTF_MSG_ITER_STATUS_ERROR
;
762 msg_it
->buf
.addr
+= consumed_bytes
;
763 msg_it
->buf
.sz
-= consumed_bytes
;
765 msg_it
->buf
.packet_offset
= 0;
766 BT_CPPLOGD_SPEC(msg_it
->logger
, "Adjusted buffer: addr={}, size={}",
767 fmt::ptr(msg_it
->buf
.addr
), msg_it
->buf
.sz
);
770 msg_it
->cur_exp_packet_content_size
= -1;
771 msg_it
->cur_exp_packet_total_size
= -1;
772 msg_it
->cur_stream_class_id
= -1;
773 msg_it
->cur_event_class_id
= -1;
774 msg_it
->cur_data_stream_id
= -1;
775 msg_it
->prev_packet_snapshots
= msg_it
->snapshots
;
776 msg_it
->snapshots
.discarded_events
= UINT64_C(-1);
777 msg_it
->snapshots
.packets
= UINT64_C(-1);
778 msg_it
->snapshots
.beginning_clock
= UINT64_C(-1);
779 msg_it
->snapshots
.end_clock
= UINT64_C(-1);
780 msg_it
->state
= STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
;
782 status
= CTF_MSG_ITER_STATUS_OK
;
787 static enum ctf_msg_iter_status
read_packet_header_begin_state(struct ctf_msg_iter
*msg_it
)
789 struct ctf_field_class
*packet_header_fc
= NULL
;
790 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
793 * Make sure at least one bit is available for this packet. An
794 * empty packet is impossible. If we reach the end of the medium
795 * at this point, then it's considered the end of the stream.
797 status
= buf_ensure_available_bits(msg_it
);
799 case CTF_MSG_ITER_STATUS_OK
:
801 case CTF_MSG_ITER_STATUS_EOF
:
802 status
= CTF_MSG_ITER_STATUS_OK
;
803 msg_it
->state
= STATE_CHECK_EMIT_MSG_STREAM_END
;
809 /* Packet header class is common to the whole trace class. */
810 packet_header_fc
= msg_it
->meta
.tc
->packet_header_fc
;
811 if (!packet_header_fc
) {
812 msg_it
->state
= STATE_AFTER_TRACE_PACKET_HEADER
;
816 msg_it
->cur_stream_class_id
= -1;
817 msg_it
->cur_event_class_id
= -1;
818 msg_it
->cur_data_stream_id
= -1;
819 BT_CPPLOGD_SPEC(msg_it
->logger
,
820 "Decoding packet header field: "
821 "msg-it-addr={}, trace-class-addr={}, fc-addr={}",
822 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.tc
), fmt::ptr(packet_header_fc
));
823 status
= read_dscope_begin_state(msg_it
, packet_header_fc
, STATE_AFTER_TRACE_PACKET_HEADER
,
824 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
, NULL
);
826 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
827 "Cannot decode packet header field: "
828 "msg-it-addr={}, trace-class-addr={}, "
830 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.tc
),
831 fmt::ptr(packet_header_fc
));
838 static enum ctf_msg_iter_status
read_packet_header_continue_state(struct ctf_msg_iter
*msg_it
)
840 return read_dscope_continue_state(msg_it
, STATE_AFTER_TRACE_PACKET_HEADER
);
843 static inline enum ctf_msg_iter_status
set_current_stream_class(struct ctf_msg_iter
*msg_it
)
845 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
846 struct ctf_stream_class
*new_stream_class
= NULL
;
848 if (msg_it
->cur_stream_class_id
== -1) {
850 * No current stream class ID field, therefore only one
853 if (msg_it
->meta
.tc
->stream_classes
->len
!= 1) {
854 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
855 "Need exactly one stream class since there's "
856 "no stream class ID field: "
859 status
= CTF_MSG_ITER_STATUS_ERROR
;
863 new_stream_class
= (ctf_stream_class
*) msg_it
->meta
.tc
->stream_classes
->pdata
[0];
864 msg_it
->cur_stream_class_id
= new_stream_class
->id
;
868 ctf_trace_class_borrow_stream_class_by_id(msg_it
->meta
.tc
, msg_it
->cur_stream_class_id
);
869 if (!new_stream_class
) {
870 BT_CPPLOGE_APPEND_CAUSE_SPEC(
872 "No stream class with ID of stream class ID to use in trace class: "
873 "msg-it-addr={}, stream-class-id={}, "
874 "trace-class-addr={}",
875 fmt::ptr(msg_it
), msg_it
->cur_stream_class_id
, fmt::ptr(msg_it
->meta
.tc
));
876 status
= CTF_MSG_ITER_STATUS_ERROR
;
880 if (msg_it
->meta
.sc
) {
881 if (new_stream_class
!= msg_it
->meta
.sc
) {
882 BT_CPPLOGE_APPEND_CAUSE_SPEC(
884 "Two packets refer to two different stream classes within the same packet sequence: "
885 "msg-it-addr={}, prev-stream-class-addr={}, "
886 "prev-stream-class-id={}, "
887 "next-stream-class-addr={}, "
888 "next-stream-class-id={}, "
890 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.sc
), msg_it
->meta
.sc
->id
,
891 fmt::ptr(new_stream_class
), new_stream_class
->id
, fmt::ptr(msg_it
->meta
.tc
));
892 status
= CTF_MSG_ITER_STATUS_ERROR
;
896 msg_it
->meta
.sc
= new_stream_class
;
899 BT_CPPLOGD_SPEC(msg_it
->logger
,
900 "Set current stream class: "
901 "msg-it-addr={}, stream-class-addr={}, "
902 "stream-class-id={}",
903 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.sc
), msg_it
->meta
.sc
->id
);
909 static inline enum ctf_msg_iter_status
set_current_stream(struct ctf_msg_iter
*msg_it
)
911 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
912 bt_stream
*stream
= NULL
;
914 BT_CPPLOGD_SPEC(msg_it
->logger
,
915 "Calling user function (get stream): msg-it-addr={}, "
916 "stream-class-addr={}, stream-class-id={}",
917 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.sc
), msg_it
->meta
.sc
->id
);
918 stream
= msg_it
->medium
.medops
.borrow_stream(msg_it
->meta
.sc
->ir_sc
, msg_it
->cur_data_stream_id
,
919 msg_it
->medium
.data
);
920 bt_stream_get_ref(stream
);
921 BT_CPPLOGD_SPEC(msg_it
->logger
, "User function returned: stream-addr={}", fmt::ptr(stream
));
923 BT_CPPLOGE_APPEND_CAUSE_SPEC(
925 "User function failed to return a stream object for the given stream class.");
926 status
= CTF_MSG_ITER_STATUS_ERROR
;
930 if (msg_it
->stream
&& stream
!= msg_it
->stream
) {
931 BT_CPPLOGE_APPEND_CAUSE_SPEC(
933 "User function returned a different stream than the previous one for the same sequence of packets.");
934 status
= CTF_MSG_ITER_STATUS_ERROR
;
938 BT_STREAM_MOVE_REF(msg_it
->stream
, stream
);
941 bt_stream_put_ref(stream
);
945 static inline enum ctf_msg_iter_status
set_current_packet(struct ctf_msg_iter
*msg_it
)
947 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
948 bt_packet
*packet
= NULL
;
950 BT_CPPLOGD_SPEC(msg_it
->logger
,
951 "Creating packet from stream: "
952 "msg-it-addr={}, stream-addr={}, "
953 "stream-class-addr={}, "
954 "stream-class-id={}",
955 fmt::ptr(msg_it
), fmt::ptr(msg_it
->stream
), fmt::ptr(msg_it
->meta
.sc
),
956 msg_it
->meta
.sc
->id
);
959 BT_ASSERT(msg_it
->stream
);
960 packet
= bt_packet_create(msg_it
->stream
);
962 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
963 "Cannot create packet from stream: "
964 "msg-it-addr={}, stream-addr={}, "
965 "stream-class-addr={}, "
966 "stream-class-id={}",
967 fmt::ptr(msg_it
), fmt::ptr(msg_it
->stream
),
968 fmt::ptr(msg_it
->meta
.sc
), msg_it
->meta
.sc
->id
);
975 BT_PACKET_PUT_REF_AND_RESET(packet
);
976 status
= CTF_MSG_ITER_STATUS_ERROR
;
979 BT_PACKET_MOVE_REF(msg_it
->packet
, packet
);
983 static enum ctf_msg_iter_status
after_packet_header_state(struct ctf_msg_iter
*msg_it
)
985 enum ctf_msg_iter_status status
;
987 status
= set_current_stream_class(msg_it
);
988 if (status
!= CTF_MSG_ITER_STATUS_OK
) {
992 if (!msg_it
->dry_run
) {
993 status
= set_current_stream(msg_it
);
994 if (status
!= CTF_MSG_ITER_STATUS_OK
) {
998 status
= set_current_packet(msg_it
);
999 if (status
!= CTF_MSG_ITER_STATUS_OK
) {
1004 msg_it
->state
= STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
;
1006 status
= CTF_MSG_ITER_STATUS_OK
;
1012 static enum ctf_msg_iter_status
read_packet_context_begin_state(struct ctf_msg_iter
*msg_it
)
1014 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
1015 struct ctf_field_class
*packet_context_fc
;
1017 BT_ASSERT(msg_it
->meta
.sc
);
1018 packet_context_fc
= msg_it
->meta
.sc
->packet_context_fc
;
1019 if (!packet_context_fc
) {
1020 BT_CPPLOGD_SPEC(msg_it
->logger
,
1021 "No packet packet context field class in stream class: continuing: "
1022 "msg-it-addr={}, stream-class-addr={}, "
1023 "stream-class-id={}",
1024 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.sc
), msg_it
->meta
.sc
->id
);
1025 msg_it
->state
= STATE_AFTER_STREAM_PACKET_CONTEXT
;
1029 if (packet_context_fc
->in_ir
&& !msg_it
->dry_run
) {
1030 BT_ASSERT(!msg_it
->dscopes
.stream_packet_context
);
1031 BT_ASSERT(msg_it
->packet
);
1032 msg_it
->dscopes
.stream_packet_context
= bt_packet_borrow_context_field(msg_it
->packet
);
1033 BT_ASSERT(msg_it
->dscopes
.stream_packet_context
);
1036 BT_CPPLOGD_SPEC(msg_it
->logger
,
1037 "Decoding packet context field: "
1038 "msg-it-addr={}, stream-class-addr={}, "
1039 "stream-class-id={}, fc-addr={}",
1040 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.sc
), msg_it
->meta
.sc
->id
,
1041 fmt::ptr(packet_context_fc
));
1042 status
= read_dscope_begin_state(msg_it
, packet_context_fc
, STATE_AFTER_STREAM_PACKET_CONTEXT
,
1043 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
,
1044 msg_it
->dscopes
.stream_packet_context
);
1046 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
1047 "Cannot decode packet context field: "
1048 "msg-it-addr={}, stream-class-addr={}, "
1049 "stream-class-id={}, fc-addr={}",
1050 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.sc
),
1051 msg_it
->meta
.sc
->id
, fmt::ptr(packet_context_fc
));
1058 static enum ctf_msg_iter_status
read_packet_context_continue_state(struct ctf_msg_iter
*msg_it
)
1060 return read_dscope_continue_state(msg_it
, STATE_AFTER_STREAM_PACKET_CONTEXT
);
1063 static enum ctf_msg_iter_status
set_current_packet_content_sizes(struct ctf_msg_iter
*msg_it
)
1065 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
1067 if (msg_it
->cur_exp_packet_total_size
== -1) {
1068 if (msg_it
->cur_exp_packet_content_size
!= -1) {
1069 msg_it
->cur_exp_packet_total_size
= msg_it
->cur_exp_packet_content_size
;
1072 if (msg_it
->cur_exp_packet_content_size
== -1) {
1073 msg_it
->cur_exp_packet_content_size
= msg_it
->cur_exp_packet_total_size
;
1078 (msg_it
->cur_exp_packet_total_size
>= 0 && msg_it
->cur_exp_packet_content_size
>= 0) ||
1079 (msg_it
->cur_exp_packet_total_size
< 0 && msg_it
->cur_exp_packet_content_size
< 0));
1081 if (msg_it
->cur_exp_packet_content_size
> msg_it
->cur_exp_packet_total_size
) {
1082 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1084 "Invalid packet or content size: "
1085 "content size is greater than packet size: "
1086 "msg-it-addr={}, packet-context-field-addr={}, "
1087 "packet-size={}, content-size={}",
1088 fmt::ptr(msg_it
), fmt::ptr(msg_it
->dscopes
.stream_packet_context
),
1089 msg_it
->cur_exp_packet_total_size
, msg_it
->cur_exp_packet_content_size
);
1090 status
= CTF_MSG_ITER_STATUS_ERROR
;
1094 BT_CPPLOGD_SPEC(msg_it
->logger
,
1095 "Set current packet and content sizes: "
1096 "msg-it-addr={}, packet-size={}, content-size={}",
1097 fmt::ptr(msg_it
), msg_it
->cur_exp_packet_total_size
,
1098 msg_it
->cur_exp_packet_content_size
);
1104 static enum ctf_msg_iter_status
after_packet_context_state(struct ctf_msg_iter
*msg_it
)
1106 enum ctf_msg_iter_status status
;
1108 status
= set_current_packet_content_sizes(msg_it
);
1109 if (status
!= CTF_MSG_ITER_STATUS_OK
) {
1113 if (msg_it
->emit_stream_beginning_message
) {
1114 msg_it
->state
= STATE_EMIT_MSG_STREAM_BEGINNING
;
1116 msg_it
->state
= STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS
;
1123 static enum ctf_msg_iter_status
read_event_header_begin_state(struct ctf_msg_iter
*msg_it
)
1125 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
1126 struct ctf_field_class
*event_header_fc
= NULL
;
1128 /* Reset the position of the last event header */
1129 msg_it
->buf
.last_eh_at
= msg_it
->buf
.at
;
1130 msg_it
->cur_event_class_id
= -1;
1132 /* Check if we have some content left */
1133 if (msg_it
->cur_exp_packet_content_size
>= 0) {
1134 if (G_UNLIKELY(packet_at(msg_it
) == msg_it
->cur_exp_packet_content_size
)) {
1135 /* No more events! */
1136 BT_CPPLOGD_SPEC(msg_it
->logger
,
1137 "Reached end of packet: msg-it-addr={}, "
1139 fmt::ptr(msg_it
), packet_at(msg_it
));
1140 msg_it
->state
= STATE_EMIT_MSG_PACKET_END_MULTI
;
1142 } else if (G_UNLIKELY(packet_at(msg_it
) > msg_it
->cur_exp_packet_content_size
)) {
1143 /* That's not supposed to happen */
1146 "Before decoding event header field: cursor is passed the packet's content: "
1147 "msg-it-addr={}, content-size={}, "
1149 fmt::ptr(msg_it
), msg_it
->cur_exp_packet_content_size
, packet_at(msg_it
));
1150 status
= CTF_MSG_ITER_STATUS_ERROR
;
1155 * "Infinite" content: we're done when the medium has
1156 * nothing else for us.
1158 status
= buf_ensure_available_bits(msg_it
);
1160 case CTF_MSG_ITER_STATUS_OK
:
1162 case CTF_MSG_ITER_STATUS_EOF
:
1163 status
= CTF_MSG_ITER_STATUS_OK
;
1164 msg_it
->state
= STATE_EMIT_MSG_PACKET_END_SINGLE
;
1171 release_event_dscopes(msg_it
);
1172 BT_ASSERT(msg_it
->meta
.sc
);
1173 event_header_fc
= msg_it
->meta
.sc
->event_header_fc
;
1174 if (!event_header_fc
) {
1175 msg_it
->state
= STATE_AFTER_EVENT_HEADER
;
1179 BT_CPPLOGD_SPEC(msg_it
->logger
,
1180 "Decoding event header field: "
1181 "msg-it-addr={}, stream-class-addr={}, "
1182 "stream-class-id={}, "
1184 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.sc
), msg_it
->meta
.sc
->id
,
1185 fmt::ptr(event_header_fc
));
1186 status
= read_dscope_begin_state(msg_it
, event_header_fc
, STATE_AFTER_EVENT_HEADER
,
1187 STATE_DSCOPE_EVENT_HEADER_CONTINUE
, NULL
);
1189 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
1190 "Cannot decode event header field: "
1191 "msg-it-addr={}, stream-class-addr={}, "
1192 "stream-class-id={}, fc-addr={}",
1193 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.sc
),
1194 msg_it
->meta
.sc
->id
, fmt::ptr(event_header_fc
));
1201 static enum ctf_msg_iter_status
read_event_header_continue_state(struct ctf_msg_iter
*msg_it
)
1203 return read_dscope_continue_state(msg_it
, STATE_AFTER_EVENT_HEADER
);
1206 static inline enum ctf_msg_iter_status
set_current_event_class(struct ctf_msg_iter
*msg_it
)
1208 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
1210 struct ctf_event_class
*new_event_class
= NULL
;
1212 if (msg_it
->cur_event_class_id
== -1) {
1214 * No current event class ID field, therefore only one
1217 if (msg_it
->meta
.sc
->event_classes
->len
!= 1) {
1218 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1220 "Need exactly one event class since there's no event class ID field: "
1223 status
= CTF_MSG_ITER_STATUS_ERROR
;
1227 new_event_class
= (ctf_event_class
*) msg_it
->meta
.sc
->event_classes
->pdata
[0];
1228 msg_it
->cur_event_class_id
= new_event_class
->id
;
1232 ctf_stream_class_borrow_event_class_by_id(msg_it
->meta
.sc
, msg_it
->cur_event_class_id
);
1233 if (!new_event_class
) {
1234 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1236 "No event class with ID of event class ID to use in stream class: "
1237 "msg-it-addr={}, stream-class-id={}, "
1238 "event-class-id={}, "
1239 "trace-class-addr={}",
1240 fmt::ptr(msg_it
), msg_it
->meta
.sc
->id
, msg_it
->cur_event_class_id
,
1241 fmt::ptr(msg_it
->meta
.tc
));
1242 status
= CTF_MSG_ITER_STATUS_ERROR
;
1246 msg_it
->meta
.ec
= new_event_class
;
1247 BT_CPPLOGD_SPEC(msg_it
->logger
,
1248 "Set current event class: "
1249 "msg-it-addr={}, event-class-addr={}, "
1250 "event-class-id={}, "
1251 "event-class-name=\"{}\"",
1252 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.ec
), msg_it
->meta
.ec
->id
,
1253 msg_it
->meta
.ec
->name
->str
);
1259 static inline enum ctf_msg_iter_status
set_current_event_message(struct ctf_msg_iter
*msg_it
)
1261 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
1262 bt_message
*msg
= NULL
;
1264 BT_ASSERT_DBG(msg_it
->meta
.ec
);
1265 BT_ASSERT_DBG(msg_it
->packet
);
1266 BT_CPPLOGD_SPEC(msg_it
->logger
,
1267 "Creating event message from event class and packet: "
1268 "msg-it-addr={}, ec-addr={}, ec-name=\"{}\", packet-addr={}",
1269 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.ec
), msg_it
->meta
.ec
->name
->str
,
1270 fmt::ptr(msg_it
->packet
));
1271 BT_ASSERT_DBG(msg_it
->self_msg_iter
);
1272 BT_ASSERT_DBG(msg_it
->meta
.sc
);
1274 if (bt_stream_class_borrow_default_clock_class(msg_it
->meta
.sc
->ir_sc
)) {
1275 msg
= bt_message_event_create_with_packet_and_default_clock_snapshot(
1276 msg_it
->self_msg_iter
, msg_it
->meta
.ec
->ir_ec
, msg_it
->packet
,
1277 msg_it
->default_clock_snapshot
);
1279 msg
= bt_message_event_create_with_packet(msg_it
->self_msg_iter
, msg_it
->meta
.ec
->ir_ec
,
1284 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
1285 "Cannot create event message: "
1286 "msg-it-addr={}, ec-addr={}, ec-name=\"{}\", "
1288 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.ec
),
1289 msg_it
->meta
.ec
->name
->str
, fmt::ptr(msg_it
->packet
));
1296 BT_MESSAGE_PUT_REF_AND_RESET(msg
);
1297 status
= CTF_MSG_ITER_STATUS_ERROR
;
1300 BT_MESSAGE_MOVE_REF(msg_it
->event_msg
, msg
);
1304 static enum ctf_msg_iter_status
after_event_header_state(struct ctf_msg_iter
*msg_it
)
1306 enum ctf_msg_iter_status status
;
1308 status
= set_current_event_class(msg_it
);
1309 if (status
!= CTF_MSG_ITER_STATUS_OK
) {
1313 if (G_UNLIKELY(msg_it
->dry_run
)) {
1317 status
= set_current_event_message(msg_it
);
1318 if (status
!= CTF_MSG_ITER_STATUS_OK
) {
1322 msg_it
->event
= bt_message_event_borrow_event(msg_it
->event_msg
);
1323 BT_ASSERT_DBG(msg_it
->event
);
1326 msg_it
->state
= STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN
;
1332 static enum ctf_msg_iter_status
read_event_common_context_begin_state(struct ctf_msg_iter
*msg_it
)
1334 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
1335 struct ctf_field_class
*event_common_context_fc
;
1337 event_common_context_fc
= msg_it
->meta
.sc
->event_common_context_fc
;
1338 if (!event_common_context_fc
) {
1339 msg_it
->state
= STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN
;
1343 if (event_common_context_fc
->in_ir
&& !msg_it
->dry_run
) {
1344 BT_ASSERT_DBG(!msg_it
->dscopes
.event_common_context
);
1345 msg_it
->dscopes
.event_common_context
= bt_event_borrow_common_context_field(msg_it
->event
);
1346 BT_ASSERT_DBG(msg_it
->dscopes
.event_common_context
);
1349 BT_CPPLOGT_SPEC(msg_it
->logger
,
1350 "Decoding event common context field: "
1351 "msg-it-addr={}, stream-class-addr={}, "
1352 "stream-class-id={}, "
1354 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.sc
), msg_it
->meta
.sc
->id
,
1355 fmt::ptr(event_common_context_fc
));
1356 status
= read_dscope_begin_state(
1357 msg_it
, event_common_context_fc
, STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN
,
1358 STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE
, msg_it
->dscopes
.event_common_context
);
1360 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
1361 "Cannot decode event common context field: "
1362 "msg-it-addr={}, stream-class-addr={}, "
1363 "stream-class-id={}, fc-addr={}",
1364 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.sc
),
1365 msg_it
->meta
.sc
->id
, fmt::ptr(event_common_context_fc
));
1372 static enum ctf_msg_iter_status
1373 read_event_common_context_continue_state(struct ctf_msg_iter
*msg_it
)
1375 return read_dscope_continue_state(msg_it
, STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN
);
1378 static enum ctf_msg_iter_status
read_event_spec_context_begin_state(struct ctf_msg_iter
*msg_it
)
1380 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
1381 struct ctf_field_class
*event_spec_context_fc
;
1383 event_spec_context_fc
= msg_it
->meta
.ec
->spec_context_fc
;
1384 if (!event_spec_context_fc
) {
1385 msg_it
->state
= STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
;
1389 if (event_spec_context_fc
->in_ir
&& !msg_it
->dry_run
) {
1390 BT_ASSERT_DBG(!msg_it
->dscopes
.event_spec_context
);
1391 msg_it
->dscopes
.event_spec_context
= bt_event_borrow_specific_context_field(msg_it
->event
);
1392 BT_ASSERT_DBG(msg_it
->dscopes
.event_spec_context
);
1395 BT_CPPLOGT_SPEC(msg_it
->logger
,
1396 "Decoding event specific context field: "
1397 "msg-it-addr={}, event-class-addr={}, "
1398 "event-class-name=\"{}\", event-class-id={}, "
1400 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.ec
), msg_it
->meta
.ec
->name
->str
,
1401 msg_it
->meta
.ec
->id
, fmt::ptr(event_spec_context_fc
));
1402 status
= read_dscope_begin_state(
1403 msg_it
, event_spec_context_fc
, STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
,
1404 STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE
, msg_it
->dscopes
.event_spec_context
);
1406 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
1407 "Cannot decode event specific context field: "
1408 "msg-it-addr={}, event-class-addr={}, "
1409 "event-class-name=\"{}\", "
1410 "event-class-id={}, fc-addr={}",
1411 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.ec
),
1412 msg_it
->meta
.ec
->name
->str
, msg_it
->meta
.ec
->id
,
1413 fmt::ptr(event_spec_context_fc
));
1420 static enum ctf_msg_iter_status
read_event_spec_context_continue_state(struct ctf_msg_iter
*msg_it
)
1422 return read_dscope_continue_state(msg_it
, STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
);
1425 static enum ctf_msg_iter_status
read_event_payload_begin_state(struct ctf_msg_iter
*msg_it
)
1427 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
1428 struct ctf_field_class
*event_payload_fc
;
1430 event_payload_fc
= msg_it
->meta
.ec
->payload_fc
;
1431 if (!event_payload_fc
) {
1432 msg_it
->state
= STATE_EMIT_MSG_EVENT
;
1436 if (event_payload_fc
->in_ir
&& !msg_it
->dry_run
) {
1437 BT_ASSERT_DBG(!msg_it
->dscopes
.event_payload
);
1438 msg_it
->dscopes
.event_payload
= bt_event_borrow_payload_field(msg_it
->event
);
1439 BT_ASSERT_DBG(msg_it
->dscopes
.event_payload
);
1442 BT_CPPLOGT_SPEC(msg_it
->logger
,
1443 "Decoding event payload field: "
1444 "msg-it-addr={}, event-class-addr={}, "
1445 "event-class-name=\"{}\", event-class-id={}, "
1447 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.ec
), msg_it
->meta
.ec
->name
->str
,
1448 msg_it
->meta
.ec
->id
, fmt::ptr(event_payload_fc
));
1450 read_dscope_begin_state(msg_it
, event_payload_fc
, STATE_EMIT_MSG_EVENT
,
1451 STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
, msg_it
->dscopes
.event_payload
);
1453 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
1454 "Cannot decode event payload field: "
1455 "msg-it-addr={}, event-class-addr={}, "
1456 "event-class-name=\"{}\", "
1457 "event-class-id={}, fc-addr={}",
1458 fmt::ptr(msg_it
), fmt::ptr(msg_it
->meta
.ec
),
1459 msg_it
->meta
.ec
->name
->str
, msg_it
->meta
.ec
->id
,
1460 fmt::ptr(event_payload_fc
));
1467 static enum ctf_msg_iter_status
read_event_payload_continue_state(struct ctf_msg_iter
*msg_it
)
1469 return read_dscope_continue_state(msg_it
, STATE_EMIT_MSG_EVENT
);
1472 static enum ctf_msg_iter_status
skip_packet_padding_state(struct ctf_msg_iter
*msg_it
)
1474 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
1475 size_t bits_to_skip
;
1476 const enum state next_state
= STATE_SWITCH_PACKET
;
1478 BT_ASSERT(msg_it
->cur_exp_packet_total_size
> 0);
1479 bits_to_skip
= msg_it
->cur_exp_packet_total_size
- packet_at(msg_it
);
1480 if (bits_to_skip
== 0) {
1481 msg_it
->state
= next_state
;
1484 size_t bits_to_consume
;
1486 BT_CPPLOGD_SPEC(msg_it
->logger
,
1487 "Trying to skip {} bits of padding: msg-it-addr={}, size={}", bits_to_skip
,
1488 fmt::ptr(msg_it
), bits_to_skip
);
1489 status
= buf_ensure_available_bits(msg_it
);
1490 if (status
!= CTF_MSG_ITER_STATUS_OK
) {
1494 bits_to_consume
= MIN(buf_available_bits(msg_it
), bits_to_skip
);
1495 BT_CPPLOGD_SPEC(msg_it
->logger
, "Skipping {} bits of padding: msg-it-addr={}, size={}",
1496 bits_to_consume
, fmt::ptr(msg_it
), bits_to_consume
);
1497 buf_consume_bits(msg_it
, bits_to_consume
);
1498 bits_to_skip
= msg_it
->cur_exp_packet_total_size
- packet_at(msg_it
);
1499 if (bits_to_skip
== 0) {
1500 msg_it
->state
= next_state
;
1509 static enum ctf_msg_iter_status
check_emit_msg_discarded_events(struct ctf_msg_iter
*msg_it
)
1511 msg_it
->state
= STATE_EMIT_MSG_DISCARDED_EVENTS
;
1513 if (!msg_it
->meta
.sc
->has_discarded_events
) {
1514 msg_it
->state
= STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS
;
1518 if (msg_it
->prev_packet_snapshots
.discarded_events
== UINT64_C(-1)) {
1519 if (msg_it
->snapshots
.discarded_events
== 0 ||
1520 msg_it
->snapshots
.discarded_events
== UINT64_C(-1)) {
1522 * Stream's first packet with no discarded
1523 * events or no information about discarded
1524 * events: do not emit.
1526 msg_it
->state
= STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS
;
1530 * If the previous packet has a value for this counter,
1531 * then this counter is defined for the whole stream.
1533 BT_ASSERT(msg_it
->snapshots
.discarded_events
!= UINT64_C(-1));
1535 if (msg_it
->snapshots
.discarded_events
- msg_it
->prev_packet_snapshots
.discarded_events
==
1538 * No discarded events since previous packet: do
1541 msg_it
->state
= STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS
;
1546 return CTF_MSG_ITER_STATUS_OK
;
1549 static enum ctf_msg_iter_status
check_emit_msg_discarded_packets(struct ctf_msg_iter
*msg_it
)
1551 msg_it
->state
= STATE_EMIT_MSG_DISCARDED_PACKETS
;
1553 if (!msg_it
->meta
.sc
->has_discarded_packets
) {
1554 msg_it
->state
= STATE_EMIT_MSG_PACKET_BEGINNING
;
1558 if (msg_it
->prev_packet_snapshots
.packets
== UINT64_C(-1)) {
1560 * Stream's first packet or no information about
1561 * discarded packets: do not emit. In other words, if
1562 * this is the first packet and its sequence number is
1563 * not 0, do not consider that packets were previously
1564 * lost: we might be reading a partial stream (LTTng
1565 * snapshot for example).
1567 msg_it
->state
= STATE_EMIT_MSG_PACKET_BEGINNING
;
1570 * If the previous packet has a value for this counter,
1571 * then this counter is defined for the whole stream.
1573 BT_ASSERT(msg_it
->snapshots
.packets
!= UINT64_C(-1));
1575 if (msg_it
->snapshots
.packets
- msg_it
->prev_packet_snapshots
.packets
<= 1) {
1577 * No discarded packets since previous packet:
1580 msg_it
->state
= STATE_EMIT_MSG_PACKET_BEGINNING
;
1585 return CTF_MSG_ITER_STATUS_OK
;
1588 static inline enum state
check_emit_msg_stream_end(struct ctf_msg_iter
*msg_it
)
1590 enum state next_state
;
1592 if (msg_it
->emit_stream_end_message
) {
1593 next_state
= STATE_EMIT_MSG_STREAM_END
;
1595 next_state
= STATE_DONE
;
1601 static inline enum ctf_msg_iter_status
handle_state(struct ctf_msg_iter
*msg_it
)
1603 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
1604 const enum state state
= msg_it
->state
;
1606 BT_CPPLOGT_SPEC(msg_it
->logger
, "Handling state: msg-it-addr={}, state={}", fmt::ptr(msg_it
),
1609 // TODO: optimalize!
1612 msg_it
->state
= STATE_SWITCH_PACKET
;
1614 case STATE_SWITCH_PACKET
:
1615 status
= switch_packet_state(msg_it
);
1617 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
:
1618 status
= read_packet_header_begin_state(msg_it
);
1620 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
:
1621 status
= read_packet_header_continue_state(msg_it
);
1623 case STATE_AFTER_TRACE_PACKET_HEADER
:
1624 status
= after_packet_header_state(msg_it
);
1626 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
:
1627 status
= read_packet_context_begin_state(msg_it
);
1629 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
:
1630 status
= read_packet_context_continue_state(msg_it
);
1632 case STATE_AFTER_STREAM_PACKET_CONTEXT
:
1633 status
= after_packet_context_state(msg_it
);
1635 case STATE_EMIT_MSG_STREAM_BEGINNING
:
1636 msg_it
->state
= STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS
;
1638 case STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS
:
1639 status
= check_emit_msg_discarded_events(msg_it
);
1641 case STATE_EMIT_MSG_DISCARDED_EVENTS
:
1642 msg_it
->state
= STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS
;
1644 case STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS
:
1645 status
= check_emit_msg_discarded_packets(msg_it
);
1647 case STATE_EMIT_MSG_DISCARDED_PACKETS
:
1648 msg_it
->state
= STATE_EMIT_MSG_PACKET_BEGINNING
;
1650 case STATE_EMIT_MSG_PACKET_BEGINNING
:
1651 msg_it
->state
= STATE_DSCOPE_EVENT_HEADER_BEGIN
;
1653 case STATE_DSCOPE_EVENT_HEADER_BEGIN
:
1654 status
= read_event_header_begin_state(msg_it
);
1656 case STATE_DSCOPE_EVENT_HEADER_CONTINUE
:
1657 status
= read_event_header_continue_state(msg_it
);
1659 case STATE_AFTER_EVENT_HEADER
:
1660 status
= after_event_header_state(msg_it
);
1662 case STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN
:
1663 status
= read_event_common_context_begin_state(msg_it
);
1665 case STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE
:
1666 status
= read_event_common_context_continue_state(msg_it
);
1668 case STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN
:
1669 status
= read_event_spec_context_begin_state(msg_it
);
1671 case STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE
:
1672 status
= read_event_spec_context_continue_state(msg_it
);
1674 case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
:
1675 status
= read_event_payload_begin_state(msg_it
);
1677 case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
:
1678 status
= read_event_payload_continue_state(msg_it
);
1680 case STATE_EMIT_MSG_EVENT
:
1681 msg_it
->state
= STATE_DSCOPE_EVENT_HEADER_BEGIN
;
1683 case STATE_EMIT_QUEUED_MSG_EVENT
:
1684 msg_it
->state
= STATE_EMIT_MSG_EVENT
;
1686 case STATE_SKIP_PACKET_PADDING
:
1687 status
= skip_packet_padding_state(msg_it
);
1689 case STATE_EMIT_MSG_PACKET_END_MULTI
:
1690 msg_it
->state
= STATE_SKIP_PACKET_PADDING
;
1692 case STATE_EMIT_MSG_PACKET_END_SINGLE
:
1693 msg_it
->state
= STATE_EMIT_MSG_STREAM_END
;
1695 case STATE_EMIT_QUEUED_MSG_PACKET_END
:
1696 msg_it
->state
= STATE_EMIT_MSG_PACKET_END_SINGLE
;
1698 case STATE_CHECK_EMIT_MSG_STREAM_END
:
1699 msg_it
->state
= check_emit_msg_stream_end(msg_it
);
1701 case STATE_EMIT_MSG_STREAM_END
:
1702 msg_it
->state
= STATE_DONE
;
1707 BT_CPPLOGF_SPEC(msg_it
->logger
,
1708 "Unknown CTF plugin message iterator state: "
1709 "msg-it-addr={}, state={}",
1710 fmt::ptr(msg_it
), msg_it
->state
);
1714 BT_CPPLOGT_SPEC(msg_it
->logger
,
1715 "Handled state: msg-it-addr={}, status={}, "
1716 "prev-state={}, cur-state={}",
1717 fmt::ptr(msg_it
), status
, state
, msg_it
->state
);
1721 void ctf_msg_iter_reset_for_next_stream_file(struct ctf_msg_iter
*msg_it
)
1724 BT_CPPLOGD_SPEC(msg_it
->logger
, "Resetting message iterator: addr={}", fmt::ptr(msg_it
));
1725 stack_clear(msg_it
->stack
);
1726 msg_it
->meta
.sc
= NULL
;
1727 msg_it
->meta
.ec
= NULL
;
1728 BT_PACKET_PUT_REF_AND_RESET(msg_it
->packet
);
1729 BT_STREAM_PUT_REF_AND_RESET(msg_it
->stream
);
1730 BT_MESSAGE_PUT_REF_AND_RESET(msg_it
->event_msg
);
1731 release_all_dscopes(msg_it
);
1732 msg_it
->cur_dscope_field
= NULL
;
1734 msg_it
->buf
.addr
= NULL
;
1737 msg_it
->buf
.last_eh_at
= SIZE_MAX
;
1738 msg_it
->buf
.packet_offset
= 0;
1739 msg_it
->state
= STATE_INIT
;
1740 msg_it
->cur_exp_packet_content_size
= -1;
1741 msg_it
->cur_exp_packet_total_size
= -1;
1742 msg_it
->cur_packet_offset
= -1;
1743 msg_it
->cur_event_class_id
= -1;
1744 msg_it
->snapshots
.beginning_clock
= UINT64_C(-1);
1745 msg_it
->snapshots
.end_clock
= UINT64_C(-1);
1749 * Resets the internal state of a CTF message iterator.
1751 void ctf_msg_iter_reset(struct ctf_msg_iter
*msg_it
)
1753 ctf_msg_iter_reset_for_next_stream_file(msg_it
);
1754 msg_it
->cur_stream_class_id
= -1;
1755 msg_it
->cur_data_stream_id
= -1;
1756 msg_it
->snapshots
.discarded_events
= UINT64_C(-1);
1757 msg_it
->snapshots
.packets
= UINT64_C(-1);
1758 msg_it
->prev_packet_snapshots
.discarded_events
= UINT64_C(-1);
1759 msg_it
->prev_packet_snapshots
.packets
= UINT64_C(-1);
1760 msg_it
->prev_packet_snapshots
.beginning_clock
= UINT64_C(-1);
1761 msg_it
->prev_packet_snapshots
.end_clock
= UINT64_C(-1);
1762 msg_it
->emit_stream_beginning_message
= true;
1763 msg_it
->emit_stream_end_message
= false;
1766 static bt_field
*borrow_next_field(struct ctf_msg_iter
*msg_it
)
1768 bt_field
*next_field
= NULL
;
1769 bt_field
*base_field
;
1770 const bt_field_class
*base_fc
;
1771 bt_field_class_type base_fc_type
;
1774 BT_ASSERT_DBG(!stack_empty(msg_it
->stack
));
1775 index
= stack_top(msg_it
->stack
)->index
;
1776 base_field
= stack_top(msg_it
->stack
)->base
;
1777 BT_ASSERT_DBG(base_field
);
1778 base_fc
= bt_field_borrow_class_const(base_field
);
1779 BT_ASSERT_DBG(base_fc
);
1780 base_fc_type
= bt_field_class_get_type(base_fc
);
1782 if (base_fc_type
== BT_FIELD_CLASS_TYPE_STRUCTURE
) {
1783 BT_ASSERT_DBG(index
< bt_field_class_structure_get_member_count(
1784 bt_field_borrow_class_const(base_field
)));
1785 next_field
= bt_field_structure_borrow_member_field_by_index(base_field
, index
);
1786 } else if (bt_field_class_type_is(base_fc_type
, BT_FIELD_CLASS_TYPE_ARRAY
)) {
1787 BT_ASSERT_DBG(index
< bt_field_array_get_length(base_field
));
1788 next_field
= bt_field_array_borrow_element_field_by_index(base_field
, index
);
1789 } else if (bt_field_class_type_is(base_fc_type
, BT_FIELD_CLASS_TYPE_VARIANT
)) {
1790 BT_ASSERT_DBG(index
== 0);
1791 next_field
= bt_field_variant_borrow_selected_option_field(base_field
);
1796 BT_ASSERT_DBG(next_field
);
1800 static void update_default_clock(struct ctf_msg_iter
*msg_it
, uint64_t new_val
,
1801 uint64_t new_val_size
)
1803 uint64_t new_val_mask
;
1804 uint64_t cur_value_masked
;
1806 BT_ASSERT_DBG(new_val_size
> 0);
1809 * Special case for a 64-bit new value, which is the limit
1810 * of a clock value as of this version: overwrite the
1811 * current value directly.
1813 if (new_val_size
== 64) {
1814 msg_it
->default_clock_snapshot
= new_val
;
1818 new_val_mask
= (1ULL << new_val_size
) - 1;
1819 cur_value_masked
= msg_it
->default_clock_snapshot
& new_val_mask
;
1821 if (new_val
< cur_value_masked
) {
1823 * It looks like a wrap happened on the number of bits
1824 * of the requested new value. Assume that the clock
1825 * value wrapped only one time.
1827 msg_it
->default_clock_snapshot
+= new_val_mask
+ 1;
1830 /* Clear the low bits of the current clock value. */
1831 msg_it
->default_clock_snapshot
&= ~new_val_mask
;
1833 /* Set the low bits of the current clock value. */
1834 msg_it
->default_clock_snapshot
|= new_val
;
1837 BT_CPPLOGT_SPEC(msg_it
->logger
,
1838 "Updated default clock's value from integer field's value: "
1840 msg_it
->default_clock_snapshot
);
1844 * Ensure the message iterator's `stored_values` array is large enough to
1845 * accommodate `storing_index`.
1847 * We may need more slots in the array than initially allocated if more
1848 * metadata arrives along the way.
1850 static void ensure_stored_values_size(ctf_msg_iter
*msg_it
, uint64_t storing_index
)
1852 if (G_UNLIKELY(storing_index
>= msg_it
->stored_values
->len
)) {
1853 g_array_set_size(msg_it
->stored_values
, msg_it
->meta
.tc
->stored_value_count
);
1857 static enum bt_bfcr_status
bfcr_unsigned_int_cb(uint64_t value
, struct ctf_field_class
*fc
,
1860 ctf_msg_iter
*msg_it
= (ctf_msg_iter
*) data
;
1861 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
1863 bt_field
*field
= NULL
;
1865 BT_CPPLOGT_SPEC(msg_it
->logger
,
1866 "Unsigned integer function called from BFCR: "
1867 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
1868 "fc-type={}, fc-in-ir={}, value={}",
1869 fmt::ptr(msg_it
), fmt::ptr(msg_it
->bfcr
), fmt::ptr(fc
), fc
->type
, fc
->in_ir
,
1872 ctf_field_class_int
*int_fc
= ctf_field_class_as_int(fc
);
1874 if (G_LIKELY(int_fc
->meaning
== CTF_FIELD_CLASS_MEANING_NONE
)) {
1875 goto update_def_clock
;
1878 switch (int_fc
->meaning
) {
1879 case CTF_FIELD_CLASS_MEANING_EVENT_CLASS_ID
:
1880 msg_it
->cur_event_class_id
= value
;
1882 case CTF_FIELD_CLASS_MEANING_DATA_STREAM_ID
:
1883 msg_it
->cur_data_stream_id
= value
;
1885 case CTF_FIELD_CLASS_MEANING_PACKET_BEGINNING_TIME
:
1886 msg_it
->snapshots
.beginning_clock
= value
;
1888 case CTF_FIELD_CLASS_MEANING_PACKET_END_TIME
:
1889 msg_it
->snapshots
.end_clock
= value
;
1891 case CTF_FIELD_CLASS_MEANING_STREAM_CLASS_ID
:
1892 msg_it
->cur_stream_class_id
= value
;
1894 case CTF_FIELD_CLASS_MEANING_MAGIC
:
1895 if (value
!= 0xc1fc1fc1) {
1896 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
1897 "Invalid CTF magic number: msg-it-addr={}, magic={}",
1898 fmt::ptr(msg_it
), value
);
1899 status
= BT_BFCR_STATUS_ERROR
;
1904 case CTF_FIELD_CLASS_MEANING_PACKET_COUNTER_SNAPSHOT
:
1905 msg_it
->snapshots
.packets
= value
;
1907 case CTF_FIELD_CLASS_MEANING_DISC_EV_REC_COUNTER_SNAPSHOT
:
1908 msg_it
->snapshots
.discarded_events
= value
;
1910 case CTF_FIELD_CLASS_MEANING_EXP_PACKET_TOTAL_SIZE
:
1911 msg_it
->cur_exp_packet_total_size
= value
;
1913 case CTF_FIELD_CLASS_MEANING_EXP_PACKET_CONTENT_SIZE
:
1914 msg_it
->cur_exp_packet_content_size
= value
;
1921 if (G_UNLIKELY(int_fc
->mapped_clock_class
)) {
1922 update_default_clock(msg_it
, value
, int_fc
->base
.size
);
1925 if (G_UNLIKELY(int_fc
->storing_index
>= 0)) {
1926 ensure_stored_values_size(msg_it
, int_fc
->storing_index
);
1927 bt_g_array_index(msg_it
->stored_values
, uint64_t, (uint64_t) int_fc
->storing_index
) = value
;
1930 if (G_UNLIKELY(!fc
->in_ir
|| msg_it
->dry_run
)) {
1934 field
= borrow_next_field(msg_it
);
1935 BT_ASSERT_DBG(field
);
1936 BT_ASSERT_DBG(bt_field_borrow_class_const(field
) == fc
->ir_fc
);
1937 BT_ASSERT_DBG(bt_field_class_type_is(bt_field_get_class_type(field
),
1938 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
));
1939 bt_field_integer_unsigned_set_value(field
, value
);
1940 stack_top(msg_it
->stack
)->index
++;
1946 static enum bt_bfcr_status
bfcr_unsigned_int_char_cb(uint64_t value
, struct ctf_field_class
*fc
,
1950 ctf_msg_iter
*msg_it
= (ctf_msg_iter
*) data
;
1951 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
1952 bt_field
*string_field
= NULL
;
1953 char str
[2] = {'\0', '\0'};
1955 BT_CPPLOGT_SPEC(msg_it
->logger
,
1956 "Unsigned integer character function called from BFCR: "
1957 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
1958 "fc-type={}, fc-in-ir={}, value={}",
1959 fmt::ptr(msg_it
), fmt::ptr(msg_it
->bfcr
), fmt::ptr(fc
), fc
->type
, fc
->in_ir
,
1962 ctf_field_class_int
*int_fc
= ctf_field_class_as_int(fc
);
1963 BT_ASSERT_DBG(int_fc
->meaning
== CTF_FIELD_CLASS_MEANING_NONE
);
1964 BT_ASSERT_DBG(!int_fc
->mapped_clock_class
);
1965 BT_ASSERT_DBG(int_fc
->storing_index
< 0);
1967 if (G_UNLIKELY(!fc
->in_ir
|| msg_it
->dry_run
)) {
1971 if (msg_it
->done_filling_string
) {
1976 msg_it
->done_filling_string
= true;
1980 string_field
= stack_top(msg_it
->stack
)->base
;
1981 BT_ASSERT_DBG(bt_field_get_class_type(string_field
) == BT_FIELD_CLASS_TYPE_STRING
);
1983 /* Append character */
1984 str
[0] = (char) value
;
1985 ret
= bt_field_string_append_with_length(string_field
, str
, 1);
1987 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
1988 "Cannot append character to string field's value: "
1989 "msg-it-addr={}, field-addr={}, ret={}",
1990 fmt::ptr(msg_it
), fmt::ptr(string_field
), ret
);
1991 status
= BT_BFCR_STATUS_ERROR
;
1999 static enum bt_bfcr_status
bfcr_signed_int_cb(int64_t value
, struct ctf_field_class
*fc
, void *data
)
2001 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
2002 bt_field
*field
= NULL
;
2003 ctf_msg_iter
*msg_it
= (ctf_msg_iter
*) data
;
2005 BT_CPPLOGT_SPEC(msg_it
->logger
,
2006 "Signed integer function called from BFCR: "
2007 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
2008 "fc-type={}, fc-in-ir={}, value={}",
2009 fmt::ptr(msg_it
), fmt::ptr(msg_it
->bfcr
), fmt::ptr(fc
), fc
->type
, fc
->in_ir
,
2012 ctf_field_class_int
*int_fc
= ctf_field_class_as_int(fc
);
2013 BT_ASSERT_DBG(int_fc
->meaning
== CTF_FIELD_CLASS_MEANING_NONE
);
2015 if (G_UNLIKELY(int_fc
->storing_index
>= 0)) {
2016 ensure_stored_values_size(msg_it
, int_fc
->storing_index
);
2017 bt_g_array_index(msg_it
->stored_values
, uint64_t, (uint64_t) int_fc
->storing_index
) =
2021 if (G_UNLIKELY(!fc
->in_ir
|| msg_it
->dry_run
)) {
2025 field
= borrow_next_field(msg_it
);
2026 BT_ASSERT_DBG(field
);
2027 BT_ASSERT_DBG(bt_field_borrow_class_const(field
) == fc
->ir_fc
);
2029 bt_field_class_type_is(bt_field_get_class_type(field
), BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
));
2030 bt_field_integer_signed_set_value(field
, value
);
2031 stack_top(msg_it
->stack
)->index
++;
2037 static enum bt_bfcr_status
bfcr_floating_point_cb(double value
, struct ctf_field_class
*fc
,
2040 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
2041 bt_field
*field
= NULL
;
2042 ctf_msg_iter
*msg_it
= (ctf_msg_iter
*) data
;
2043 bt_field_class_type type
;
2045 BT_CPPLOGT_SPEC(msg_it
->logger
,
2046 "Floating point number function called from BFCR: "
2047 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
2048 "fc-type={}, fc-in-ir={}, value={}",
2049 fmt::ptr(msg_it
), fmt::ptr(msg_it
->bfcr
), fmt::ptr(fc
), fc
->type
, fc
->in_ir
,
2052 if (G_UNLIKELY(!fc
->in_ir
|| msg_it
->dry_run
)) {
2056 field
= borrow_next_field(msg_it
);
2057 type
= bt_field_get_class_type(field
);
2058 BT_ASSERT_DBG(field
);
2059 BT_ASSERT_DBG(bt_field_borrow_class_const(field
) == fc
->ir_fc
);
2060 BT_ASSERT_DBG(bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_REAL
));
2062 if (type
== BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL
) {
2063 bt_field_real_single_precision_set_value(field
, (float) value
);
2065 bt_field_real_double_precision_set_value(field
, value
);
2067 stack_top(msg_it
->stack
)->index
++;
2073 static enum bt_bfcr_status
bfcr_string_begin_cb(struct ctf_field_class
*fc
, void *data
)
2075 bt_field
*field
= NULL
;
2076 ctf_msg_iter
*msg_it
= (ctf_msg_iter
*) data
;
2078 BT_CPPLOGT_SPEC(msg_it
->logger
,
2079 "String (beginning) function called from BFCR: "
2080 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
2081 "fc-type={}, fc-in-ir={}",
2082 fmt::ptr(msg_it
), fmt::ptr(msg_it
->bfcr
), fmt::ptr(fc
), fc
->type
, fc
->in_ir
);
2084 if (G_UNLIKELY(!fc
->in_ir
|| msg_it
->dry_run
)) {
2088 field
= borrow_next_field(msg_it
);
2089 BT_ASSERT_DBG(field
);
2090 BT_ASSERT_DBG(bt_field_borrow_class_const(field
) == fc
->ir_fc
);
2091 BT_ASSERT_DBG(bt_field_get_class_type(field
) == BT_FIELD_CLASS_TYPE_STRING
);
2092 bt_field_string_clear(field
);
2095 * Push on stack. Not a compound class per se, but we know that
2096 * only bfcr_string_cb() may be called between this call and a
2097 * subsequent call to bfcr_string_end_cb().
2099 stack_push(msg_it
->stack
, field
);
2102 return BT_BFCR_STATUS_OK
;
2105 static enum bt_bfcr_status
bfcr_string_cb(const char *value
, size_t len
, struct ctf_field_class
*fc
,
2108 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
2109 bt_field
*field
= NULL
;
2110 ctf_msg_iter
*msg_it
= (ctf_msg_iter
*) data
;
2113 BT_CPPLOGT_SPEC(msg_it
->logger
,
2114 "String (substring) function called from BFCR: "
2115 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
2116 "fc-type={}, fc-in-ir={}, string-length={}",
2117 fmt::ptr(msg_it
), fmt::ptr(msg_it
->bfcr
), fmt::ptr(fc
), fc
->type
, fc
->in_ir
,
2120 if (G_UNLIKELY(!fc
->in_ir
|| msg_it
->dry_run
)) {
2124 field
= stack_top(msg_it
->stack
)->base
;
2125 BT_ASSERT_DBG(field
);
2127 /* Append current substring */
2128 ret
= bt_field_string_append_with_length(field
, value
, len
);
2130 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
2131 "Cannot append substring to string field's value: "
2132 "msg-it-addr={}, field-addr={}, string-length={}, "
2134 fmt::ptr(msg_it
), fmt::ptr(field
), len
, ret
);
2135 status
= BT_BFCR_STATUS_ERROR
;
2143 static enum bt_bfcr_status
bfcr_string_end_cb(struct ctf_field_class
*fc
, void *data
)
2145 ctf_msg_iter
*msg_it
= (ctf_msg_iter
*) data
;
2147 BT_CPPLOGT_SPEC(msg_it
->logger
,
2148 "String (end) function called from BFCR: "
2149 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
2150 "fc-type={}, fc-in-ir={}",
2151 fmt::ptr(msg_it
), fmt::ptr(msg_it
->bfcr
), fmt::ptr(fc
), fc
->type
, fc
->in_ir
);
2153 if (G_UNLIKELY(!fc
->in_ir
|| msg_it
->dry_run
)) {
2157 /* Pop string field */
2158 stack_pop(msg_it
->stack
);
2160 /* Go to next field */
2161 stack_top(msg_it
->stack
)->index
++;
2164 return BT_BFCR_STATUS_OK
;
2167 static enum bt_bfcr_status
bfcr_compound_begin_cb(struct ctf_field_class
*fc
, void *data
)
2169 ctf_msg_iter
*msg_it
= (ctf_msg_iter
*) data
;
2172 BT_CPPLOGT_SPEC(msg_it
->logger
,
2173 "Compound (beginning) function called from BFCR: "
2174 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
2175 "fc-type={}, fc-in-ir={}",
2176 fmt::ptr(msg_it
), fmt::ptr(msg_it
->bfcr
), fmt::ptr(fc
), fc
->type
, fc
->in_ir
);
2178 if (G_UNLIKELY(!fc
->in_ir
|| msg_it
->dry_run
)) {
2183 if (stack_empty(msg_it
->stack
)) {
2184 /* Root: already set by read_dscope_begin_state() */
2185 field
= msg_it
->cur_dscope_field
;
2187 field
= borrow_next_field(msg_it
);
2188 BT_ASSERT_DBG(field
);
2192 BT_ASSERT_DBG(field
);
2193 BT_ASSERT_DBG(bt_field_borrow_class_const(field
) == fc
->ir_fc
);
2194 stack_push(msg_it
->stack
, field
);
2197 * Change BFCR "unsigned int" callback if it's a text
2200 if (fc
->type
== CTF_FIELD_CLASS_TYPE_ARRAY
|| fc
->type
== CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
2201 ctf_field_class_array_base
*array_fc
= ctf_field_class_as_array_base(fc
);
2203 if (array_fc
->is_text
) {
2204 BT_ASSERT_DBG(bt_field_get_class_type(field
) == BT_FIELD_CLASS_TYPE_STRING
);
2205 msg_it
->done_filling_string
= false;
2206 bt_field_string_clear(field
);
2207 bt_bfcr_set_unsigned_int_cb(msg_it
->bfcr
, bfcr_unsigned_int_char_cb
);
2212 return BT_BFCR_STATUS_OK
;
2215 static enum bt_bfcr_status
bfcr_compound_end_cb(struct ctf_field_class
*fc
, void *data
)
2217 ctf_msg_iter
*msg_it
= (ctf_msg_iter
*) data
;
2219 BT_CPPLOGT_SPEC(msg_it
->logger
,
2220 "Compound (end) function called from BFCR: "
2221 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
2222 "fc-type={}, fc-in-ir={}",
2223 fmt::ptr(msg_it
), fmt::ptr(msg_it
->bfcr
), fmt::ptr(fc
), fc
->type
, fc
->in_ir
);
2225 if (G_UNLIKELY(!fc
->in_ir
|| msg_it
->dry_run
)) {
2229 BT_ASSERT_DBG(!stack_empty(msg_it
->stack
));
2230 BT_ASSERT_DBG(bt_field_borrow_class_const(stack_top(msg_it
->stack
)->base
) == fc
->ir_fc
);
2233 * Reset BFCR "unsigned int" callback if it's a text
2236 if (fc
->type
== CTF_FIELD_CLASS_TYPE_ARRAY
|| fc
->type
== CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
2237 ctf_field_class_array_base
*array_fc
= ctf_field_class_as_array_base(fc
);
2239 if (array_fc
->is_text
) {
2240 BT_ASSERT_DBG(bt_field_get_class_type(stack_top(msg_it
->stack
)->base
) ==
2241 BT_FIELD_CLASS_TYPE_STRING
);
2242 bt_bfcr_set_unsigned_int_cb(msg_it
->bfcr
, bfcr_unsigned_int_cb
);
2247 stack_pop(msg_it
->stack
);
2249 /* If the stack is not empty, increment the base's index */
2250 if (!stack_empty(msg_it
->stack
)) {
2251 stack_top(msg_it
->stack
)->index
++;
2255 return BT_BFCR_STATUS_OK
;
2258 static int64_t bfcr_get_sequence_length_cb(struct ctf_field_class
*fc
, void *data
)
2260 bt_field
*seq_field
;
2261 ctf_msg_iter
*msg_it
= (ctf_msg_iter
*) data
;
2262 struct ctf_field_class_sequence
*seq_fc
= ctf_field_class_as_sequence(fc
);
2267 (uint64_t) bt_g_array_index(msg_it
->stored_values
, uint64_t, seq_fc
->stored_length_index
);
2269 if (G_UNLIKELY(msg_it
->dry_run
)) {
2273 seq_field
= stack_top(msg_it
->stack
)->base
;
2274 BT_ASSERT_DBG(seq_field
);
2277 * bfcr_get_sequence_length_cb() also gets called back for a
2278 * text sequence, but the destination field is a string field.
2279 * Only set the field's sequence length if the destination field
2280 * is a sequence field.
2282 if (!seq_fc
->base
.is_text
) {
2283 BT_ASSERT_DBG(bt_field_class_type_is(bt_field_get_class_type(seq_field
),
2284 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
));
2285 ret
= bt_field_array_dynamic_set_length(seq_field
, (uint64_t) length
);
2287 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
2288 "Cannot set dynamic array field's length field: "
2289 "msg-it-addr={}, field-addr={}, "
2291 fmt::ptr(msg_it
), fmt::ptr(seq_field
), length
);
2300 static struct ctf_field_class
*
2301 bfcr_borrow_variant_selected_field_class_cb(struct ctf_field_class
*fc
, void *data
)
2305 int64_t option_index
= -1;
2306 ctf_msg_iter
*msg_it
= (ctf_msg_iter
*) data
;
2307 ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(fc
);
2308 struct ctf_named_field_class
*selected_option
= NULL
;
2309 struct ctf_field_class
*ret_fc
= NULL
;
2316 /* Get variant's tag */
2317 tag
.u
= bt_g_array_index(msg_it
->stored_values
, uint64_t, var_fc
->stored_tag_index
);
2320 * Check each range to find the selected option's index.
2322 if (var_fc
->tag_fc
->base
.is_signed
) {
2323 for (i
= 0; i
< var_fc
->ranges
->len
; i
++) {
2324 struct ctf_field_class_variant_range
*range
=
2325 ctf_field_class_variant_borrow_range_by_index(var_fc
, i
);
2327 if (tag
.i
>= range
->range
.lower
.i
&& tag
.i
<= range
->range
.upper
.i
) {
2328 option_index
= (int64_t) range
->option_index
;
2333 for (i
= 0; i
< var_fc
->ranges
->len
; i
++) {
2334 struct ctf_field_class_variant_range
*range
=
2335 ctf_field_class_variant_borrow_range_by_index(var_fc
, i
);
2337 if (tag
.u
>= range
->range
.lower
.u
&& tag
.u
<= range
->range
.upper
.u
) {
2338 option_index
= (int64_t) range
->option_index
;
2344 if (option_index
< 0) {
2345 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
2346 "Cannot find variant field class's option: "
2347 "msg-it-addr={}, var-fc-addr={}, u-tag={}, "
2349 fmt::ptr(msg_it
), fmt::ptr(var_fc
), tag
.u
, tag
.i
);
2355 ctf_field_class_variant_borrow_option_by_index(var_fc
, (uint64_t) option_index
);
2357 if (selected_option
->fc
->in_ir
&& !msg_it
->dry_run
) {
2358 bt_field
*var_field
= stack_top(msg_it
->stack
)->base
;
2360 ret
= bt_field_variant_select_option_by_index(var_field
, option_index
);
2362 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
2363 "Cannot select variant field's option field: "
2364 "msg-it-addr={}, var-field-addr={}, "
2366 fmt::ptr(msg_it
), fmt::ptr(var_field
), option_index
);
2372 ret_fc
= selected_option
->fc
;
2378 static bt_message
*create_msg_stream_beginning(struct ctf_msg_iter
*msg_it
)
2382 BT_ASSERT(msg_it
->stream
);
2383 BT_ASSERT(msg_it
->self_msg_iter
);
2384 msg
= bt_message_stream_beginning_create(msg_it
->self_msg_iter
, msg_it
->stream
);
2386 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
2387 "Cannot create stream beginning message: "
2388 "msg-it-addr={}, stream-addr={}",
2389 fmt::ptr(msg_it
), fmt::ptr(msg_it
->stream
));
2395 static bt_message
*create_msg_stream_end(struct ctf_msg_iter
*msg_it
)
2399 if (!msg_it
->stream
) {
2400 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
2401 "Cannot create stream end message because stream is NULL: "
2408 BT_ASSERT(msg_it
->self_msg_iter
);
2409 msg
= bt_message_stream_end_create(msg_it
->self_msg_iter
, msg_it
->stream
);
2411 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
2412 "Cannot create stream end message: "
2413 "msg-it-addr={}, stream-addr={}",
2414 fmt::ptr(msg_it
), fmt::ptr(msg_it
->stream
));
2421 static bt_message
*create_msg_packet_beginning(struct ctf_msg_iter
*msg_it
, bool use_default_cs
)
2424 const bt_stream_class
*sc
= msg_it
->meta
.sc
->ir_sc
;
2426 BT_ASSERT(msg_it
->packet
);
2428 BT_ASSERT(msg_it
->self_msg_iter
);
2430 if (msg_it
->meta
.sc
->packets_have_ts_begin
) {
2431 BT_ASSERT(msg_it
->snapshots
.beginning_clock
!= UINT64_C(-1));
2432 uint64_t raw_cs_value
;
2435 * Either use the decoded packet `timestamp_begin` field or the
2436 * current stream's default clock_snapshot.
2438 if (use_default_cs
) {
2439 raw_cs_value
= msg_it
->default_clock_snapshot
;
2441 raw_cs_value
= msg_it
->snapshots
.beginning_clock
;
2444 msg
= bt_message_packet_beginning_create_with_default_clock_snapshot(
2445 msg_it
->self_msg_iter
, msg_it
->packet
, raw_cs_value
);
2447 msg
= bt_message_packet_beginning_create(msg_it
->self_msg_iter
, msg_it
->packet
);
2451 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
2452 "Cannot create packet beginning message: "
2453 "msg-it-addr={}, packet-addr={}",
2454 fmt::ptr(msg_it
), fmt::ptr(msg_it
->packet
));
2462 static bt_message
*emit_delayed_packet_beg_msg(struct ctf_msg_iter
*msg_it
)
2464 bool packet_beg_ts_need_fix_up
;
2466 msg_it
->emit_delayed_packet_beginning_msg
= false;
2469 * Only fix the packet's timestamp_begin if it's larger than the first
2470 * event of the packet. If there was no event in the packet, the
2471 * `default_clock_snapshot` field will be either equal or greater than
2472 * `snapshots.beginning_clock` so there is not fix needed.
2474 packet_beg_ts_need_fix_up
= msg_it
->default_clock_snapshot
< msg_it
->snapshots
.beginning_clock
;
2476 /* create_msg_packet_beginning() logs errors */
2477 return create_msg_packet_beginning(msg_it
, packet_beg_ts_need_fix_up
);
2480 static bt_message
*create_msg_packet_end(struct ctf_msg_iter
*msg_it
)
2483 bool update_default_cs
= true;
2485 if (!msg_it
->packet
) {
2491 * Check if we need to emit the delayed packet
2492 * beginning message instead of the packet end message.
2494 if (G_UNLIKELY(msg_it
->emit_delayed_packet_beginning_msg
)) {
2495 msg
= emit_delayed_packet_beg_msg(msg_it
);
2496 /* Don't forget to emit the packet end message. */
2497 msg_it
->state
= STATE_EMIT_QUEUED_MSG_PACKET_END
;
2501 /* Check if may be affected by lttng-crash timestamp_end quirk. */
2502 if (G_UNLIKELY(msg_it
->meta
.tc
->quirks
.lttng_crash
)) {
2504 * Check if the `timestamp_begin` field is non-zero but
2505 * `timestamp_end` is zero. It means the trace is affected by
2506 * the lttng-crash packet `timestamp_end` quirk and must be
2507 * fixed up by omitting to update the default clock snapshot to
2508 * the `timestamp_end` as is typically done.
2510 if (msg_it
->snapshots
.beginning_clock
!= 0 && msg_it
->snapshots
.end_clock
== 0) {
2511 update_default_cs
= false;
2516 * Check if may be affected by lttng event-after-packet `timestamp_end`
2519 if (msg_it
->meta
.tc
->quirks
.lttng_event_after_packet
) {
2521 * Check if `timestamp_end` is smaller then the current
2522 * default_clock_snapshot (which is set to the last event
2523 * decoded). It means the trace is affected by the lttng
2524 * `event-after-packet` packet `timestamp_end` quirk and must
2525 * be fixed up by omitting to update the default clock snapshot
2526 * to the `timestamp_end` as is typically done.
2528 if (msg_it
->snapshots
.end_clock
< msg_it
->default_clock_snapshot
) {
2529 update_default_cs
= false;
2533 /* Update default clock from packet's end time. */
2534 if (msg_it
->snapshots
.end_clock
!= UINT64_C(-1) && update_default_cs
) {
2535 msg_it
->default_clock_snapshot
= msg_it
->snapshots
.end_clock
;
2538 BT_ASSERT(msg_it
->self_msg_iter
);
2540 if (msg_it
->meta
.sc
->packets_have_ts_end
) {
2541 BT_ASSERT(msg_it
->snapshots
.end_clock
!= UINT64_C(-1));
2542 msg
= bt_message_packet_end_create_with_default_clock_snapshot(
2543 msg_it
->self_msg_iter
, msg_it
->packet
, msg_it
->default_clock_snapshot
);
2545 msg
= bt_message_packet_end_create(msg_it
->self_msg_iter
, msg_it
->packet
);
2549 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
2550 "Cannot create packet end message: "
2551 "msg-it-addr={}, packet-addr={}",
2552 fmt::ptr(msg_it
), fmt::ptr(msg_it
->packet
));
2556 BT_PACKET_PUT_REF_AND_RESET(msg_it
->packet
);
2562 static bt_message
*create_msg_discarded_events(struct ctf_msg_iter
*msg_it
)
2565 uint64_t beginning_raw_value
= UINT64_C(-1);
2566 uint64_t end_raw_value
= UINT64_C(-1);
2568 BT_ASSERT(msg_it
->self_msg_iter
);
2569 BT_ASSERT(msg_it
->stream
);
2570 BT_ASSERT(msg_it
->meta
.sc
->has_discarded_events
);
2572 if (msg_it
->meta
.sc
->discarded_events_have_default_cs
) {
2573 if (msg_it
->prev_packet_snapshots
.discarded_events
== UINT64_C(-1)) {
2575 * We discarded events, but before (and possibly
2576 * including) the current packet: use this packet's time
2577 * range, and do not have a specific count.
2579 beginning_raw_value
= msg_it
->snapshots
.beginning_clock
;
2580 end_raw_value
= msg_it
->snapshots
.end_clock
;
2582 beginning_raw_value
= msg_it
->prev_packet_snapshots
.end_clock
;
2583 end_raw_value
= msg_it
->snapshots
.end_clock
;
2586 BT_ASSERT(beginning_raw_value
!= UINT64_C(-1));
2587 BT_ASSERT(end_raw_value
!= UINT64_C(-1));
2588 msg
= bt_message_discarded_events_create_with_default_clock_snapshots(
2589 msg_it
->self_msg_iter
, msg_it
->stream
, beginning_raw_value
, end_raw_value
);
2591 msg
= bt_message_discarded_events_create(msg_it
->self_msg_iter
, msg_it
->stream
);
2595 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
2596 "Cannot create discarded events message: "
2597 "msg-it-addr={}, stream-addr={}",
2598 fmt::ptr(msg_it
), fmt::ptr(msg_it
->stream
));
2602 if (msg_it
->prev_packet_snapshots
.discarded_events
!= UINT64_C(-1)) {
2603 bt_message_discarded_events_set_count(msg
,
2604 msg_it
->snapshots
.discarded_events
-
2605 msg_it
->prev_packet_snapshots
.discarded_events
);
2612 static bt_message
*create_msg_discarded_packets(struct ctf_msg_iter
*msg_it
)
2616 BT_ASSERT(msg_it
->self_msg_iter
);
2617 BT_ASSERT(msg_it
->stream
);
2618 BT_ASSERT(msg_it
->meta
.sc
->has_discarded_packets
);
2619 BT_ASSERT(msg_it
->prev_packet_snapshots
.packets
!= UINT64_C(-1));
2621 if (msg_it
->meta
.sc
->discarded_packets_have_default_cs
) {
2622 BT_ASSERT(msg_it
->prev_packet_snapshots
.end_clock
!= UINT64_C(-1));
2623 BT_ASSERT(msg_it
->snapshots
.beginning_clock
!= UINT64_C(-1));
2624 msg
= bt_message_discarded_packets_create_with_default_clock_snapshots(
2625 msg_it
->self_msg_iter
, msg_it
->stream
, msg_it
->prev_packet_snapshots
.end_clock
,
2626 msg_it
->snapshots
.beginning_clock
);
2628 msg
= bt_message_discarded_packets_create(msg_it
->self_msg_iter
, msg_it
->stream
);
2632 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
2633 "Cannot create discarded packets message: "
2634 "msg-it-addr={}, stream-addr={}",
2635 fmt::ptr(msg_it
), fmt::ptr(msg_it
->stream
));
2639 bt_message_discarded_packets_set_count(msg
, msg_it
->snapshots
.packets
-
2640 msg_it
->prev_packet_snapshots
.packets
- 1);
2646 ctf_msg_iter_up
ctf_msg_iter_create(struct ctf_trace_class
*tc
, size_t max_request_sz
,
2647 struct ctf_msg_iter_medium_ops medops
, void *data
,
2648 bt_self_message_iterator
*self_msg_iter
,
2649 const bt2c::Logger
& parentLogger
)
2651 struct bt_bfcr_cbs cbs
= {
2654 .signed_int
= bfcr_signed_int_cb
,
2655 .unsigned_int
= bfcr_unsigned_int_cb
,
2656 .floating_point
= bfcr_floating_point_cb
,
2657 .string_begin
= bfcr_string_begin_cb
,
2658 .string
= bfcr_string_cb
,
2659 .string_end
= bfcr_string_end_cb
,
2660 .compound_begin
= bfcr_compound_begin_cb
,
2661 .compound_end
= bfcr_compound_end_cb
,
2665 .get_sequence_length
= bfcr_get_sequence_length_cb
,
2666 .borrow_variant_selected_field_class
= bfcr_borrow_variant_selected_field_class_cb
,
2671 BT_ASSERT(medops
.request_bytes
);
2672 BT_ASSERT(medops
.borrow_stream
);
2673 BT_ASSERT(max_request_sz
> 0);
2675 bt2c::Logger logger
{parentLogger
, "PLUGIN/CTF/MSG-ITER"};
2676 BT_CPPLOGD_SPEC(logger
,
2677 "Creating CTF plugin message iterator: "
2678 "trace-addr={}, max-request-size={}, "
2679 "data={}, log-level={}",
2680 fmt::ptr(tc
), max_request_sz
, fmt::ptr(data
), logger
.level());
2682 ctf_msg_iter_up msg_it
{new ctf_msg_iter
{std::move(logger
)}};
2683 msg_it
->self_msg_iter
= self_msg_iter
;
2684 msg_it
->meta
.tc
= tc
;
2685 msg_it
->medium
.medops
= medops
;
2686 msg_it
->medium
.max_request_sz
= max_request_sz
;
2687 msg_it
->medium
.data
= data
;
2688 msg_it
->stack
= stack_new(msg_it
.get());
2689 msg_it
->stored_values
= g_array_new(FALSE
, TRUE
, sizeof(uint64_t));
2690 g_array_set_size(msg_it
->stored_values
, tc
->stored_value_count
);
2692 if (!msg_it
->stack
) {
2693 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
, "Failed to create field stack.");
2697 msg_it
->bfcr
= bt_bfcr_create(cbs
, msg_it
.get(), msg_it
->logger
);
2698 if (!msg_it
->bfcr
) {
2699 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
2700 "Failed to create binary class reader (BFCR).");
2704 ctf_msg_iter_reset(msg_it
.get());
2705 BT_CPPLOGD_SPEC(msg_it
->logger
,
2706 "Created CTF plugin message iterator: "
2707 "trace-addr={}, max-request-size={}, "
2708 "data={}, msg-it-addr={}, log-level={}",
2709 fmt::ptr(tc
), max_request_sz
, fmt::ptr(data
), fmt::ptr(msg_it
),
2710 msg_it
->logger
.level());
2711 msg_it
->cur_packet_offset
= 0;
2721 void ctf_msg_iter_destroy(struct ctf_msg_iter
*msg_it
)
2723 BT_PACKET_PUT_REF_AND_RESET(msg_it
->packet
);
2724 BT_STREAM_PUT_REF_AND_RESET(msg_it
->stream
);
2725 release_all_dscopes(msg_it
);
2727 BT_CPPLOGD_SPEC(msg_it
->logger
, "Destroying CTF plugin message iterator: addr={}",
2730 if (msg_it
->stack
) {
2731 BT_CPPLOGD_SPEC(msg_it
->logger
, "Destroying field stack.");
2732 stack_destroy(msg_it
->stack
);
2736 BT_CPPLOGD_SPEC(msg_it
->logger
, "Destroying BFCR: bfcr-addr={}", fmt::ptr(msg_it
->bfcr
));
2737 bt_bfcr_destroy(msg_it
->bfcr
);
2740 if (msg_it
->stored_values
) {
2741 g_array_free(msg_it
->stored_values
, TRUE
);
2747 void ctf_msg_iter_deleter::operator()(ctf_msg_iter
*iter
) noexcept
2749 ctf_msg_iter_destroy(iter
);
2752 enum ctf_msg_iter_status
ctf_msg_iter_get_next_message(struct ctf_msg_iter
*msg_it
,
2753 const bt_message
**message
)
2755 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
2757 BT_ASSERT_DBG(msg_it
);
2758 BT_ASSERT_DBG(message
);
2759 BT_CPPLOGD_SPEC(msg_it
->logger
, "Getting next message: msg-it-addr={}", fmt::ptr(msg_it
));
2762 status
= handle_state(msg_it
);
2763 if (G_UNLIKELY(status
== CTF_MSG_ITER_STATUS_AGAIN
)) {
2764 BT_CPPLOGD_SPEC(msg_it
->logger
, "Medium returned CTF_MSG_ITER_STATUS_AGAIN.");
2766 } else if (G_UNLIKELY(status
!= CTF_MSG_ITER_STATUS_OK
)) {
2767 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
2768 "Cannot handle state: msg-it-addr={}, state={}",
2769 fmt::ptr(msg_it
), msg_it
->state
);
2773 switch (msg_it
->state
) {
2774 case STATE_EMIT_MSG_EVENT
:
2775 BT_ASSERT_DBG(msg_it
->event_msg
);
2778 * Check if we need to emit the delayed packet
2779 * beginning message instead of the event message.
2781 if (G_UNLIKELY(msg_it
->emit_delayed_packet_beginning_msg
)) {
2782 *message
= emit_delayed_packet_beg_msg(msg_it
);
2784 status
= CTF_MSG_ITER_STATUS_ERROR
;
2788 * Don't forget to emit the event message of
2789 * the event record that was just decoded.
2791 msg_it
->state
= STATE_EMIT_QUEUED_MSG_EVENT
;
2794 *message
= msg_it
->event_msg
;
2795 msg_it
->event_msg
= NULL
;
2798 case STATE_EMIT_MSG_DISCARDED_EVENTS
:
2799 /* create_msg_discarded_events() logs errors */
2800 *message
= create_msg_discarded_events(msg_it
);
2803 status
= CTF_MSG_ITER_STATUS_ERROR
;
2807 case STATE_EMIT_MSG_DISCARDED_PACKETS
:
2808 /* create_msg_discarded_packets() logs errors */
2809 *message
= create_msg_discarded_packets(msg_it
);
2812 status
= CTF_MSG_ITER_STATUS_ERROR
;
2816 case STATE_EMIT_MSG_PACKET_BEGINNING
:
2817 if (G_UNLIKELY(msg_it
->meta
.tc
->quirks
.barectf_event_before_packet
)) {
2818 msg_it
->emit_delayed_packet_beginning_msg
= true;
2820 * There is no message to return yet as this
2821 * packet beginning message is delayed until we
2822 * decode the first event message of the
2827 /* create_msg_packet_beginning() logs errors */
2828 *message
= create_msg_packet_beginning(msg_it
, false);
2830 status
= CTF_MSG_ITER_STATUS_ERROR
;
2835 case STATE_EMIT_MSG_PACKET_END_SINGLE
:
2836 case STATE_EMIT_MSG_PACKET_END_MULTI
:
2837 /* create_msg_packet_end() logs errors */
2838 *message
= create_msg_packet_end(msg_it
);
2841 status
= CTF_MSG_ITER_STATUS_ERROR
;
2845 case STATE_EMIT_MSG_STREAM_BEGINNING
:
2846 /* create_msg_stream_beginning() logs errors */
2847 *message
= create_msg_stream_beginning(msg_it
);
2848 msg_it
->emit_stream_beginning_message
= false;
2849 msg_it
->emit_stream_end_message
= true;
2852 status
= CTF_MSG_ITER_STATUS_ERROR
;
2856 case STATE_EMIT_MSG_STREAM_END
:
2857 /* create_msg_stream_end() logs errors */
2858 *message
= create_msg_stream_end(msg_it
);
2859 msg_it
->emit_stream_end_message
= false;
2862 status
= CTF_MSG_ITER_STATUS_ERROR
;
2867 status
= CTF_MSG_ITER_STATUS_EOF
;
2870 /* Non-emitting state: continue */
2879 static enum ctf_msg_iter_status
decode_until_state(struct ctf_msg_iter
*msg_it
,
2880 enum state target_state_1
,
2881 enum state target_state_2
)
2883 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
2885 BT_ASSERT_DBG(msg_it
);
2889 * Check if we reached the state at which we want to stop
2892 if (msg_it
->state
== target_state_1
|| msg_it
->state
== target_state_2
) {
2896 status
= handle_state(msg_it
);
2897 if (G_UNLIKELY(status
== CTF_MSG_ITER_STATUS_AGAIN
)) {
2898 BT_CPPLOGD_SPEC(msg_it
->logger
, "Medium returned CTF_MSG_ITER_STATUS_AGAIN.");
2900 } else if (G_UNLIKELY(status
!= CTF_MSG_ITER_STATUS_OK
)) {
2901 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it
->logger
,
2902 "Cannot handle state: msg-it-addr={}, state={}",
2903 fmt::ptr(msg_it
), msg_it
->state
);
2907 switch (msg_it
->state
) {
2909 case STATE_SWITCH_PACKET
:
2910 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
:
2911 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
:
2912 case STATE_AFTER_TRACE_PACKET_HEADER
:
2913 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
:
2914 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
:
2915 case STATE_AFTER_STREAM_PACKET_CONTEXT
:
2916 case STATE_EMIT_MSG_STREAM_BEGINNING
:
2917 case STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS
:
2918 case STATE_EMIT_MSG_DISCARDED_EVENTS
:
2919 case STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS
:
2920 case STATE_EMIT_MSG_DISCARDED_PACKETS
:
2921 case STATE_EMIT_MSG_PACKET_BEGINNING
:
2922 case STATE_DSCOPE_EVENT_HEADER_BEGIN
:
2923 case STATE_DSCOPE_EVENT_HEADER_CONTINUE
:
2924 case STATE_AFTER_EVENT_HEADER
:
2925 case STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN
:
2926 case STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE
:
2927 case STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN
:
2928 case STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE
:
2929 case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
:
2930 case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
:
2931 case STATE_EMIT_MSG_EVENT
:
2932 case STATE_EMIT_QUEUED_MSG_EVENT
:
2933 case STATE_SKIP_PACKET_PADDING
:
2934 case STATE_EMIT_MSG_PACKET_END_MULTI
:
2935 case STATE_EMIT_MSG_PACKET_END_SINGLE
:
2936 case STATE_EMIT_QUEUED_MSG_PACKET_END
:
2937 case STATE_EMIT_MSG_STREAM_END
:
2942 /* We should never get to the STATE_DONE state. */
2943 BT_CPPLOGF_SPEC(msg_it
->logger
, "Unexpected state: msg-it-addr={}, state={}",
2944 fmt::ptr(msg_it
), msg_it
->state
);
2953 static enum ctf_msg_iter_status
read_packet_header_context_fields(struct ctf_msg_iter
*msg_it
)
2956 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
2958 status
= decode_until_state(msg_it
, STATE_EMIT_MSG_PACKET_BEGINNING
, (state
) -1);
2959 if (status
!= CTF_MSG_ITER_STATUS_OK
) {
2963 ret
= set_current_packet_content_sizes(msg_it
);
2965 status
= CTF_MSG_ITER_STATUS_ERROR
;
2973 enum ctf_msg_iter_status
ctf_msg_iter_seek(struct ctf_msg_iter
*msg_it
, off_t offset
)
2975 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
2976 enum ctf_msg_iter_medium_status medium_status
;
2979 BT_ASSERT(offset
>= 0);
2980 BT_ASSERT(msg_it
->medium
.medops
.seek
);
2982 medium_status
= msg_it
->medium
.medops
.seek(offset
, msg_it
->medium
.data
);
2983 if (medium_status
!= CTF_MSG_ITER_MEDIUM_STATUS_OK
) {
2984 if (medium_status
== CTF_MSG_ITER_MEDIUM_STATUS_EOF
) {
2985 status
= CTF_MSG_ITER_STATUS_EOF
;
2987 status
= CTF_MSG_ITER_STATUS_ERROR
;
2992 ctf_msg_iter_reset(msg_it
);
2993 msg_it
->cur_packet_offset
= offset
;
2999 static enum ctf_msg_iter_status
clock_snapshot_at_msg_iter_state(struct ctf_msg_iter
*msg_it
,
3000 enum state target_state_1
,
3001 enum state target_state_2
,
3002 uint64_t *clock_snapshot
)
3004 enum ctf_msg_iter_status status
= CTF_MSG_ITER_STATUS_OK
;
3006 BT_ASSERT_DBG(msg_it
);
3007 BT_ASSERT_DBG(clock_snapshot
);
3008 status
= decode_until_state(msg_it
, target_state_1
, target_state_2
);
3009 if (status
!= CTF_MSG_ITER_STATUS_OK
) {
3013 *clock_snapshot
= msg_it
->default_clock_snapshot
;
3018 enum ctf_msg_iter_status
3019 ctf_msg_iter_curr_packet_first_event_clock_snapshot(struct ctf_msg_iter
*msg_it
,
3020 uint64_t *first_clock_snapshot
)
3022 return clock_snapshot_at_msg_iter_state(msg_it
, STATE_AFTER_EVENT_HEADER
, (state
) -1,
3023 first_clock_snapshot
);
3026 enum ctf_msg_iter_status
3027 ctf_msg_iter_curr_packet_last_event_clock_snapshot(struct ctf_msg_iter
*msg_it
,
3028 uint64_t *last_clock_snapshot
)
3030 return clock_snapshot_at_msg_iter_state(msg_it
, STATE_EMIT_MSG_PACKET_END_SINGLE
,
3031 STATE_EMIT_MSG_PACKET_END_MULTI
, last_clock_snapshot
);
3034 enum ctf_msg_iter_status
3035 ctf_msg_iter_get_packet_properties(struct ctf_msg_iter
*msg_it
,
3036 struct ctf_msg_iter_packet_properties
*props
)
3038 enum ctf_msg_iter_status status
;
3040 BT_ASSERT_DBG(msg_it
);
3041 BT_ASSERT_DBG(props
);
3042 status
= read_packet_header_context_fields(msg_it
);
3043 if (status
!= CTF_MSG_ITER_STATUS_OK
) {
3047 props
->exp_packet_total_size
= msg_it
->cur_exp_packet_total_size
;
3048 props
->exp_packet_content_size
= msg_it
->cur_exp_packet_content_size
;
3049 props
->stream_class_id
= (uint64_t) msg_it
->cur_stream_class_id
;
3050 props
->data_stream_id
= msg_it
->cur_data_stream_id
;
3051 props
->snapshots
.discarded_events
= msg_it
->snapshots
.discarded_events
;
3052 props
->snapshots
.packets
= msg_it
->snapshots
.packets
;
3053 props
->snapshots
.beginning_clock
= msg_it
->snapshots
.beginning_clock
;
3054 props
->snapshots
.end_clock
= msg_it
->snapshots
.end_clock
;
3060 void ctf_msg_iter_set_dry_run(struct ctf_msg_iter
*msg_it
, bool val
)
3062 msg_it
->dry_run
= val
;