2 * Babeltrace - CTF message iterator
4 * Copyright (c) 2015-2018 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2015-2018 Philippe Proulx <pproulx@efficios.com>
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 #define BT_LOG_OUTPUT_LEVEL (notit->log_level)
27 #define BT_LOG_TAG "PLUGIN/CTF/MSG-ITER"
28 #include "logging/log.h"
35 #include "common/assert.h"
37 #include <babeltrace2/babeltrace.h>
38 #include "common/common.h"
43 #include "../bfcr/bfcr.h"
47 /* A visit stack entry */
50 * Current base field, one of:
62 /* Index of next field to set */
70 struct bt_msg_iter
*notit
;
72 /* Entries (struct stack_entry) */
75 /* Number of active entries */
82 STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
,
83 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
,
84 STATE_AFTER_TRACE_PACKET_HEADER
,
85 STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
,
86 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
,
87 STATE_AFTER_STREAM_PACKET_CONTEXT
,
88 STATE_CHECK_EMIT_MSG_STREAM_BEGINNING
,
89 STATE_EMIT_MSG_STREAM_BEGINNING
,
90 STATE_EMIT_MSG_STREAM_ACTIVITY_BEGINNING
,
91 STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS
,
92 STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS
,
93 STATE_EMIT_MSG_DISCARDED_EVENTS
,
94 STATE_EMIT_MSG_DISCARDED_PACKETS
,
95 STATE_EMIT_MSG_PACKET_BEGINNING
,
96 STATE_DSCOPE_EVENT_HEADER_BEGIN
,
97 STATE_DSCOPE_EVENT_HEADER_CONTINUE
,
98 STATE_AFTER_EVENT_HEADER
,
99 STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN
,
100 STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE
,
101 STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN
,
102 STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE
,
103 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
,
104 STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
,
105 STATE_EMIT_MSG_EVENT
,
106 STATE_SKIP_PACKET_PADDING
,
107 STATE_EMIT_MSG_PACKET_END_MULTI
,
108 STATE_EMIT_MSG_PACKET_END_SINGLE
,
109 STATE_CHECK_EMIT_MSG_STREAM_ACTIVITY_END
,
110 STATE_EMIT_MSG_STREAM_ACTIVITY_END
,
111 STATE_EMIT_MSG_STREAM_END
,
115 struct end_of_packet_snapshots
{
116 uint64_t discarded_events
;
118 uint64_t beginning_clock
;
122 /* CTF message iterator */
127 /* Current message iterator to create messages (weak) */
128 bt_self_message_iterator
*msg_iter
;
131 * True to emit stream beginning and stream activity beginning
134 bool emit_stream_begin_msg
;
136 /* True to emit stream end and stream activity end messages */
137 bool emit_stream_end_msg
;
139 /* True to set the stream */
143 * Current dynamic scope field pointer.
145 * This is set by read_dscope_begin_state() and contains the
146 * value of one of the pointers in `dscopes` below.
148 bt_field
*cur_dscope_field
;
151 * True if we're done filling a string field from a text
152 * array/sequence payload.
154 bool done_filling_string
;
156 /* Trace and classes */
157 /* True to set IR fields */
161 struct ctf_trace_class
*tc
;
162 struct ctf_stream_class
*sc
;
163 struct ctf_event_class
*ec
;
166 /* Current packet context field wrapper (NULL if not created yet) */
167 bt_packet_context_field
*packet_context_field
;
169 /* Current packet (NULL if not created yet) */
172 /* Current stream (NULL if not set yet) */
175 /* Current event (NULL if not created yet) */
178 /* Current event message (NULL if not created yet) */
179 bt_message
*event_msg
;
181 /* Database of current dynamic scopes */
183 bt_field
*stream_packet_context
;
184 bt_field
*event_common_context
;
185 bt_field
*event_spec_context
;
186 bt_field
*event_payload
;
192 /* Current medium buffer data */
194 /* Last address provided by medium */
197 /* Buffer size provided by medium (bytes) */
200 /* Offset within whole packet of addr (bits) */
201 size_t packet_offset
;
203 /* Current position from addr (bits) */
206 /* Position of the last event header from addr (bits) */
210 /* Binary type reader */
211 struct bt_bfcr
*bfcr
;
213 /* Current medium data */
215 struct bt_msg_iter_medium_ops medops
;
216 size_t max_request_sz
;
220 /* Current packet size (bits) (-1 if unknown) */
221 int64_t cur_exp_packet_total_size
;
223 /* Current content size (bits) (-1 if unknown) */
224 int64_t cur_exp_packet_content_size
;
226 /* Current stream class ID */
227 int64_t cur_stream_class_id
;
229 /* Current event class ID */
230 int64_t cur_event_class_id
;
232 /* Current data stream ID */
233 int64_t cur_data_stream_id
;
236 * Offset, in the underlying media, of the current packet's
237 * start (-1 if unknown).
239 off_t cur_packet_offset
;
241 /* Default clock's current value */
242 uint64_t default_clock_snapshot
;
244 /* End of current packet snapshots */
245 struct end_of_packet_snapshots snapshots
;
247 /* End of previous packet snapshots */
248 struct end_of_packet_snapshots prev_packet_snapshots
;
250 /* Stored values (for sequence lengths, variant tags) */
251 GArray
*stored_values
;
253 /* Iterator's current log level */
254 bt_logging_level log_level
;
258 const char *state_string(enum state state
)
263 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
:
264 return "STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN";
265 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
:
266 return "STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE";
267 case STATE_AFTER_TRACE_PACKET_HEADER
:
268 return "STATE_AFTER_TRACE_PACKET_HEADER";
269 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
:
270 return "STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN";
271 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
:
272 return "STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE";
273 case STATE_AFTER_STREAM_PACKET_CONTEXT
:
274 return "STATE_AFTER_STREAM_PACKET_CONTEXT";
275 case STATE_EMIT_MSG_STREAM_BEGINNING
:
276 return "STATE_EMIT_MSG_STREAM_BEGINNING";
277 case STATE_EMIT_MSG_STREAM_ACTIVITY_BEGINNING
:
278 return "STATE_EMIT_MSG_STREAM_ACTIVITY_BEGINNING";
279 case STATE_EMIT_MSG_PACKET_BEGINNING
:
280 return "STATE_EMIT_MSG_PACKET_BEGINNING";
281 case STATE_EMIT_MSG_DISCARDED_EVENTS
:
282 return "STATE_EMIT_MSG_DISCARDED_EVENTS";
283 case STATE_EMIT_MSG_DISCARDED_PACKETS
:
284 return "STATE_EMIT_MSG_DISCARDED_PACKETS";
285 case STATE_DSCOPE_EVENT_HEADER_BEGIN
:
286 return "STATE_DSCOPE_EVENT_HEADER_BEGIN";
287 case STATE_DSCOPE_EVENT_HEADER_CONTINUE
:
288 return "STATE_DSCOPE_EVENT_HEADER_CONTINUE";
289 case STATE_AFTER_EVENT_HEADER
:
290 return "STATE_AFTER_EVENT_HEADER";
291 case STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN
:
292 return "STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN";
293 case STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE
:
294 return "STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE";
295 case STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN
:
296 return "STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN";
297 case STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE
:
298 return "STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE";
299 case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
:
300 return "STATE_DSCOPE_EVENT_PAYLOAD_BEGIN";
301 case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
:
302 return "STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE";
303 case STATE_EMIT_MSG_EVENT
:
304 return "STATE_EMIT_MSG_EVENT";
305 case STATE_SKIP_PACKET_PADDING
:
306 return "STATE_SKIP_PACKET_PADDING";
307 case STATE_EMIT_MSG_PACKET_END_MULTI
:
308 return "STATE_EMIT_MSG_PACKET_END_MULTI";
309 case STATE_EMIT_MSG_PACKET_END_SINGLE
:
310 return "STATE_EMIT_MSG_PACKET_END_SINGLE";
311 case STATE_EMIT_MSG_STREAM_ACTIVITY_END
:
312 return "STATE_EMIT_MSG_STREAM_ACTIVITY_END";
313 case STATE_EMIT_MSG_STREAM_END
:
314 return "STATE_EMIT_MSG_STREAM_END";
323 int bt_msg_iter_switch_packet(struct bt_msg_iter
*notit
);
326 struct stack
*stack_new(struct bt_msg_iter
*notit
)
328 struct stack
*stack
= NULL
;
330 stack
= g_new0(struct stack
, 1);
332 BT_LOGE_STR("Failed to allocate one stack.");
336 stack
->notit
= notit
;
337 stack
->entries
= g_array_new(FALSE
, TRUE
, sizeof(struct stack_entry
));
338 if (!stack
->entries
) {
339 BT_LOGE_STR("Failed to allocate a GArray.");
343 BT_LOGD("Created stack: notit-addr=%p, stack-addr=%p", notit
, stack
);
355 void stack_destroy(struct stack
*stack
)
357 struct bt_msg_iter
*notit
;
360 notit
= stack
->notit
;
361 BT_LOGD("Destroying stack: addr=%p", stack
);
363 if (stack
->entries
) {
364 g_array_free(stack
->entries
, TRUE
);
371 void stack_push(struct stack
*stack
, bt_field
*base
)
373 struct stack_entry
*entry
;
374 struct bt_msg_iter
*notit
;
377 notit
= stack
->notit
;
379 BT_LOGV("Pushing base field on stack: stack-addr=%p, "
380 "stack-size-before=%zu, stack-size-after=%zu",
381 stack
, stack
->size
, stack
->size
+ 1);
383 if (stack
->entries
->len
== stack
->size
) {
384 g_array_set_size(stack
->entries
, stack
->size
+ 1);
387 entry
= &g_array_index(stack
->entries
, struct stack_entry
, stack
->size
);
394 unsigned int stack_size(struct stack
*stack
)
401 void stack_pop(struct stack
*stack
)
403 struct bt_msg_iter
*notit
;
406 BT_ASSERT(stack_size(stack
));
407 notit
= stack
->notit
;
408 BT_LOGV("Popping from stack: "
409 "stack-addr=%p, stack-size-before=%zu, stack-size-after=%zu",
410 stack
, stack
->size
, stack
->size
- 1);
415 struct stack_entry
*stack_top(struct stack
*stack
)
418 BT_ASSERT(stack_size(stack
));
419 return &g_array_index(stack
->entries
, struct stack_entry
,
424 bool stack_empty(struct stack
*stack
)
426 return stack_size(stack
) == 0;
430 void stack_clear(struct stack
*stack
)
437 enum bt_msg_iter_status
msg_iter_status_from_m_status(
438 enum bt_msg_iter_medium_status m_status
)
440 /* They are the same */
441 return (int) m_status
;
445 size_t buf_size_bits(struct bt_msg_iter
*notit
)
447 return notit
->buf
.sz
* 8;
451 size_t buf_available_bits(struct bt_msg_iter
*notit
)
453 return buf_size_bits(notit
) - notit
->buf
.at
;
457 size_t packet_at(struct bt_msg_iter
*notit
)
459 return notit
->buf
.packet_offset
+ notit
->buf
.at
;
463 void buf_consume_bits(struct bt_msg_iter
*notit
, size_t incr
)
465 BT_LOGV("Advancing cursor: notit-addr=%p, cur-before=%zu, cur-after=%zu",
466 notit
, notit
->buf
.at
, notit
->buf
.at
+ incr
);
467 notit
->buf
.at
+= incr
;
471 enum bt_msg_iter_status
request_medium_bytes(
472 struct bt_msg_iter
*notit
)
474 uint8_t *buffer_addr
= NULL
;
475 size_t buffer_sz
= 0;
476 enum bt_msg_iter_medium_status m_status
;
478 BT_LOGD("Calling user function (request bytes): notit-addr=%p, "
479 "request-size=%zu", notit
, notit
->medium
.max_request_sz
);
480 m_status
= notit
->medium
.medops
.request_bytes(
481 notit
->medium
.max_request_sz
, &buffer_addr
,
482 &buffer_sz
, notit
->medium
.data
);
483 BT_LOGD("User function returned: status=%s, buf-addr=%p, buf-size=%zu",
484 bt_msg_iter_medium_status_string(m_status
),
485 buffer_addr
, buffer_sz
);
486 if (m_status
== BT_MSG_ITER_MEDIUM_STATUS_OK
) {
487 BT_ASSERT(buffer_sz
!= 0);
489 /* New packet offset is old one + old size (in bits) */
490 notit
->buf
.packet_offset
+= buf_size_bits(notit
);
492 /* Restart at the beginning of the new medium buffer */
494 notit
->buf
.last_eh_at
= SIZE_MAX
;
496 /* New medium buffer size */
497 notit
->buf
.sz
= buffer_sz
;
499 /* New medium buffer address */
500 notit
->buf
.addr
= buffer_addr
;
502 BT_LOGD("User function returned new bytes: "
503 "packet-offset=%zu, cur=%zu, size=%zu, addr=%p",
504 notit
->buf
.packet_offset
, notit
->buf
.at
,
505 notit
->buf
.sz
, notit
->buf
.addr
);
506 BT_LOGD_MEM(buffer_addr
, buffer_sz
, "Returned bytes at %p:",
508 } else if (m_status
== BT_MSG_ITER_MEDIUM_STATUS_EOF
) {
510 * User returned end of stream: validate that we're not
511 * in the middle of a packet header, packet context, or
514 if (notit
->cur_exp_packet_total_size
>= 0) {
515 if (packet_at(notit
) ==
516 notit
->cur_exp_packet_total_size
) {
520 if (packet_at(notit
) == 0) {
524 if (notit
->buf
.last_eh_at
!= SIZE_MAX
&&
525 notit
->buf
.at
== notit
->buf
.last_eh_at
) {
530 /* All other states are invalid */
531 BT_LOGW("User function returned %s, but message iterator is in an unexpected state: "
532 "state=%s, cur-packet-size=%" PRId64
", cur=%zu, "
533 "packet-cur=%zu, last-eh-at=%zu",
534 bt_msg_iter_medium_status_string(m_status
),
535 state_string(notit
->state
),
536 notit
->cur_exp_packet_total_size
,
537 notit
->buf
.at
, packet_at(notit
),
538 notit
->buf
.last_eh_at
);
539 m_status
= BT_MSG_ITER_MEDIUM_STATUS_ERROR
;
540 } else if (m_status
< 0) {
541 BT_LOGW("User function failed: status=%s",
542 bt_msg_iter_medium_status_string(m_status
));
546 return msg_iter_status_from_m_status(m_status
);
550 enum bt_msg_iter_status
buf_ensure_available_bits(
551 struct bt_msg_iter
*notit
)
553 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
555 if (G_UNLIKELY(buf_available_bits(notit
) == 0)) {
557 * This _cannot_ return BT_MSG_ITER_STATUS_OK
560 status
= request_medium_bytes(notit
);
567 enum bt_msg_iter_status
read_dscope_begin_state(
568 struct bt_msg_iter
*notit
,
569 struct ctf_field_class
*dscope_fc
,
570 enum state done_state
, enum state continue_state
,
571 bt_field
*dscope_field
)
573 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
574 enum bt_bfcr_status bfcr_status
;
575 size_t consumed_bits
;
577 notit
->cur_dscope_field
= dscope_field
;
578 BT_LOGV("Starting BFCR: notit-addr=%p, bfcr-addr=%p, fc-addr=%p",
579 notit
, notit
->bfcr
, dscope_fc
);
580 consumed_bits
= bt_bfcr_start(notit
->bfcr
, dscope_fc
,
581 notit
->buf
.addr
, notit
->buf
.at
, packet_at(notit
),
582 notit
->buf
.sz
, &bfcr_status
);
583 BT_LOGV("BFCR consumed bits: size=%zu", consumed_bits
);
585 switch (bfcr_status
) {
586 case BT_BFCR_STATUS_OK
:
587 /* Field class was read completely */
588 BT_LOGV_STR("Field was completely decoded.");
589 notit
->state
= done_state
;
591 case BT_BFCR_STATUS_EOF
:
592 BT_LOGV_STR("BFCR needs more data to decode field completely.");
593 notit
->state
= continue_state
;
596 BT_LOGW("BFCR failed to start: notit-addr=%p, bfcr-addr=%p, "
597 "status=%s", notit
, notit
->bfcr
,
598 bt_bfcr_status_string(bfcr_status
));
599 status
= BT_MSG_ITER_STATUS_ERROR
;
603 /* Consume bits now since we know we're not in an error state */
604 buf_consume_bits(notit
, consumed_bits
);
611 enum bt_msg_iter_status
read_dscope_continue_state(
612 struct bt_msg_iter
*notit
, enum state done_state
)
614 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
615 enum bt_bfcr_status bfcr_status
;
616 size_t consumed_bits
;
618 BT_LOGV("Continuing BFCR: notit-addr=%p, bfcr-addr=%p",
621 status
= buf_ensure_available_bits(notit
);
622 if (status
!= BT_MSG_ITER_STATUS_OK
) {
624 BT_LOGW("Cannot ensure that buffer has at least one byte: "
625 "msg-addr=%p, status=%s",
626 notit
, bt_msg_iter_status_string(status
));
628 BT_LOGV("Cannot ensure that buffer has at least one byte: "
629 "msg-addr=%p, status=%s",
630 notit
, bt_msg_iter_status_string(status
));
636 consumed_bits
= bt_bfcr_continue(notit
->bfcr
, notit
->buf
.addr
,
637 notit
->buf
.sz
, &bfcr_status
);
638 BT_LOGV("BFCR consumed bits: size=%zu", consumed_bits
);
640 switch (bfcr_status
) {
641 case BT_BFCR_STATUS_OK
:
642 /* Type was read completely. */
643 BT_LOGV_STR("Field was completely decoded.");
644 notit
->state
= done_state
;
646 case BT_BFCR_STATUS_EOF
:
647 /* Stay in this continue state. */
648 BT_LOGV_STR("BFCR needs more data to decode field completely.");
651 BT_LOGW("BFCR failed to continue: notit-addr=%p, bfcr-addr=%p, "
652 "status=%s", notit
, notit
->bfcr
,
653 bt_bfcr_status_string(bfcr_status
));
654 status
= BT_MSG_ITER_STATUS_ERROR
;
658 /* Consume bits now since we know we're not in an error state. */
659 buf_consume_bits(notit
, consumed_bits
);
665 void release_event_dscopes(struct bt_msg_iter
*notit
)
667 notit
->dscopes
.event_common_context
= NULL
;
668 notit
->dscopes
.event_spec_context
= NULL
;
669 notit
->dscopes
.event_payload
= NULL
;
673 void release_all_dscopes(struct bt_msg_iter
*notit
)
675 notit
->dscopes
.stream_packet_context
= NULL
;
677 if (notit
->packet_context_field
) {
678 bt_packet_context_field_release(notit
->packet_context_field
);
679 notit
->packet_context_field
= NULL
;
682 release_event_dscopes(notit
);
686 enum bt_msg_iter_status
read_packet_header_begin_state(
687 struct bt_msg_iter
*notit
)
689 struct ctf_field_class
*packet_header_fc
= NULL
;
690 enum bt_msg_iter_status ret
= BT_MSG_ITER_STATUS_OK
;
692 if (bt_msg_iter_switch_packet(notit
)) {
693 BT_LOGW("Cannot switch packet: notit-addr=%p", notit
);
694 ret
= BT_MSG_ITER_STATUS_ERROR
;
699 * Make sure at least one bit is available for this packet. An
700 * empty packet is impossible. If we reach the end of the medium
701 * at this point, then it's considered the end of the stream.
703 ret
= buf_ensure_available_bits(notit
);
705 case BT_MSG_ITER_STATUS_OK
:
707 case BT_MSG_ITER_STATUS_EOF
:
708 ret
= BT_MSG_ITER_STATUS_OK
;
709 notit
->state
= STATE_CHECK_EMIT_MSG_STREAM_ACTIVITY_END
;
715 /* Packet header class is common to the whole trace class. */
716 packet_header_fc
= notit
->meta
.tc
->packet_header_fc
;
717 if (!packet_header_fc
) {
718 notit
->state
= STATE_AFTER_TRACE_PACKET_HEADER
;
722 notit
->cur_stream_class_id
= -1;
723 notit
->cur_event_class_id
= -1;
724 notit
->cur_data_stream_id
= -1;
725 BT_LOGD("Decoding packet header field:"
726 "notit-addr=%p, trace-class-addr=%p, fc-addr=%p",
727 notit
, notit
->meta
.tc
, packet_header_fc
);
728 ret
= read_dscope_begin_state(notit
, packet_header_fc
,
729 STATE_AFTER_TRACE_PACKET_HEADER
,
730 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
, NULL
);
732 BT_LOGW("Cannot decode packet header field: "
733 "notit-addr=%p, trace-class-addr=%p, "
735 notit
, notit
->meta
.tc
, packet_header_fc
);
743 enum bt_msg_iter_status
read_packet_header_continue_state(
744 struct bt_msg_iter
*notit
)
746 return read_dscope_continue_state(notit
,
747 STATE_AFTER_TRACE_PACKET_HEADER
);
751 enum bt_msg_iter_status
set_current_stream_class(struct bt_msg_iter
*notit
)
753 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
754 struct ctf_stream_class
*new_stream_class
= NULL
;
756 if (notit
->cur_stream_class_id
== -1) {
758 * No current stream class ID field, therefore only one
761 if (notit
->meta
.tc
->stream_classes
->len
!= 1) {
762 BT_LOGW("Need exactly one stream class since there's "
763 "no stream class ID field: "
764 "notit-addr=%p", notit
);
765 status
= BT_MSG_ITER_STATUS_ERROR
;
769 new_stream_class
= notit
->meta
.tc
->stream_classes
->pdata
[0];
770 notit
->cur_stream_class_id
= new_stream_class
->id
;
773 new_stream_class
= ctf_trace_class_borrow_stream_class_by_id(
774 notit
->meta
.tc
, notit
->cur_stream_class_id
);
775 if (!new_stream_class
) {
776 BT_LOGW("No stream class with ID of stream class ID to use in trace class: "
777 "notit-addr=%p, stream-class-id=%" PRIu64
", "
778 "trace-class-addr=%p",
779 notit
, notit
->cur_stream_class_id
, notit
->meta
.tc
);
780 status
= BT_MSG_ITER_STATUS_ERROR
;
784 if (notit
->meta
.sc
) {
785 if (new_stream_class
!= notit
->meta
.sc
) {
786 BT_LOGW("Two packets refer to two different stream classes within the same packet sequence: "
787 "notit-addr=%p, prev-stream-class-addr=%p, "
788 "prev-stream-class-id=%" PRId64
", "
789 "next-stream-class-addr=%p, "
790 "next-stream-class-id=%" PRId64
", "
792 notit
, notit
->meta
.sc
,
795 new_stream_class
->id
,
797 status
= BT_MSG_ITER_STATUS_ERROR
;
801 notit
->meta
.sc
= new_stream_class
;
804 BT_LOGD("Set current stream class: "
805 "notit-addr=%p, stream-class-addr=%p, "
806 "stream-class-id=%" PRId64
,
807 notit
, notit
->meta
.sc
, notit
->meta
.sc
->id
);
814 enum bt_msg_iter_status
set_current_stream(struct bt_msg_iter
*notit
)
816 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
817 bt_stream
*stream
= NULL
;
819 BT_LOGD("Calling user function (get stream): notit-addr=%p, "
820 "stream-class-addr=%p, stream-class-id=%" PRId64
,
821 notit
, notit
->meta
.sc
,
823 stream
= notit
->medium
.medops
.borrow_stream(
824 notit
->meta
.sc
->ir_sc
, notit
->cur_data_stream_id
,
826 bt_stream_get_ref(stream
);
827 BT_LOGD("User function returned: stream-addr=%p", stream
);
829 BT_LOGW_STR("User function failed to return a stream object "
830 "for the given stream class.");
831 status
= BT_MSG_ITER_STATUS_ERROR
;
835 if (notit
->stream
&& stream
!= notit
->stream
) {
836 BT_LOGW("User function returned a different stream than the "
837 "previous one for the same sequence of packets.");
838 status
= BT_MSG_ITER_STATUS_ERROR
;
842 BT_STREAM_MOVE_REF(notit
->stream
, stream
);
845 bt_stream_put_ref(stream
);
850 enum bt_msg_iter_status
set_current_packet(struct bt_msg_iter
*notit
)
852 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
853 bt_packet
*packet
= NULL
;
855 BT_LOGD("Creating packet for packet message: "
856 "notit-addr=%p", notit
);
857 BT_LOGD("Creating packet from stream: "
858 "notit-addr=%p, stream-addr=%p, "
859 "stream-class-addr=%p, "
860 "stream-class-id=%" PRId64
,
861 notit
, notit
->stream
, notit
->meta
.sc
,
865 BT_ASSERT(notit
->stream
);
866 packet
= bt_packet_create(notit
->stream
);
868 BT_LOGE("Cannot create packet from stream: "
869 "notit-addr=%p, stream-addr=%p, "
870 "stream-class-addr=%p, "
871 "stream-class-id=%" PRId64
,
872 notit
, notit
->stream
, notit
->meta
.sc
,
880 BT_PACKET_PUT_REF_AND_RESET(packet
);
881 status
= BT_MSG_ITER_STATUS_ERROR
;
884 BT_PACKET_MOVE_REF(notit
->packet
, packet
);
889 enum bt_msg_iter_status
after_packet_header_state(
890 struct bt_msg_iter
*notit
)
892 enum bt_msg_iter_status status
;
894 status
= set_current_stream_class(notit
);
895 if (status
!= BT_MSG_ITER_STATUS_OK
) {
899 notit
->state
= STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
;
906 enum bt_msg_iter_status
read_packet_context_begin_state(
907 struct bt_msg_iter
*notit
)
909 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
910 struct ctf_field_class
*packet_context_fc
;
912 BT_ASSERT(notit
->meta
.sc
);
913 packet_context_fc
= notit
->meta
.sc
->packet_context_fc
;
914 if (!packet_context_fc
) {
915 BT_LOGD("No packet packet context field class in stream class: continuing: "
916 "notit-addr=%p, stream-class-addr=%p, "
917 "stream-class-id=%" PRId64
,
918 notit
, notit
->meta
.sc
,
920 notit
->state
= STATE_AFTER_STREAM_PACKET_CONTEXT
;
924 BT_ASSERT(!notit
->packet_context_field
);
926 if (packet_context_fc
->in_ir
) {
928 * Create free packet context field from stream class.
929 * This field is going to be moved to the packet once we
930 * create it. We cannot create the packet now because a
931 * packet is created from a stream, and this API must be
932 * able to return the packet context properties without
934 * (bt_msg_iter_get_packet_properties()).
936 notit
->packet_context_field
=
937 bt_packet_context_field_create(
938 notit
->meta
.sc
->ir_sc
);
939 if (!notit
->packet_context_field
) {
940 BT_LOGE_STR("Cannot create packet context field wrapper from stream class.");
941 status
= BT_MSG_ITER_STATUS_ERROR
;
945 notit
->dscopes
.stream_packet_context
=
946 bt_packet_context_field_borrow_field(
947 notit
->packet_context_field
);
948 BT_ASSERT(notit
->dscopes
.stream_packet_context
);
951 BT_LOGD("Decoding packet context field: "
952 "notit-addr=%p, stream-class-addr=%p, "
953 "stream-class-id=%" PRId64
", fc-addr=%p",
954 notit
, notit
->meta
.sc
,
955 notit
->meta
.sc
->id
, packet_context_fc
);
956 status
= read_dscope_begin_state(notit
, packet_context_fc
,
957 STATE_AFTER_STREAM_PACKET_CONTEXT
,
958 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
,
959 notit
->dscopes
.stream_packet_context
);
961 BT_LOGW("Cannot decode packet context field: "
962 "notit-addr=%p, stream-class-addr=%p, "
963 "stream-class-id=%" PRId64
", fc-addr=%p",
964 notit
, notit
->meta
.sc
,
974 enum bt_msg_iter_status
read_packet_context_continue_state(
975 struct bt_msg_iter
*notit
)
977 return read_dscope_continue_state(notit
,
978 STATE_AFTER_STREAM_PACKET_CONTEXT
);
982 enum bt_msg_iter_status
set_current_packet_content_sizes(
983 struct bt_msg_iter
*notit
)
985 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
987 if (notit
->cur_exp_packet_total_size
== -1) {
988 if (notit
->cur_exp_packet_content_size
!= -1) {
989 notit
->cur_exp_packet_total_size
=
990 notit
->cur_exp_packet_content_size
;
993 if (notit
->cur_exp_packet_content_size
== -1) {
994 notit
->cur_exp_packet_content_size
=
995 notit
->cur_exp_packet_total_size
;
999 BT_ASSERT((notit
->cur_exp_packet_total_size
>= 0 &&
1000 notit
->cur_exp_packet_content_size
>= 0) ||
1001 (notit
->cur_exp_packet_total_size
< 0 &&
1002 notit
->cur_exp_packet_content_size
< 0));
1004 if (notit
->cur_exp_packet_content_size
>
1005 notit
->cur_exp_packet_total_size
) {
1006 BT_LOGW("Invalid packet or content size: "
1007 "content size is greater than packet size: "
1008 "notit-addr=%p, packet-context-field-addr=%p, "
1009 "packet-size=%" PRId64
", content-size=%" PRId64
,
1010 notit
, notit
->dscopes
.stream_packet_context
,
1011 notit
->cur_exp_packet_total_size
,
1012 notit
->cur_exp_packet_content_size
);
1013 status
= BT_MSG_ITER_STATUS_ERROR
;
1017 BT_LOGD("Set current packet and content sizes: "
1018 "notit-addr=%p, packet-size=%" PRIu64
", content-size=%" PRIu64
,
1019 notit
, notit
->cur_exp_packet_total_size
,
1020 notit
->cur_exp_packet_content_size
);
1027 enum bt_msg_iter_status
after_packet_context_state(struct bt_msg_iter
*notit
)
1029 enum bt_msg_iter_status status
;
1031 status
= set_current_packet_content_sizes(notit
);
1032 if (status
!= BT_MSG_ITER_STATUS_OK
) {
1036 if (notit
->stream
) {
1038 * Stream exists, which means we already emitted at
1039 * least one packet beginning message, so the initial
1040 * stream beginning message was also emitted.
1042 notit
->state
= STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS
;
1044 notit
->state
= STATE_CHECK_EMIT_MSG_STREAM_BEGINNING
;
1052 enum bt_msg_iter_status
read_event_header_begin_state(struct bt_msg_iter
*notit
)
1054 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
1055 struct ctf_field_class
*event_header_fc
= NULL
;
1057 /* Reset the position of the last event header */
1058 notit
->buf
.last_eh_at
= notit
->buf
.at
;
1059 notit
->cur_event_class_id
= -1;
1061 /* Check if we have some content left */
1062 if (notit
->cur_exp_packet_content_size
>= 0) {
1063 if (G_UNLIKELY(packet_at(notit
) ==
1064 notit
->cur_exp_packet_content_size
)) {
1065 /* No more events! */
1066 BT_LOGD("Reached end of packet: notit-addr=%p, "
1067 "cur=%zu", notit
, packet_at(notit
));
1068 notit
->state
= STATE_EMIT_MSG_PACKET_END_MULTI
;
1070 } else if (G_UNLIKELY(packet_at(notit
) >
1071 notit
->cur_exp_packet_content_size
)) {
1072 /* That's not supposed to happen */
1073 BT_LOGD("Before decoding event header field: cursor is passed the packet's content: "
1074 "notit-addr=%p, content-size=%" PRId64
", "
1076 notit
->cur_exp_packet_content_size
,
1078 status
= BT_MSG_ITER_STATUS_ERROR
;
1083 * "Infinite" content: we're done when the medium has
1084 * nothing else for us.
1086 status
= buf_ensure_available_bits(notit
);
1088 case BT_MSG_ITER_STATUS_OK
:
1090 case BT_MSG_ITER_STATUS_EOF
:
1091 status
= BT_MSG_ITER_STATUS_OK
;
1092 notit
->state
= STATE_EMIT_MSG_PACKET_END_SINGLE
;
1099 release_event_dscopes(notit
);
1100 BT_ASSERT(notit
->meta
.sc
);
1101 event_header_fc
= notit
->meta
.sc
->event_header_fc
;
1102 if (!event_header_fc
) {
1103 notit
->state
= STATE_AFTER_EVENT_HEADER
;
1107 BT_LOGD("Decoding event header field: "
1108 "notit-addr=%p, stream-class-addr=%p, "
1109 "stream-class-id=%" PRId64
", "
1111 notit
, notit
->meta
.sc
,
1114 status
= read_dscope_begin_state(notit
, event_header_fc
,
1115 STATE_AFTER_EVENT_HEADER
,
1116 STATE_DSCOPE_EVENT_HEADER_CONTINUE
, NULL
);
1118 BT_LOGW("Cannot decode event header field: "
1119 "notit-addr=%p, stream-class-addr=%p, "
1120 "stream-class-id=%" PRId64
", fc-addr=%p",
1121 notit
, notit
->meta
.sc
,
1131 enum bt_msg_iter_status
read_event_header_continue_state(
1132 struct bt_msg_iter
*notit
)
1134 return read_dscope_continue_state(notit
,
1135 STATE_AFTER_EVENT_HEADER
);
1139 enum bt_msg_iter_status
set_current_event_class(struct bt_msg_iter
*notit
)
1141 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
1143 struct ctf_event_class
*new_event_class
= NULL
;
1145 if (notit
->cur_event_class_id
== -1) {
1147 * No current event class ID field, therefore only one
1150 if (notit
->meta
.sc
->event_classes
->len
!= 1) {
1151 BT_LOGW("Need exactly one event class since there's "
1152 "no event class ID field: "
1153 "notit-addr=%p", notit
);
1154 status
= BT_MSG_ITER_STATUS_ERROR
;
1158 new_event_class
= notit
->meta
.sc
->event_classes
->pdata
[0];
1159 notit
->cur_event_class_id
= new_event_class
->id
;
1162 new_event_class
= ctf_stream_class_borrow_event_class_by_id(
1163 notit
->meta
.sc
, notit
->cur_event_class_id
);
1164 if (!new_event_class
) {
1165 BT_LOGW("No event class with ID of event class ID to use in stream class: "
1166 "notit-addr=%p, stream-class-id=%" PRIu64
", "
1167 "event-class-id=%" PRIu64
", "
1168 "trace-class-addr=%p",
1169 notit
, notit
->meta
.sc
->id
, notit
->cur_event_class_id
,
1171 status
= BT_MSG_ITER_STATUS_ERROR
;
1175 notit
->meta
.ec
= new_event_class
;
1176 BT_LOGD("Set current event class: "
1177 "notit-addr=%p, event-class-addr=%p, "
1178 "event-class-id=%" PRId64
", "
1179 "event-class-name=\"%s\"",
1180 notit
, notit
->meta
.ec
, notit
->meta
.ec
->id
,
1181 notit
->meta
.ec
->name
->str
);
1188 enum bt_msg_iter_status
set_current_event_message(
1189 struct bt_msg_iter
*notit
)
1191 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
1192 bt_message
*msg
= NULL
;
1194 BT_ASSERT(notit
->meta
.ec
);
1195 BT_ASSERT(notit
->packet
);
1196 BT_LOGD("Creating event message from event class and packet: "
1197 "notit-addr=%p, ec-addr=%p, ec-name=\"%s\", packet-addr=%p",
1198 notit
, notit
->meta
.ec
,
1199 notit
->meta
.ec
->name
->str
,
1201 BT_ASSERT(notit
->msg_iter
);
1202 BT_ASSERT(notit
->meta
.sc
);
1204 if (bt_stream_class_borrow_default_clock_class(notit
->meta
.sc
->ir_sc
)) {
1205 msg
= bt_message_event_create_with_default_clock_snapshot(
1206 notit
->msg_iter
, notit
->meta
.ec
->ir_ec
,
1207 notit
->packet
, notit
->default_clock_snapshot
);
1209 msg
= bt_message_event_create(notit
->msg_iter
,
1210 notit
->meta
.ec
->ir_ec
, notit
->packet
);
1214 BT_LOGE("Cannot create event message: "
1215 "notit-addr=%p, ec-addr=%p, ec-name=\"%s\", "
1217 notit
, notit
->meta
.ec
,
1218 notit
->meta
.ec
->name
->str
,
1226 BT_MESSAGE_PUT_REF_AND_RESET(msg
);
1227 status
= BT_MSG_ITER_STATUS_ERROR
;
1230 BT_MESSAGE_MOVE_REF(notit
->event_msg
, msg
);
1235 enum bt_msg_iter_status
after_event_header_state(
1236 struct bt_msg_iter
*notit
)
1238 enum bt_msg_iter_status status
;
1240 status
= set_current_event_class(notit
);
1241 if (status
!= BT_MSG_ITER_STATUS_OK
) {
1245 status
= set_current_event_message(notit
);
1246 if (status
!= BT_MSG_ITER_STATUS_OK
) {
1250 notit
->event
= bt_message_event_borrow_event(
1252 BT_ASSERT(notit
->event
);
1253 notit
->state
= STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN
;
1260 enum bt_msg_iter_status
read_event_common_context_begin_state(
1261 struct bt_msg_iter
*notit
)
1263 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
1264 struct ctf_field_class
*event_common_context_fc
;
1266 event_common_context_fc
= notit
->meta
.sc
->event_common_context_fc
;
1267 if (!event_common_context_fc
) {
1268 notit
->state
= STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN
;
1272 if (event_common_context_fc
->in_ir
) {
1273 BT_ASSERT(!notit
->dscopes
.event_common_context
);
1274 notit
->dscopes
.event_common_context
=
1275 bt_event_borrow_common_context_field(
1277 BT_ASSERT(notit
->dscopes
.event_common_context
);
1280 BT_LOGV("Decoding event common context field: "
1281 "notit-addr=%p, stream-class-addr=%p, "
1282 "stream-class-id=%" PRId64
", "
1284 notit
, notit
->meta
.sc
,
1286 event_common_context_fc
);
1287 status
= read_dscope_begin_state(notit
, event_common_context_fc
,
1288 STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN
,
1289 STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE
,
1290 notit
->dscopes
.event_common_context
);
1292 BT_LOGW("Cannot decode event common context field: "
1293 "notit-addr=%p, stream-class-addr=%p, "
1294 "stream-class-id=%" PRId64
", fc-addr=%p",
1295 notit
, notit
->meta
.sc
,
1297 event_common_context_fc
);
1305 enum bt_msg_iter_status
read_event_common_context_continue_state(
1306 struct bt_msg_iter
*notit
)
1308 return read_dscope_continue_state(notit
,
1309 STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN
);
1313 enum bt_msg_iter_status
read_event_spec_context_begin_state(
1314 struct bt_msg_iter
*notit
)
1316 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
1317 struct ctf_field_class
*event_spec_context_fc
;
1319 event_spec_context_fc
= notit
->meta
.ec
->spec_context_fc
;
1320 if (!event_spec_context_fc
) {
1321 notit
->state
= STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
;
1325 if (event_spec_context_fc
->in_ir
) {
1326 BT_ASSERT(!notit
->dscopes
.event_spec_context
);
1327 notit
->dscopes
.event_spec_context
=
1328 bt_event_borrow_specific_context_field(
1330 BT_ASSERT(notit
->dscopes
.event_spec_context
);
1333 BT_LOGV("Decoding event specific context field: "
1334 "notit-addr=%p, event-class-addr=%p, "
1335 "event-class-name=\"%s\", event-class-id=%" PRId64
", "
1337 notit
, notit
->meta
.ec
,
1338 notit
->meta
.ec
->name
->str
,
1340 event_spec_context_fc
);
1341 status
= read_dscope_begin_state(notit
, event_spec_context_fc
,
1342 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
,
1343 STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE
,
1344 notit
->dscopes
.event_spec_context
);
1346 BT_LOGW("Cannot decode event specific context field: "
1347 "notit-addr=%p, event-class-addr=%p, "
1348 "event-class-name=\"%s\", "
1349 "event-class-id=%" PRId64
", fc-addr=%p",
1350 notit
, notit
->meta
.ec
,
1351 notit
->meta
.ec
->name
->str
,
1353 event_spec_context_fc
);
1361 enum bt_msg_iter_status
read_event_spec_context_continue_state(
1362 struct bt_msg_iter
*notit
)
1364 return read_dscope_continue_state(notit
,
1365 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
);
1369 enum bt_msg_iter_status
read_event_payload_begin_state(
1370 struct bt_msg_iter
*notit
)
1372 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
1373 struct ctf_field_class
*event_payload_fc
;
1375 event_payload_fc
= notit
->meta
.ec
->payload_fc
;
1376 if (!event_payload_fc
) {
1377 notit
->state
= STATE_EMIT_MSG_EVENT
;
1381 if (event_payload_fc
->in_ir
) {
1382 BT_ASSERT(!notit
->dscopes
.event_payload
);
1383 notit
->dscopes
.event_payload
=
1384 bt_event_borrow_payload_field(
1386 BT_ASSERT(notit
->dscopes
.event_payload
);
1389 BT_LOGV("Decoding event payload field: "
1390 "notit-addr=%p, event-class-addr=%p, "
1391 "event-class-name=\"%s\", event-class-id=%" PRId64
", "
1393 notit
, notit
->meta
.ec
,
1394 notit
->meta
.ec
->name
->str
,
1397 status
= read_dscope_begin_state(notit
, event_payload_fc
,
1398 STATE_EMIT_MSG_EVENT
,
1399 STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
,
1400 notit
->dscopes
.event_payload
);
1402 BT_LOGW("Cannot decode event payload field: "
1403 "notit-addr=%p, event-class-addr=%p, "
1404 "event-class-name=\"%s\", "
1405 "event-class-id=%" PRId64
", fc-addr=%p",
1406 notit
, notit
->meta
.ec
,
1407 notit
->meta
.ec
->name
->str
,
1417 enum bt_msg_iter_status
read_event_payload_continue_state(
1418 struct bt_msg_iter
*notit
)
1420 return read_dscope_continue_state(notit
, STATE_EMIT_MSG_EVENT
);
1424 enum bt_msg_iter_status
skip_packet_padding_state(struct bt_msg_iter
*notit
)
1426 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
1427 size_t bits_to_skip
;
1429 BT_ASSERT(notit
->cur_exp_packet_total_size
> 0);
1430 bits_to_skip
= notit
->cur_exp_packet_total_size
- packet_at(notit
);
1431 if (bits_to_skip
== 0) {
1432 notit
->state
= STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
;
1435 size_t bits_to_consume
;
1437 BT_LOGD("Trying to skip %zu bits of padding: notit-addr=%p, size=%zu",
1438 bits_to_skip
, notit
, bits_to_skip
);
1439 status
= buf_ensure_available_bits(notit
);
1440 if (status
!= BT_MSG_ITER_STATUS_OK
) {
1444 bits_to_consume
= MIN(buf_available_bits(notit
), bits_to_skip
);
1445 BT_LOGD("Skipping %zu bits of padding: notit-addr=%p, size=%zu",
1446 bits_to_consume
, notit
, bits_to_consume
);
1447 buf_consume_bits(notit
, bits_to_consume
);
1448 bits_to_skip
= notit
->cur_exp_packet_total_size
-
1450 if (bits_to_skip
== 0) {
1451 notit
->state
= STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
;
1461 enum bt_msg_iter_status
check_emit_msg_stream_beginning_state(
1462 struct bt_msg_iter
*notit
)
1464 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
1466 if (notit
->set_stream
) {
1467 status
= set_current_stream(notit
);
1468 if (status
!= BT_MSG_ITER_STATUS_OK
) {
1473 if (notit
->emit_stream_begin_msg
) {
1474 notit
->state
= STATE_EMIT_MSG_STREAM_BEGINNING
;
1476 /* Stream's first packet */
1477 notit
->state
= STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS
;
1485 enum bt_msg_iter_status
check_emit_msg_discarded_events(
1486 struct bt_msg_iter
*notit
)
1488 notit
->state
= STATE_EMIT_MSG_DISCARDED_EVENTS
;
1490 if (!notit
->meta
.sc
->has_discarded_events
) {
1491 notit
->state
= STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS
;
1495 if (notit
->prev_packet_snapshots
.discarded_events
== UINT64_C(-1)) {
1496 if (notit
->snapshots
.discarded_events
== 0 ||
1497 notit
->snapshots
.discarded_events
== UINT64_C(-1)) {
1499 * Stream's first packet with no discarded
1500 * events or no information about discarded
1501 * events: do not emit.
1503 notit
->state
= STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS
;
1507 * If the previous packet has a value for this counter,
1508 * then this counter is defined for the whole stream.
1510 BT_ASSERT(notit
->snapshots
.discarded_events
!= UINT64_C(-1));
1512 if (notit
->snapshots
.discarded_events
-
1513 notit
->prev_packet_snapshots
.discarded_events
== 0) {
1515 * No discarded events since previous packet: do
1518 notit
->state
= STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS
;
1523 return BT_MSG_ITER_STATUS_OK
;
1527 enum bt_msg_iter_status
check_emit_msg_discarded_packets(
1528 struct bt_msg_iter
*notit
)
1530 notit
->state
= STATE_EMIT_MSG_DISCARDED_PACKETS
;
1532 if (!notit
->meta
.sc
->has_discarded_packets
) {
1533 notit
->state
= STATE_EMIT_MSG_PACKET_BEGINNING
;
1537 if (notit
->prev_packet_snapshots
.packets
== UINT64_C(-1)) {
1539 * Stream's first packet or no information about
1540 * discarded packets: do not emit. In other words, if
1541 * this is the first packet and its sequence number is
1542 * not 0, do not consider that packets were previously
1543 * lost: we might be reading a partial stream (LTTng
1544 * snapshot for example).
1546 notit
->state
= STATE_EMIT_MSG_PACKET_BEGINNING
;
1549 * If the previous packet has a value for this counter,
1550 * then this counter is defined for the whole stream.
1552 BT_ASSERT(notit
->snapshots
.packets
!= UINT64_C(-1));
1554 if (notit
->snapshots
.packets
-
1555 notit
->prev_packet_snapshots
.packets
<= 1) {
1557 * No discarded packets since previous packet:
1560 notit
->state
= STATE_EMIT_MSG_PACKET_BEGINNING
;
1565 return BT_MSG_ITER_STATUS_OK
;
1569 enum bt_msg_iter_status
check_emit_msg_stream_activity_end(
1570 struct bt_msg_iter
*notit
)
1572 if (notit
->emit_stream_end_msg
) {
1573 notit
->state
= STATE_EMIT_MSG_STREAM_ACTIVITY_END
;
1575 notit
->state
= STATE_DONE
;
1578 return BT_MSG_ITER_STATUS_OK
;
1582 enum bt_msg_iter_status
handle_state(struct bt_msg_iter
*notit
)
1584 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
1585 const enum state state
= notit
->state
;
1587 BT_LOGV("Handling state: notit-addr=%p, state=%s",
1588 notit
, state_string(state
));
1590 // TODO: optimalize!
1593 notit
->state
= STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
;
1595 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
:
1596 status
= read_packet_header_begin_state(notit
);
1598 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
:
1599 status
= read_packet_header_continue_state(notit
);
1601 case STATE_AFTER_TRACE_PACKET_HEADER
:
1602 status
= after_packet_header_state(notit
);
1604 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
:
1605 status
= read_packet_context_begin_state(notit
);
1607 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
:
1608 status
= read_packet_context_continue_state(notit
);
1610 case STATE_AFTER_STREAM_PACKET_CONTEXT
:
1611 status
= after_packet_context_state(notit
);
1613 case STATE_CHECK_EMIT_MSG_STREAM_BEGINNING
:
1614 status
= check_emit_msg_stream_beginning_state(notit
);
1616 case STATE_EMIT_MSG_STREAM_BEGINNING
:
1617 notit
->state
= STATE_EMIT_MSG_STREAM_ACTIVITY_BEGINNING
;
1619 case STATE_EMIT_MSG_STREAM_ACTIVITY_BEGINNING
:
1620 notit
->state
= STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS
;
1622 case STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS
:
1623 status
= check_emit_msg_discarded_events(notit
);
1625 case STATE_EMIT_MSG_DISCARDED_EVENTS
:
1626 notit
->state
= STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS
;
1628 case STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS
:
1629 status
= check_emit_msg_discarded_packets(notit
);
1631 case STATE_EMIT_MSG_DISCARDED_PACKETS
:
1632 notit
->state
= STATE_EMIT_MSG_PACKET_BEGINNING
;
1634 case STATE_EMIT_MSG_PACKET_BEGINNING
:
1635 notit
->state
= STATE_DSCOPE_EVENT_HEADER_BEGIN
;
1637 case STATE_DSCOPE_EVENT_HEADER_BEGIN
:
1638 status
= read_event_header_begin_state(notit
);
1640 case STATE_DSCOPE_EVENT_HEADER_CONTINUE
:
1641 status
= read_event_header_continue_state(notit
);
1643 case STATE_AFTER_EVENT_HEADER
:
1644 status
= after_event_header_state(notit
);
1646 case STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN
:
1647 status
= read_event_common_context_begin_state(notit
);
1649 case STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE
:
1650 status
= read_event_common_context_continue_state(notit
);
1652 case STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN
:
1653 status
= read_event_spec_context_begin_state(notit
);
1655 case STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE
:
1656 status
= read_event_spec_context_continue_state(notit
);
1658 case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
:
1659 status
= read_event_payload_begin_state(notit
);
1661 case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
:
1662 status
= read_event_payload_continue_state(notit
);
1664 case STATE_EMIT_MSG_EVENT
:
1665 notit
->state
= STATE_DSCOPE_EVENT_HEADER_BEGIN
;
1667 case STATE_SKIP_PACKET_PADDING
:
1668 status
= skip_packet_padding_state(notit
);
1670 case STATE_EMIT_MSG_PACKET_END_MULTI
:
1671 notit
->state
= STATE_SKIP_PACKET_PADDING
;
1673 case STATE_EMIT_MSG_PACKET_END_SINGLE
:
1674 notit
->state
= STATE_CHECK_EMIT_MSG_STREAM_ACTIVITY_END
;
1676 case STATE_CHECK_EMIT_MSG_STREAM_ACTIVITY_END
:
1677 status
= check_emit_msg_stream_activity_end(notit
);
1679 case STATE_EMIT_MSG_STREAM_ACTIVITY_END
:
1680 notit
->state
= STATE_EMIT_MSG_STREAM_END
;
1682 case STATE_EMIT_MSG_STREAM_END
:
1683 notit
->state
= STATE_DONE
;
1688 BT_LOGF("Unknown CTF plugin message iterator state: "
1689 "notit-addr=%p, state=%d", notit
, notit
->state
);
1693 BT_LOGV("Handled state: notit-addr=%p, status=%s, "
1694 "prev-state=%s, cur-state=%s",
1695 notit
, bt_msg_iter_status_string(status
),
1696 state_string(state
), state_string(notit
->state
));
1701 void bt_msg_iter_reset_for_next_stream_file(struct bt_msg_iter
*notit
)
1704 BT_LOGD("Resetting message iterator: addr=%p", notit
);
1705 stack_clear(notit
->stack
);
1706 notit
->meta
.sc
= NULL
;
1707 notit
->meta
.ec
= NULL
;
1708 BT_PACKET_PUT_REF_AND_RESET(notit
->packet
);
1709 BT_STREAM_PUT_REF_AND_RESET(notit
->stream
);
1710 BT_MESSAGE_PUT_REF_AND_RESET(notit
->event_msg
);
1711 release_all_dscopes(notit
);
1712 notit
->cur_dscope_field
= NULL
;
1714 if (notit
->packet_context_field
) {
1715 bt_packet_context_field_release(notit
->packet_context_field
);
1716 notit
->packet_context_field
= NULL
;
1719 notit
->buf
.addr
= NULL
;
1722 notit
->buf
.last_eh_at
= SIZE_MAX
;
1723 notit
->buf
.packet_offset
= 0;
1724 notit
->state
= STATE_INIT
;
1725 notit
->cur_exp_packet_content_size
= -1;
1726 notit
->cur_exp_packet_total_size
= -1;
1727 notit
->cur_packet_offset
= -1;
1728 notit
->cur_event_class_id
= -1;
1729 notit
->snapshots
.beginning_clock
= UINT64_C(-1);
1730 notit
->snapshots
.end_clock
= UINT64_C(-1);
1734 * Resets the internal state of a CTF message iterator.
1737 void bt_msg_iter_reset(struct bt_msg_iter
*notit
)
1739 bt_msg_iter_reset_for_next_stream_file(notit
);
1740 notit
->cur_stream_class_id
= -1;
1741 notit
->cur_data_stream_id
= -1;
1742 notit
->emit_stream_begin_msg
= true;
1743 notit
->emit_stream_end_msg
= true;
1744 notit
->snapshots
.discarded_events
= UINT64_C(-1);
1745 notit
->snapshots
.packets
= UINT64_C(-1);
1746 notit
->prev_packet_snapshots
.discarded_events
= UINT64_C(-1);
1747 notit
->prev_packet_snapshots
.packets
= UINT64_C(-1);
1748 notit
->prev_packet_snapshots
.beginning_clock
= UINT64_C(-1);
1749 notit
->prev_packet_snapshots
.end_clock
= UINT64_C(-1);
1753 int bt_msg_iter_switch_packet(struct bt_msg_iter
*notit
)
1758 * We don't put the stream class here because we need to make
1759 * sure that all the packets processed by the same message
1760 * iterator refer to the same stream class (the first one).
1764 if (notit
->cur_exp_packet_total_size
!= -1) {
1765 notit
->cur_packet_offset
+= notit
->cur_exp_packet_total_size
;
1768 BT_LOGD("Switching packet: notit-addr=%p, cur=%zu, "
1769 "packet-offset=%" PRId64
, notit
, notit
->buf
.at
,
1770 notit
->cur_packet_offset
);
1771 stack_clear(notit
->stack
);
1772 notit
->meta
.ec
= NULL
;
1773 BT_PACKET_PUT_REF_AND_RESET(notit
->packet
);
1774 BT_MESSAGE_PUT_REF_AND_RESET(notit
->event_msg
);
1775 release_all_dscopes(notit
);
1776 notit
->cur_dscope_field
= NULL
;
1779 * Adjust current buffer so that addr points to the beginning of the new
1782 if (notit
->buf
.addr
) {
1783 size_t consumed_bytes
= (size_t) (notit
->buf
.at
/ CHAR_BIT
);
1785 /* Packets are assumed to start on a byte frontier. */
1786 if (notit
->buf
.at
% CHAR_BIT
) {
1787 BT_LOGW("Cannot switch packet: current position is not a multiple of 8: "
1788 "notit-addr=%p, cur=%zu", notit
, notit
->buf
.at
);
1793 notit
->buf
.addr
+= consumed_bytes
;
1794 notit
->buf
.sz
-= consumed_bytes
;
1796 notit
->buf
.packet_offset
= 0;
1797 BT_LOGD("Adjusted buffer: addr=%p, size=%zu",
1798 notit
->buf
.addr
, notit
->buf
.sz
);
1801 notit
->cur_exp_packet_content_size
= -1;
1802 notit
->cur_exp_packet_total_size
= -1;
1803 notit
->cur_stream_class_id
= -1;
1804 notit
->cur_event_class_id
= -1;
1805 notit
->cur_data_stream_id
= -1;
1806 notit
->prev_packet_snapshots
= notit
->snapshots
;
1807 notit
->snapshots
.discarded_events
= UINT64_C(-1);
1808 notit
->snapshots
.packets
= UINT64_C(-1);
1809 notit
->snapshots
.beginning_clock
= UINT64_C(-1);
1810 notit
->snapshots
.end_clock
= UINT64_C(-1);
1817 bt_field
*borrow_next_field(struct bt_msg_iter
*notit
)
1819 bt_field
*next_field
= NULL
;
1820 bt_field
*base_field
;
1821 const bt_field_class
*base_fc
;
1824 BT_ASSERT(!stack_empty(notit
->stack
));
1825 index
= stack_top(notit
->stack
)->index
;
1826 base_field
= stack_top(notit
->stack
)->base
;
1827 BT_ASSERT(base_field
);
1828 base_fc
= bt_field_borrow_class_const(base_field
);
1831 switch (bt_field_class_get_type(base_fc
)) {
1832 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
1835 bt_field_class_structure_get_member_count(
1836 bt_field_borrow_class_const(
1839 bt_field_structure_borrow_member_field_by_index(
1843 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
1844 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
1845 BT_ASSERT(index
< bt_field_array_get_length(base_field
));
1846 next_field
= bt_field_array_borrow_element_field_by_index(
1849 case BT_FIELD_CLASS_TYPE_VARIANT
:
1850 BT_ASSERT(index
== 0);
1851 next_field
= bt_field_variant_borrow_selected_option_field(
1858 BT_ASSERT(next_field
);
1863 void update_default_clock(struct bt_msg_iter
*notit
, uint64_t new_val
,
1864 uint64_t new_val_size
)
1866 uint64_t new_val_mask
;
1867 uint64_t cur_value_masked
;
1869 BT_ASSERT(new_val_size
> 0);
1872 * Special case for a 64-bit new value, which is the limit
1873 * of a clock value as of this version: overwrite the
1874 * current value directly.
1876 if (new_val_size
== 64) {
1877 notit
->default_clock_snapshot
= new_val
;
1881 new_val_mask
= (1ULL << new_val_size
) - 1;
1882 cur_value_masked
= notit
->default_clock_snapshot
& new_val_mask
;
1884 if (new_val
< cur_value_masked
) {
1886 * It looks like a wrap happened on the number of bits
1887 * of the requested new value. Assume that the clock
1888 * value wrapped only one time.
1890 notit
->default_clock_snapshot
+= new_val_mask
+ 1;
1893 /* Clear the low bits of the current clock value. */
1894 notit
->default_clock_snapshot
&= ~new_val_mask
;
1896 /* Set the low bits of the current clock value. */
1897 notit
->default_clock_snapshot
|= new_val
;
1900 BT_LOGV("Updated default clock's value from integer field's value: "
1901 "value=%" PRIu64
, notit
->default_clock_snapshot
);
1905 enum bt_bfcr_status
bfcr_unsigned_int_cb(uint64_t value
,
1906 struct ctf_field_class
*fc
, void *data
)
1908 struct bt_msg_iter
*notit
= data
;
1909 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
1910 bt_field
*field
= NULL
;
1911 struct ctf_field_class_int
*int_fc
= (void *) fc
;
1913 BT_LOGV("Unsigned integer function called from BFCR: "
1914 "notit-addr=%p, bfcr-addr=%p, fc-addr=%p, "
1915 "fc-type=%d, fc-in-ir=%d, value=%" PRIu64
,
1916 notit
, notit
->bfcr
, fc
, fc
->type
, fc
->in_ir
, value
);
1918 if (G_LIKELY(int_fc
->meaning
== CTF_FIELD_CLASS_MEANING_NONE
)) {
1919 goto update_def_clock
;
1922 switch (int_fc
->meaning
) {
1923 case CTF_FIELD_CLASS_MEANING_EVENT_CLASS_ID
:
1924 notit
->cur_event_class_id
= value
;
1926 case CTF_FIELD_CLASS_MEANING_DATA_STREAM_ID
:
1927 notit
->cur_data_stream_id
= value
;
1929 case CTF_FIELD_CLASS_MEANING_PACKET_BEGINNING_TIME
:
1930 notit
->snapshots
.beginning_clock
= value
;
1932 case CTF_FIELD_CLASS_MEANING_PACKET_END_TIME
:
1933 notit
->snapshots
.end_clock
= value
;
1935 case CTF_FIELD_CLASS_MEANING_STREAM_CLASS_ID
:
1936 notit
->cur_stream_class_id
= value
;
1938 case CTF_FIELD_CLASS_MEANING_MAGIC
:
1939 if (value
!= 0xc1fc1fc1) {
1940 BT_LOGW("Invalid CTF magic number: notit-addr=%p, "
1941 "magic=%" PRIx64
, notit
, value
);
1942 status
= BT_BFCR_STATUS_ERROR
;
1947 case CTF_FIELD_CLASS_MEANING_PACKET_COUNTER_SNAPSHOT
:
1948 notit
->snapshots
.packets
= value
;
1950 case CTF_FIELD_CLASS_MEANING_DISC_EV_REC_COUNTER_SNAPSHOT
:
1951 notit
->snapshots
.discarded_events
= value
;
1953 case CTF_FIELD_CLASS_MEANING_EXP_PACKET_TOTAL_SIZE
:
1954 notit
->cur_exp_packet_total_size
= value
;
1956 case CTF_FIELD_CLASS_MEANING_EXP_PACKET_CONTENT_SIZE
:
1957 notit
->cur_exp_packet_content_size
= value
;
1964 if (G_UNLIKELY(int_fc
->mapped_clock_class
)) {
1965 update_default_clock(notit
, value
, int_fc
->base
.size
);
1968 if (G_UNLIKELY(int_fc
->storing_index
>= 0)) {
1969 g_array_index(notit
->stored_values
, uint64_t,
1970 (uint64_t) int_fc
->storing_index
) = value
;
1973 if (G_UNLIKELY(!fc
->in_ir
)) {
1977 field
= borrow_next_field(notit
);
1979 BT_ASSERT(bt_field_borrow_class_const(field
) == fc
->ir_fc
);
1980 BT_ASSERT(bt_field_get_class_type(field
) ==
1981 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
||
1982 bt_field_get_class_type(field
) ==
1983 BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
);
1984 bt_field_unsigned_integer_set_value(field
, value
);
1985 stack_top(notit
->stack
)->index
++;
1992 enum bt_bfcr_status
bfcr_unsigned_int_char_cb(uint64_t value
,
1993 struct ctf_field_class
*fc
, void *data
)
1996 struct bt_msg_iter
*notit
= data
;
1997 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
1998 bt_field
*string_field
= NULL
;
1999 struct ctf_field_class_int
*int_fc
= (void *) fc
;
2000 char str
[2] = {'\0', '\0'};
2002 BT_LOGV("Unsigned integer character function called from BFCR: "
2003 "notit-addr=%p, bfcr-addr=%p, fc-addr=%p, "
2004 "fc-type=%d, fc-in-ir=%d, value=%" PRIu64
,
2005 notit
, notit
->bfcr
, fc
, fc
->type
, fc
->in_ir
, value
);
2006 BT_ASSERT(int_fc
->meaning
== CTF_FIELD_CLASS_MEANING_NONE
);
2007 BT_ASSERT(!int_fc
->mapped_clock_class
);
2008 BT_ASSERT(int_fc
->storing_index
< 0);
2010 if (G_UNLIKELY(!fc
->in_ir
)) {
2014 if (notit
->done_filling_string
) {
2019 notit
->done_filling_string
= true;
2023 string_field
= stack_top(notit
->stack
)->base
;
2024 BT_ASSERT(bt_field_get_class_type(string_field
) ==
2025 BT_FIELD_CLASS_TYPE_STRING
);
2027 /* Append character */
2028 str
[0] = (char) value
;
2029 ret
= bt_field_string_append_with_length(string_field
, str
, 1);
2031 BT_LOGE("Cannot append character to string field's value: "
2032 "notit-addr=%p, field-addr=%p, ret=%d",
2033 notit
, string_field
, ret
);
2034 status
= BT_BFCR_STATUS_ERROR
;
2043 enum bt_bfcr_status
bfcr_signed_int_cb(int64_t value
,
2044 struct ctf_field_class
*fc
, void *data
)
2046 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
2047 bt_field
*field
= NULL
;
2048 struct bt_msg_iter
*notit
= data
;
2049 struct ctf_field_class_int
*int_fc
= (void *) fc
;
2051 BT_LOGV("Signed integer function called from BFCR: "
2052 "notit-addr=%p, bfcr-addr=%p, fc-addr=%p, "
2053 "fc-type=%d, fc-in-ir=%d, value=%" PRId64
,
2054 notit
, notit
->bfcr
, fc
, fc
->type
, fc
->in_ir
, value
);
2055 BT_ASSERT(int_fc
->meaning
== CTF_FIELD_CLASS_MEANING_NONE
);
2057 if (G_UNLIKELY(int_fc
->storing_index
>= 0)) {
2058 g_array_index(notit
->stored_values
, uint64_t,
2059 (uint64_t) int_fc
->storing_index
) = (uint64_t) value
;
2062 if (G_UNLIKELY(!fc
->in_ir
)) {
2066 field
= borrow_next_field(notit
);
2068 BT_ASSERT(bt_field_borrow_class_const(field
) == fc
->ir_fc
);
2069 BT_ASSERT(bt_field_get_class_type(field
) ==
2070 BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
||
2071 bt_field_get_class_type(field
) ==
2072 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
);
2073 bt_field_signed_integer_set_value(field
, value
);
2074 stack_top(notit
->stack
)->index
++;
2081 enum bt_bfcr_status
bfcr_floating_point_cb(double value
,
2082 struct ctf_field_class
*fc
, void *data
)
2084 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
2085 bt_field
*field
= NULL
;
2086 struct bt_msg_iter
*notit
= data
;
2088 BT_LOGV("Floating point number function called from BFCR: "
2089 "notit-addr=%p, bfcr-addr=%p, fc-addr=%p, "
2090 "fc-type=%d, fc-in-ir=%d, value=%f",
2091 notit
, notit
->bfcr
, fc
, fc
->type
, fc
->in_ir
, value
);
2093 if (G_UNLIKELY(!fc
->in_ir
)) {
2097 field
= borrow_next_field(notit
);
2099 BT_ASSERT(bt_field_borrow_class_const(field
) == fc
->ir_fc
);
2100 BT_ASSERT(bt_field_get_class_type(field
) ==
2101 BT_FIELD_CLASS_TYPE_REAL
);
2102 bt_field_real_set_value(field
, value
);
2103 stack_top(notit
->stack
)->index
++;
2110 enum bt_bfcr_status
bfcr_string_begin_cb(
2111 struct ctf_field_class
*fc
, void *data
)
2113 bt_field
*field
= NULL
;
2114 struct bt_msg_iter
*notit
= data
;
2117 BT_LOGV("String (beginning) function called from BFCR: "
2118 "notit-addr=%p, bfcr-addr=%p, fc-addr=%p, "
2119 "fc-type=%d, fc-in-ir=%d",
2120 notit
, notit
->bfcr
, fc
, fc
->type
, fc
->in_ir
);
2122 if (G_UNLIKELY(!fc
->in_ir
)) {
2126 field
= borrow_next_field(notit
);
2128 BT_ASSERT(bt_field_borrow_class_const(field
) == fc
->ir_fc
);
2129 BT_ASSERT(bt_field_get_class_type(field
) ==
2130 BT_FIELD_CLASS_TYPE_STRING
);
2131 ret
= bt_field_string_clear(field
);
2132 BT_ASSERT(ret
== 0);
2135 * Push on stack. Not a compound class per se, but we know that
2136 * only bfcr_string_cb() may be called between this call and a
2137 * subsequent call to bfcr_string_end_cb().
2139 stack_push(notit
->stack
, field
);
2142 return BT_BFCR_STATUS_OK
;
2146 enum bt_bfcr_status
bfcr_string_cb(const char *value
,
2147 size_t len
, struct ctf_field_class
*fc
, void *data
)
2149 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
2150 bt_field
*field
= NULL
;
2151 struct bt_msg_iter
*notit
= data
;
2154 BT_LOGV("String (substring) function called from BFCR: "
2155 "notit-addr=%p, bfcr-addr=%p, fc-addr=%p, "
2156 "fc-type=%d, fc-in-ir=%d, string-length=%zu",
2157 notit
, notit
->bfcr
, fc
, fc
->type
, fc
->in_ir
,
2160 if (G_UNLIKELY(!fc
->in_ir
)) {
2164 field
= stack_top(notit
->stack
)->base
;
2167 /* Append current substring */
2168 ret
= bt_field_string_append_with_length(field
, value
, len
);
2170 BT_LOGE("Cannot append substring to string field's value: "
2171 "notit-addr=%p, field-addr=%p, string-length=%zu, "
2172 "ret=%d", notit
, field
, len
, ret
);
2173 status
= BT_BFCR_STATUS_ERROR
;
2182 enum bt_bfcr_status
bfcr_string_end_cb(
2183 struct ctf_field_class
*fc
, void *data
)
2185 struct bt_msg_iter
*notit
= data
;
2187 BT_LOGV("String (end) function called from BFCR: "
2188 "notit-addr=%p, bfcr-addr=%p, fc-addr=%p, "
2189 "fc-type=%d, fc-in-ir=%d",
2190 notit
, notit
->bfcr
, fc
, fc
->type
, fc
->in_ir
);
2192 if (G_UNLIKELY(!fc
->in_ir
)) {
2196 /* Pop string field */
2197 stack_pop(notit
->stack
);
2199 /* Go to next field */
2200 stack_top(notit
->stack
)->index
++;
2203 return BT_BFCR_STATUS_OK
;
2206 enum bt_bfcr_status
bfcr_compound_begin_cb(
2207 struct ctf_field_class
*fc
, void *data
)
2209 struct bt_msg_iter
*notit
= data
;
2212 BT_LOGV("Compound (beginning) function called from BFCR: "
2213 "notit-addr=%p, bfcr-addr=%p, fc-addr=%p, "
2214 "fc-type=%d, fc-in-ir=%d",
2215 notit
, notit
->bfcr
, fc
, fc
->type
, fc
->in_ir
);
2222 if (stack_empty(notit
->stack
)) {
2223 /* Root: already set by read_dscope_begin_state() */
2224 field
= notit
->cur_dscope_field
;
2226 field
= borrow_next_field(notit
);
2232 BT_ASSERT(bt_field_borrow_class_const(field
) == fc
->ir_fc
);
2233 stack_push(notit
->stack
, field
);
2236 * Change BFCR "unsigned int" callback if it's a text
2239 if (fc
->type
== CTF_FIELD_CLASS_TYPE_ARRAY
||
2240 fc
->type
== CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
2241 struct ctf_field_class_array_base
*array_fc
= (void *) fc
;
2243 if (array_fc
->is_text
) {
2246 BT_ASSERT(bt_field_get_class_type(field
) ==
2247 BT_FIELD_CLASS_TYPE_STRING
);
2248 notit
->done_filling_string
= false;
2249 ret
= bt_field_string_clear(field
);
2250 BT_ASSERT(ret
== 0);
2251 bt_bfcr_set_unsigned_int_cb(notit
->bfcr
,
2252 bfcr_unsigned_int_char_cb
);
2257 return BT_BFCR_STATUS_OK
;
2260 enum bt_bfcr_status
bfcr_compound_end_cb(
2261 struct ctf_field_class
*fc
, void *data
)
2263 struct bt_msg_iter
*notit
= data
;
2265 BT_LOGV("Compound (end) function called from BFCR: "
2266 "notit-addr=%p, bfcr-addr=%p, fc-addr=%p, "
2267 "fc-type=%d, fc-in-ir=%d",
2268 notit
, notit
->bfcr
, fc
, fc
->type
, fc
->in_ir
);
2274 BT_ASSERT(!stack_empty(notit
->stack
));
2275 BT_ASSERT(bt_field_borrow_class_const(stack_top(notit
->stack
)->base
) ==
2279 * Reset BFCR "unsigned int" callback if it's a text
2282 if (fc
->type
== CTF_FIELD_CLASS_TYPE_ARRAY
||
2283 fc
->type
== CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
2284 struct ctf_field_class_array_base
*array_fc
= (void *) fc
;
2286 if (array_fc
->is_text
) {
2287 BT_ASSERT(bt_field_get_class_type(
2288 stack_top(notit
->stack
)->base
) ==
2289 BT_FIELD_CLASS_TYPE_STRING
);
2290 bt_bfcr_set_unsigned_int_cb(notit
->bfcr
,
2291 bfcr_unsigned_int_cb
);
2296 stack_pop(notit
->stack
);
2298 /* If the stack is not empty, increment the base's index */
2299 if (!stack_empty(notit
->stack
)) {
2300 stack_top(notit
->stack
)->index
++;
2304 return BT_BFCR_STATUS_OK
;
2308 int64_t bfcr_get_sequence_length_cb(struct ctf_field_class
*fc
, void *data
)
2310 bt_field
*seq_field
;
2311 struct bt_msg_iter
*notit
= data
;
2312 struct ctf_field_class_sequence
*seq_fc
= (void *) fc
;
2313 int64_t length
= -1;
2316 length
= (uint64_t) g_array_index(notit
->stored_values
, uint64_t,
2317 seq_fc
->stored_length_index
);
2318 seq_field
= stack_top(notit
->stack
)->base
;
2319 BT_ASSERT(seq_field
);
2322 * bfcr_get_sequence_length_cb() also gets called back for a
2323 * text sequence, but the destination field is a string field.
2324 * Only set the field's sequence length if the destination field
2325 * is a sequence field.
2327 if (!seq_fc
->base
.is_text
) {
2328 BT_ASSERT(bt_field_get_class_type(seq_field
) ==
2329 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
);
2330 ret
= bt_field_dynamic_array_set_length(seq_field
,
2333 BT_LOGE("Cannot set dynamic array field's length field: "
2334 "notit-addr=%p, field-addr=%p, "
2335 "length=%" PRIu64
, notit
, seq_field
, length
);
2343 struct ctf_field_class
*bfcr_borrow_variant_selected_field_class_cb(
2344 struct ctf_field_class
*fc
, void *data
)
2348 int64_t option_index
= -1;
2349 struct bt_msg_iter
*notit
= data
;
2350 struct ctf_field_class_variant
*var_fc
= (void *) fc
;
2351 struct ctf_named_field_class
*selected_option
= NULL
;
2352 struct ctf_field_class
*ret_fc
= NULL
;
2358 /* Get variant's tag */
2359 tag
.u
= g_array_index(notit
->stored_values
, uint64_t,
2360 var_fc
->stored_tag_index
);
2363 * Check each range to find the selected option's index.
2365 if (var_fc
->tag_fc
->base
.is_signed
) {
2366 for (i
= 0; i
< var_fc
->ranges
->len
; i
++) {
2367 struct ctf_field_class_variant_range
*range
=
2368 ctf_field_class_variant_borrow_range_by_index(
2371 if (tag
.i
>= range
->range
.lower
.i
&&
2372 tag
.i
<= range
->range
.upper
.i
) {
2373 option_index
= (int64_t) range
->option_index
;
2378 for (i
= 0; i
< var_fc
->ranges
->len
; i
++) {
2379 struct ctf_field_class_variant_range
*range
=
2380 ctf_field_class_variant_borrow_range_by_index(
2383 if (tag
.u
>= range
->range
.lower
.u
&&
2384 tag
.u
<= range
->range
.upper
.u
) {
2385 option_index
= (int64_t) range
->option_index
;
2391 if (option_index
< 0) {
2392 BT_LOGW("Cannot find variant field class's option: "
2393 "notit-addr=%p, var-fc-addr=%p, u-tag=%" PRIu64
", "
2394 "i-tag=%" PRId64
, notit
, var_fc
, tag
.u
, tag
.i
);
2398 selected_option
= ctf_field_class_variant_borrow_option_by_index(
2399 var_fc
, (uint64_t) option_index
);
2401 if (selected_option
->fc
->in_ir
) {
2402 bt_field
*var_field
= stack_top(notit
->stack
)->base
;
2404 ret
= bt_field_variant_select_option_field(
2405 var_field
, option_index
);
2407 BT_LOGW("Cannot select variant field's option field: "
2408 "notit-addr=%p, var-field-addr=%p, "
2409 "opt-index=%" PRId64
, notit
, var_field
,
2415 ret_fc
= selected_option
->fc
;
2422 void create_msg_stream_beginning(struct bt_msg_iter
*notit
,
2423 bt_message
**message
)
2425 bt_message
*ret
= NULL
;
2427 BT_ASSERT(notit
->stream
);
2428 BT_ASSERT(notit
->msg_iter
);
2429 ret
= bt_message_stream_beginning_create(notit
->msg_iter
,
2432 BT_LOGE("Cannot create stream beginning message: "
2433 "notit-addr=%p, stream-addr=%p",
2434 notit
, notit
->stream
);
2442 void create_msg_stream_activity_beginning(struct bt_msg_iter
*notit
,
2443 bt_message
**message
)
2445 bt_message
*ret
= NULL
;
2447 BT_ASSERT(notit
->stream
);
2448 BT_ASSERT(notit
->msg_iter
);
2449 ret
= bt_message_stream_activity_beginning_create(notit
->msg_iter
,
2452 BT_LOGE("Cannot create stream activity beginning message: "
2453 "notit-addr=%p, stream-addr=%p",
2454 notit
, notit
->stream
);
2462 void create_msg_stream_activity_end(struct bt_msg_iter
*notit
,
2463 bt_message
**message
)
2465 bt_message
*ret
= NULL
;
2467 if (!notit
->stream
) {
2468 BT_LOGE("Cannot create stream for stream message: "
2469 "notit-addr=%p", notit
);
2473 BT_ASSERT(notit
->stream
);
2474 BT_ASSERT(notit
->msg_iter
);
2475 ret
= bt_message_stream_activity_end_create(notit
->msg_iter
,
2478 BT_LOGE("Cannot create stream activity end message: "
2479 "notit-addr=%p, stream-addr=%p",
2480 notit
, notit
->stream
);
2488 void create_msg_stream_end(struct bt_msg_iter
*notit
, bt_message
**message
)
2492 if (!notit
->stream
) {
2493 BT_LOGE("Cannot create stream for stream message: "
2494 "notit-addr=%p", notit
);
2498 BT_ASSERT(notit
->msg_iter
);
2499 ret
= bt_message_stream_end_create(notit
->msg_iter
,
2502 BT_LOGE("Cannot create stream end message: "
2503 "notit-addr=%p, stream-addr=%p",
2504 notit
, notit
->stream
);
2512 void create_msg_packet_beginning(struct bt_msg_iter
*notit
,
2513 bt_message
**message
)
2516 enum bt_msg_iter_status status
;
2517 bt_message
*msg
= NULL
;
2518 const bt_stream_class
*sc
;
2520 status
= set_current_packet(notit
);
2521 if (status
!= BT_MSG_ITER_STATUS_OK
) {
2525 BT_ASSERT(notit
->packet
);
2526 sc
= notit
->meta
.sc
->ir_sc
;
2529 if (notit
->packet_context_field
) {
2530 ret
= bt_packet_move_context_field(
2531 notit
->packet
, notit
->packet_context_field
);
2536 notit
->packet_context_field
= NULL
;
2539 * At this point notit->dscopes.stream_packet_context
2540 * has the same value as the packet context field within
2543 BT_ASSERT(bt_packet_borrow_context_field(
2545 notit
->dscopes
.stream_packet_context
);
2548 BT_ASSERT(notit
->msg_iter
);
2550 if (notit
->meta
.sc
->packets_have_ts_begin
) {
2551 BT_ASSERT(notit
->snapshots
.beginning_clock
!= UINT64_C(-1));
2552 msg
= bt_message_packet_beginning_create_with_default_clock_snapshot(
2553 notit
->msg_iter
, notit
->packet
,
2554 notit
->snapshots
.beginning_clock
);
2556 msg
= bt_message_packet_beginning_create(notit
->msg_iter
,
2561 BT_LOGE("Cannot create packet beginning message: "
2562 "notit-addr=%p, packet-addr=%p",
2563 notit
, notit
->packet
);
2574 void create_msg_packet_end(struct bt_msg_iter
*notit
, bt_message
**message
)
2578 if (!notit
->packet
) {
2582 /* Update default clock from packet's end time */
2583 if (notit
->snapshots
.end_clock
!= UINT64_C(-1)) {
2584 notit
->default_clock_snapshot
= notit
->snapshots
.end_clock
;
2587 BT_ASSERT(notit
->msg_iter
);
2589 if (notit
->meta
.sc
->packets_have_ts_end
) {
2590 BT_ASSERT(notit
->snapshots
.end_clock
!= UINT64_C(-1));
2591 msg
= bt_message_packet_end_create_with_default_clock_snapshot(
2592 notit
->msg_iter
, notit
->packet
,
2593 notit
->snapshots
.end_clock
);
2595 msg
= bt_message_packet_end_create(notit
->msg_iter
,
2600 BT_LOGE("Cannot create packet end message: "
2601 "notit-addr=%p, packet-addr=%p",
2602 notit
, notit
->packet
);
2607 BT_PACKET_PUT_REF_AND_RESET(notit
->packet
);
2612 void create_msg_discarded_events(struct bt_msg_iter
*notit
,
2613 bt_message
**message
)
2616 uint64_t beginning_raw_value
= UINT64_C(-1);
2617 uint64_t end_raw_value
= UINT64_C(-1);
2619 BT_ASSERT(notit
->msg_iter
);
2620 BT_ASSERT(notit
->stream
);
2621 BT_ASSERT(notit
->meta
.sc
->has_discarded_events
);
2623 if (notit
->meta
.sc
->discarded_events_have_default_cs
) {
2624 if (notit
->prev_packet_snapshots
.discarded_events
== UINT64_C(-1)) {
2626 * We discarded events, but before (and possibly
2627 * including) the current packet: use this packet's time
2628 * range, and do not have a specific count.
2630 beginning_raw_value
= notit
->snapshots
.beginning_clock
;
2631 end_raw_value
= notit
->snapshots
.end_clock
;
2633 beginning_raw_value
= notit
->prev_packet_snapshots
.end_clock
;
2634 end_raw_value
= notit
->snapshots
.end_clock
;
2637 BT_ASSERT(beginning_raw_value
!= UINT64_C(-1));
2638 BT_ASSERT(end_raw_value
!= UINT64_C(-1));
2639 msg
= bt_message_discarded_events_create_with_default_clock_snapshots(
2640 notit
->msg_iter
, notit
->stream
, beginning_raw_value
,
2643 msg
= bt_message_discarded_events_create(notit
->msg_iter
,
2648 BT_LOGE("Cannot create discarded events message: "
2649 "notit-addr=%p, stream-addr=%p",
2650 notit
, notit
->stream
);
2654 if (notit
->prev_packet_snapshots
.discarded_events
!= UINT64_C(-1)) {
2655 bt_message_discarded_events_set_count(msg
,
2656 notit
->snapshots
.discarded_events
-
2657 notit
->prev_packet_snapshots
.discarded_events
);
2664 void create_msg_discarded_packets(struct bt_msg_iter
*notit
,
2665 bt_message
**message
)
2669 BT_ASSERT(notit
->msg_iter
);
2670 BT_ASSERT(notit
->stream
);
2671 BT_ASSERT(notit
->meta
.sc
->has_discarded_packets
);
2672 BT_ASSERT(notit
->prev_packet_snapshots
.packets
!=
2675 if (notit
->meta
.sc
->discarded_packets_have_default_cs
) {
2676 BT_ASSERT(notit
->prev_packet_snapshots
.end_clock
!= UINT64_C(-1));
2677 BT_ASSERT(notit
->snapshots
.beginning_clock
!= UINT64_C(-1));
2678 msg
= bt_message_discarded_packets_create_with_default_clock_snapshots(
2679 notit
->msg_iter
, notit
->stream
,
2680 notit
->prev_packet_snapshots
.end_clock
,
2681 notit
->snapshots
.beginning_clock
);
2683 msg
= bt_message_discarded_packets_create(notit
->msg_iter
,
2688 BT_LOGE("Cannot create discarded packets message: "
2689 "notit-addr=%p, stream-addr=%p",
2690 notit
, notit
->stream
);
2694 bt_message_discarded_packets_set_count(msg
,
2695 notit
->snapshots
.packets
-
2696 notit
->prev_packet_snapshots
.packets
- 1);
2701 struct bt_msg_iter
*bt_msg_iter_create(struct ctf_trace_class
*tc
,
2702 size_t max_request_sz
,
2703 struct bt_msg_iter_medium_ops medops
, void *data
,
2704 bt_logging_level log_level
)
2706 struct bt_msg_iter
*notit
= NULL
;
2707 struct bt_bfcr_cbs cbs
= {
2709 .signed_int
= bfcr_signed_int_cb
,
2710 .unsigned_int
= bfcr_unsigned_int_cb
,
2711 .floating_point
= bfcr_floating_point_cb
,
2712 .string_begin
= bfcr_string_begin_cb
,
2713 .string
= bfcr_string_cb
,
2714 .string_end
= bfcr_string_end_cb
,
2715 .compound_begin
= bfcr_compound_begin_cb
,
2716 .compound_end
= bfcr_compound_end_cb
,
2719 .get_sequence_length
= bfcr_get_sequence_length_cb
,
2720 .borrow_variant_selected_field_class
= bfcr_borrow_variant_selected_field_class_cb
,
2725 BT_ASSERT(medops
.request_bytes
);
2726 BT_ASSERT(medops
.borrow_stream
);
2727 BT_LOG_WRITE_CUR_LVL(BT_LOG_DEBUG
, log_level
, BT_LOG_TAG
,
2728 "Creating CTF plugin message iterator: "
2729 "trace-addr=%p, max-request-size=%zu, "
2730 "data=%p, log-level=%s", tc
, max_request_sz
, data
,
2731 bt_common_logging_level_string(log_level
));
2732 notit
= g_new0(struct bt_msg_iter
, 1);
2734 BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR
, log_level
, BT_LOG_TAG
,
2735 "Failed to allocate one CTF plugin message iterator.");
2738 notit
->log_level
= log_level
;
2739 notit
->meta
.tc
= tc
;
2740 notit
->medium
.medops
= medops
;
2741 notit
->medium
.max_request_sz
= max_request_sz
;
2742 notit
->medium
.data
= data
;
2743 notit
->stack
= stack_new(notit
);
2744 notit
->stored_values
= g_array_new(FALSE
, TRUE
, sizeof(uint64_t));
2745 g_array_set_size(notit
->stored_values
, tc
->stored_value_count
);
2747 if (!notit
->stack
) {
2748 BT_LOGE_STR("Failed to create field stack.");
2752 notit
->bfcr
= bt_bfcr_create(cbs
, notit
, log_level
);
2754 BT_LOGE_STR("Failed to create binary class reader (BFCR).");
2758 bt_msg_iter_reset(notit
);
2759 BT_LOGD("Created CTF plugin message iterator: "
2760 "trace-addr=%p, max-request-size=%zu, "
2761 "data=%p, notit-addr=%p, log-level=%s",
2762 tc
, max_request_sz
, data
, notit
,
2763 bt_common_logging_level_string(log_level
));
2764 notit
->cur_packet_offset
= 0;
2770 bt_msg_iter_destroy(notit
);
2775 void bt_msg_iter_destroy(struct bt_msg_iter
*notit
)
2777 BT_PACKET_PUT_REF_AND_RESET(notit
->packet
);
2778 BT_STREAM_PUT_REF_AND_RESET(notit
->stream
);
2779 release_all_dscopes(notit
);
2781 BT_LOGD("Destroying CTF plugin message iterator: addr=%p", notit
);
2784 BT_LOGD_STR("Destroying field stack.");
2785 stack_destroy(notit
->stack
);
2789 BT_LOGD("Destroying BFCR: bfcr-addr=%p", notit
->bfcr
);
2790 bt_bfcr_destroy(notit
->bfcr
);
2793 if (notit
->stored_values
) {
2794 g_array_free(notit
->stored_values
, TRUE
);
2800 enum bt_msg_iter_status
bt_msg_iter_get_next_message(
2801 struct bt_msg_iter
*notit
,
2802 bt_self_message_iterator
*msg_iter
, bt_message
**message
)
2804 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
2808 notit
->msg_iter
= msg_iter
;
2809 notit
->set_stream
= true;
2810 BT_LOGD("Getting next message: notit-addr=%p", notit
);
2813 status
= handle_state(notit
);
2814 if (G_UNLIKELY(status
== BT_MSG_ITER_STATUS_AGAIN
)) {
2815 BT_LOGD_STR("Medium returned BT_MSG_ITER_STATUS_AGAIN.");
2817 } else if (G_UNLIKELY(status
!= BT_MSG_ITER_STATUS_OK
)) {
2818 BT_LOGW("Cannot handle state: notit-addr=%p, state=%s",
2819 notit
, state_string(notit
->state
));
2823 switch (notit
->state
) {
2824 case STATE_EMIT_MSG_EVENT
:
2825 BT_ASSERT(notit
->event_msg
);
2826 *message
= notit
->event_msg
;
2827 notit
->event_msg
= NULL
;
2829 case STATE_EMIT_MSG_DISCARDED_EVENTS
:
2830 /* create_msg_discared_events() logs errors */
2831 create_msg_discarded_events(notit
, message
);
2834 status
= BT_MSG_ITER_STATUS_ERROR
;
2838 case STATE_EMIT_MSG_DISCARDED_PACKETS
:
2839 /* create_msg_discared_packets() logs errors */
2840 create_msg_discarded_packets(notit
, message
);
2843 status
= BT_MSG_ITER_STATUS_ERROR
;
2847 case STATE_EMIT_MSG_PACKET_BEGINNING
:
2848 /* create_msg_packet_beginning() logs errors */
2849 create_msg_packet_beginning(notit
, message
);
2852 status
= BT_MSG_ITER_STATUS_ERROR
;
2856 case STATE_EMIT_MSG_PACKET_END_SINGLE
:
2857 case STATE_EMIT_MSG_PACKET_END_MULTI
:
2858 /* create_msg_packet_end() logs errors */
2859 create_msg_packet_end(notit
, message
);
2862 status
= BT_MSG_ITER_STATUS_ERROR
;
2866 case STATE_EMIT_MSG_STREAM_ACTIVITY_BEGINNING
:
2867 /* create_msg_stream_activity_beginning() logs errors */
2868 create_msg_stream_activity_beginning(notit
, message
);
2871 status
= BT_MSG_ITER_STATUS_ERROR
;
2875 case STATE_EMIT_MSG_STREAM_ACTIVITY_END
:
2876 /* create_msg_stream_activity_end() logs errors */
2877 create_msg_stream_activity_end(notit
, message
);
2880 status
= BT_MSG_ITER_STATUS_ERROR
;
2884 case STATE_EMIT_MSG_STREAM_BEGINNING
:
2885 /* create_msg_stream_beginning() logs errors */
2886 create_msg_stream_beginning(notit
, message
);
2889 status
= BT_MSG_ITER_STATUS_ERROR
;
2893 case STATE_EMIT_MSG_STREAM_END
:
2894 /* create_msg_stream_end() logs errors */
2895 create_msg_stream_end(notit
, message
);
2898 status
= BT_MSG_ITER_STATUS_ERROR
;
2903 status
= BT_MSG_ITER_STATUS_EOF
;
2906 /* Non-emitting state: continue */
2916 enum bt_msg_iter_status
read_packet_header_context_fields(
2917 struct bt_msg_iter
*notit
)
2920 enum bt_msg_iter_status status
= BT_MSG_ITER_STATUS_OK
;
2923 notit
->set_stream
= false;
2925 if (notit
->state
== STATE_EMIT_MSG_PACKET_BEGINNING
) {
2926 /* We're already there */
2931 status
= handle_state(notit
);
2932 if (G_UNLIKELY(status
== BT_MSG_ITER_STATUS_AGAIN
)) {
2933 BT_LOGD_STR("Medium returned BT_MSG_ITER_STATUS_AGAIN.");
2935 } else if (G_UNLIKELY(status
!= BT_MSG_ITER_STATUS_OK
)) {
2936 BT_LOGW("Cannot handle state: notit-addr=%p, state=%s",
2937 notit
, state_string(notit
->state
));
2941 switch (notit
->state
) {
2942 case STATE_EMIT_MSG_PACKET_BEGINNING
:
2944 * Packet header and context fields are
2945 * potentially decoded (or they don't exist).
2949 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
:
2950 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
:
2951 case STATE_AFTER_TRACE_PACKET_HEADER
:
2952 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
:
2953 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
:
2954 case STATE_AFTER_STREAM_PACKET_CONTEXT
:
2955 case STATE_CHECK_EMIT_MSG_STREAM_BEGINNING
:
2956 case STATE_EMIT_MSG_STREAM_BEGINNING
:
2957 case STATE_EMIT_MSG_STREAM_ACTIVITY_BEGINNING
:
2958 case STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS
:
2959 case STATE_EMIT_MSG_DISCARDED_EVENTS
:
2960 case STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS
:
2961 case STATE_EMIT_MSG_DISCARDED_PACKETS
:
2962 /* Non-emitting state: continue */
2966 * We should never get past the
2967 * STATE_EMIT_MSG_PACKET_BEGINNING state.
2969 BT_LOGF("Unexpected state: notit-addr=%p, state=%s",
2970 notit
, state_string(notit
->state
));
2976 ret
= set_current_packet_content_sizes(notit
);
2978 status
= BT_MSG_ITER_STATUS_ERROR
;
2985 void bt_msg_iter_set_medops_data(struct bt_msg_iter
*notit
,
2989 notit
->medium
.data
= medops_data
;
2993 enum bt_msg_iter_status
bt_msg_iter_seek(struct bt_msg_iter
*notit
,
2996 enum bt_msg_iter_status ret
= BT_MSG_ITER_STATUS_OK
;
2997 enum bt_msg_iter_medium_status medium_status
;
3001 BT_LOGE("Cannot seek to negative offset: offset=%jd", offset
);
3002 ret
= BT_MSG_ITER_STATUS_INVAL
;
3006 if (!notit
->medium
.medops
.seek
) {
3007 ret
= BT_MSG_ITER_STATUS_UNSUPPORTED
;
3008 BT_LOGD("Aborting seek as the iterator's underlying media does not implement seek support.");
3012 medium_status
= notit
->medium
.medops
.seek(
3013 BT_MSG_ITER_SEEK_WHENCE_SET
, offset
, notit
->medium
.data
);
3014 if (medium_status
!= BT_MSG_ITER_MEDIUM_STATUS_OK
) {
3015 if (medium_status
== BT_MSG_ITER_MEDIUM_STATUS_EOF
) {
3016 ret
= BT_MSG_ITER_STATUS_EOF
;
3018 ret
= BT_MSG_ITER_STATUS_ERROR
;
3023 bt_msg_iter_reset(notit
);
3024 notit
->cur_packet_offset
= offset
;
3031 enum bt_msg_iter_status
bt_msg_iter_get_packet_properties(
3032 struct bt_msg_iter
*notit
,
3033 struct bt_msg_iter_packet_properties
*props
)
3035 enum bt_msg_iter_status status
;
3039 status
= read_packet_header_context_fields(notit
);
3040 if (status
!= BT_MSG_ITER_STATUS_OK
) {
3044 props
->exp_packet_total_size
= notit
->cur_exp_packet_total_size
;
3045 props
->exp_packet_content_size
= notit
->cur_exp_packet_content_size
;
3046 props
->stream_class_id
= (uint64_t) notit
->cur_stream_class_id
;
3047 props
->data_stream_id
= notit
->cur_data_stream_id
;
3048 props
->snapshots
.discarded_events
= notit
->snapshots
.discarded_events
;
3049 props
->snapshots
.packets
= notit
->snapshots
.packets
;
3050 props
->snapshots
.beginning_clock
= notit
->snapshots
.beginning_clock
;
3051 props
->snapshots
.end_clock
= notit
->snapshots
.end_clock
;
3058 void bt_msg_iter_set_emit_stream_beginning_message(struct bt_msg_iter
*notit
,
3061 notit
->emit_stream_begin_msg
= val
;
3065 void bt_msg_iter_set_emit_stream_end_message(struct bt_msg_iter
*notit
,
3068 notit
->emit_stream_end_msg
= val
;