2 * Babeltrace - CTF notification iterator
4 * Copyright (c) 2015-2016 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2015-2016 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_TAG "PLUGIN-CTF-NOTIF-ITER"
34 #include <babeltrace/assert-internal.h>
36 #include <babeltrace/babeltrace.h>
37 #include <babeltrace/common-internal.h>
41 #include "notif-iter.h"
42 #include "../btr/btr.h"
46 /* A visit stack entry */
49 * Current base field, one of:
59 struct bt_field
*base
;
61 /* index of next field to set */
67 /* Entries (struct stack_entry) */
70 /* Number of active entries */
77 STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
,
78 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
,
79 STATE_AFTER_TRACE_PACKET_HEADER
,
80 STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
,
81 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
,
82 STATE_AFTER_STREAM_PACKET_CONTEXT
,
83 STATE_EMIT_NOTIF_NEW_STREAM
,
84 STATE_EMIT_NOTIF_NEW_PACKET
,
85 STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN
,
86 STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE
,
87 STATE_AFTER_STREAM_EVENT_HEADER
,
88 STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN
,
89 STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE
,
90 STATE_DSCOPE_EVENT_CONTEXT_BEGIN
,
91 STATE_DSCOPE_EVENT_CONTEXT_CONTINUE
,
92 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
,
93 STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
,
94 STATE_EMIT_NOTIF_EVENT
,
95 STATE_EMIT_NOTIF_END_OF_PACKET
,
97 STATE_SKIP_PACKET_PADDING
,
100 struct trace_field_path_cache
{
102 * Indexes of the stream_id and stream_instance_id field in the packet
103 * header structure, -1 if unset.
106 int stream_instance_id
;
109 struct stream_class_field_path_cache
{
111 * Indexes of the v and id fields in the stream event header structure,
118 * index of the timestamp_end, packet_size and content_size fields in
119 * the stream packet context structure. Set to -1 if the fields were
127 struct field_cb_override
{
128 enum bt_btr_status (* func
)(void *value
,
129 struct bt_field_type
*type
, void *data
);
133 /* Clock value: clock class and raw value */
135 struct bt_clock_class
*clock_class
; /* Weak */
139 /* CTF notification iterator */
140 struct bt_notif_iter
{
144 /* Current notification iterator to create notifications (weak) */
145 struct bt_private_connection_private_notification_iterator
*notif_iter
;
148 * Current dynamic scope field pointer.
150 * This is set by read_dscope_begin_state() and contains the
151 * value of one of the pointers in `dscopes` below.
153 struct bt_field
*cur_dscope_field
;
155 /* Trace and classes (owned by this) */
157 struct bt_trace
*trace
;
158 struct bt_stream_class
*stream_class
;
159 struct bt_event_class
*event_class
;
162 /* Current packet header field wrapper (NULL if not created yet) */
163 struct bt_packet_header_field
*packet_header_field
;
165 /* Current packet header field wrapper (NULL if not created yet) */
166 struct bt_packet_context_field
*packet_context_field
;
168 /* Current event header field (NULL if not created yet) */
169 struct bt_event_header_field
*event_header_field
;
171 /* Current packet (NULL if not created yet) */
172 struct bt_packet
*packet
;
174 /* Previous packet availability */
175 enum bt_packet_previous_packet_availability prev_packet_avail
;
177 /* Previous packet (NULL if not available) */
178 struct bt_packet
*prev_packet
;
180 /* Current stream (NULL if not set yet) */
181 struct bt_stream
*stream
;
183 /* Current event (NULL if not created yet) */
184 struct bt_event
*event
;
186 /* Current event notification (NULL if not created yet) */
187 struct bt_notification
*event_notif
;
190 * Current `timestamp_end` field (to consider before switching
191 * packets). If it's set, it's a field which is within
192 * `dscopes.stream_packet_context` below, which is in `packet`
195 struct bt_field
*cur_timestamp_end
;
197 /* Database of current dynamic scopes (owned by this) */
199 struct bt_field
*trace_packet_header
;
200 struct bt_field
*stream_packet_context
;
201 struct bt_field
*stream_event_header
;
202 struct bt_field
*stream_event_context
;
203 struct bt_field
*event_context
;
204 struct bt_field
*event_payload
;
208 * Special field overrides.
210 * Overrides are used to implement the behaviours of special fields such
211 * as "timestamp_end" (which must be ignored until the end of the
212 * packet), "id" (event id) which can be present multiple times and must
213 * be updated multiple time.
215 * This should be used to implement the behaviour of integer fields
216 * mapped to clocks and other "tagged" fields (in CTF 2).
218 * bt_field_type to struct field_cb_override
220 GHashTable
*field_overrides
;
225 /* Current medium buffer data */
227 /* Last address provided by medium */
230 /* Buffer size provided by medium (bytes) */
233 /* Offset within whole packet of addr (bits) */
234 size_t packet_offset
;
236 /* Current position from addr (bits) */
239 /* Position of the last event header from addr (bits) */
243 /* Binary type reader */
246 /* Current medium data */
248 struct bt_notif_iter_medium_ops medops
;
249 size_t max_request_sz
;
253 /* Stream beginning was emitted */
254 bool stream_begin_emitted
;
256 /* Current packet size (bits) (-1 if unknown) */
257 int64_t cur_packet_size
;
259 /* Current content size (bits) (-1 if unknown) */
260 int64_t cur_content_size
;
263 * Offset, in the underlying media, of the current packet's start
266 off_t cur_packet_offset
;
268 /* bt_clock_class to uint64_t. */
269 GHashTable
*clock_states
;
272 * Cache of the trace-constant field paths (event header type)
273 * associated to the current trace.
275 struct trace_field_path_cache trace_field_path_cache
;
278 * Field path cache associated with the current stream class.
279 * Ownership of this structure belongs to the field_path_caches HT.
281 struct stream_class_field_path_cache
*cur_sc_field_path_cache
;
283 /* bt_stream_class to struct stream_class_field_path_cache. */
284 GHashTable
*sc_field_path_caches
;
288 const char *state_string(enum state state
)
293 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
:
294 return "STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN";
295 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
:
296 return "STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE";
297 case STATE_AFTER_TRACE_PACKET_HEADER
:
298 return "STATE_AFTER_TRACE_PACKET_HEADER";
299 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
:
300 return "STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN";
301 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
:
302 return "STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE";
303 case STATE_AFTER_STREAM_PACKET_CONTEXT
:
304 return "STATE_AFTER_STREAM_PACKET_CONTEXT";
305 case STATE_EMIT_NOTIF_NEW_PACKET
:
306 return "STATE_EMIT_NOTIF_NEW_PACKET";
307 case STATE_EMIT_NOTIF_NEW_STREAM
:
308 return "STATE_EMIT_NOTIF_NEW_STREAM";
309 case STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN
:
310 return "STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN";
311 case STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE
:
312 return "STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE";
313 case STATE_AFTER_STREAM_EVENT_HEADER
:
314 return "STATE_AFTER_STREAM_EVENT_HEADER";
315 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN
:
316 return "STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN";
317 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE
:
318 return "STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE";
319 case STATE_DSCOPE_EVENT_CONTEXT_BEGIN
:
320 return "STATE_DSCOPE_EVENT_CONTEXT_BEGIN";
321 case STATE_DSCOPE_EVENT_CONTEXT_CONTINUE
:
322 return "STATE_DSCOPE_EVENT_CONTEXT_CONTINUE";
323 case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
:
324 return "STATE_DSCOPE_EVENT_PAYLOAD_BEGIN";
325 case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
:
326 return "STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE";
327 case STATE_EMIT_NOTIF_EVENT
:
328 return "STATE_EMIT_NOTIF_EVENT";
329 case STATE_EMIT_NOTIF_END_OF_PACKET
:
330 return "STATE_EMIT_NOTIF_END_OF_PACKET";
333 case STATE_SKIP_PACKET_PADDING
:
334 return "STATE_SKIP_PACKET_PADDING";
341 int bt_notif_iter_switch_packet(struct bt_notif_iter
*notit
);
344 enum bt_btr_status
btr_timestamp_end_cb(void *value
,
345 struct bt_field_type
*type
, void *data
);
348 struct stack
*stack_new(struct bt_notif_iter
*notit
)
350 struct stack
*stack
= NULL
;
352 stack
= g_new0(struct stack
, 1);
354 BT_LOGE_STR("Failed to allocate one stack.");
358 stack
->entries
= g_array_new(FALSE
, TRUE
, sizeof(struct stack_entry
));
359 if (!stack
->entries
) {
360 BT_LOGE_STR("Failed to allocate a GArray.");
364 BT_LOGD("Created stack: notit-addr=%p, stack-addr=%p", notit
, stack
);
373 void stack_destroy(struct stack
*stack
)
376 BT_LOGD("Destroying stack: addr=%p", stack
);
378 if (stack
->entries
) {
379 g_array_free(stack
->entries
, TRUE
);
386 int stack_push(struct stack
*stack
, struct bt_field
*base
)
388 struct stack_entry
*entry
;
392 BT_LOGV("Pushing base field on stack: stack-addr=%p, "
393 "stack-size-before=%zu, stack-size-after=%zu",
394 stack
, stack
->size
, stack
->size
+ 1);
396 if (stack
->entries
->len
== stack
->size
) {
397 g_array_set_size(stack
->entries
, stack
->size
+ 1);
400 entry
= &g_array_index(stack
->entries
, struct stack_entry
, stack
->size
);
408 unsigned int stack_size(struct stack
*stack
)
415 void stack_pop(struct stack
*stack
)
418 BT_ASSERT(stack_size(stack
));
419 BT_LOGV("Popping from stack: "
420 "stack-addr=%p, stack-size-before=%zu, stack-size-after=%zu",
421 stack
, stack
->size
, stack
->size
- 1);
426 struct stack_entry
*stack_top(struct stack
*stack
)
429 BT_ASSERT(stack_size(stack
));
430 return &g_array_index(stack
->entries
, struct stack_entry
,
435 bool stack_empty(struct stack
*stack
)
437 return stack_size(stack
) == 0;
441 void stack_clear(struct stack
*stack
)
448 enum bt_notif_iter_status
notif_iter_status_from_m_status(
449 enum bt_notif_iter_medium_status m_status
)
451 return (int) m_status
;
455 size_t buf_size_bits(struct bt_notif_iter
*notit
)
457 return notit
->buf
.sz
* 8;
461 size_t buf_available_bits(struct bt_notif_iter
*notit
)
463 return buf_size_bits(notit
) - notit
->buf
.at
;
467 size_t packet_at(struct bt_notif_iter
*notit
)
469 return notit
->buf
.packet_offset
+ notit
->buf
.at
;
473 void buf_consume_bits(struct bt_notif_iter
*notit
, size_t incr
)
475 BT_LOGV("Advancing cursor: notit-addr=%p, cur-before=%zu, cur-after=%zu",
476 notit
, notit
->buf
.at
, notit
->buf
.at
+ incr
);
477 notit
->buf
.at
+= incr
;
481 enum bt_notif_iter_status
request_medium_bytes(
482 struct bt_notif_iter
*notit
)
484 uint8_t *buffer_addr
= NULL
;
485 size_t buffer_sz
= 0;
486 enum bt_notif_iter_medium_status m_status
;
488 BT_LOGV("Calling user function (request bytes): notit-addr=%p, "
489 "request-size=%zu", notit
, notit
->medium
.max_request_sz
);
490 m_status
= notit
->medium
.medops
.request_bytes(
491 notit
->medium
.max_request_sz
, &buffer_addr
,
492 &buffer_sz
, notit
->medium
.data
);
493 BT_LOGV("User function returned: status=%s, buf-addr=%p, buf-size=%zu",
494 bt_notif_iter_medium_status_string(m_status
),
495 buffer_addr
, buffer_sz
);
496 if (m_status
== BT_NOTIF_ITER_MEDIUM_STATUS_OK
) {
497 BT_ASSERT(buffer_sz
!= 0);
499 /* New packet offset is old one + old size (in bits) */
500 notit
->buf
.packet_offset
+= buf_size_bits(notit
);
502 /* Restart at the beginning of the new medium buffer */
504 notit
->buf
.last_eh_at
= SIZE_MAX
;
506 /* New medium buffer size */
507 notit
->buf
.sz
= buffer_sz
;
509 /* New medium buffer address */
510 notit
->buf
.addr
= buffer_addr
;
512 BT_LOGV("User function returned new bytes: "
513 "packet-offset=%zu, cur=%zu, size=%zu, addr=%p",
514 notit
->buf
.packet_offset
, notit
->buf
.at
,
515 notit
->buf
.sz
, notit
->buf
.addr
);
516 BT_LOGV_MEM(buffer_addr
, buffer_sz
, "Returned bytes at %p:",
518 } else if (m_status
== BT_NOTIF_ITER_MEDIUM_STATUS_EOF
) {
520 * User returned end of stream: validate that we're not
521 * in the middle of a packet header, packet context, or
524 if (notit
->cur_packet_size
>= 0) {
525 if (packet_at(notit
) == notit
->cur_packet_size
) {
529 if (packet_at(notit
) == 0) {
533 if (notit
->buf
.last_eh_at
!= SIZE_MAX
&&
534 notit
->buf
.at
== notit
->buf
.last_eh_at
) {
539 /* All other states are invalid */
540 BT_LOGW("User function returned %s, but notification iterator is in an unexpected state: "
541 "state=%s, cur-packet-size=%" PRId64
", cur=%zu, "
542 "packet-cur=%zu, last-eh-at=%zu",
543 bt_notif_iter_medium_status_string(m_status
),
544 state_string(notit
->state
),
545 notit
->cur_packet_size
,
546 notit
->buf
.at
, packet_at(notit
),
547 notit
->buf
.last_eh_at
);
548 m_status
= BT_NOTIF_ITER_MEDIUM_STATUS_ERROR
;
549 } else if (m_status
< 0) {
550 BT_LOGW("User function failed: status=%s",
551 bt_notif_iter_medium_status_string(m_status
));
555 return notif_iter_status_from_m_status(m_status
);
559 enum bt_notif_iter_status
buf_ensure_available_bits(
560 struct bt_notif_iter
*notit
)
562 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
564 if (buf_available_bits(notit
) == 0) {
566 * This _cannot_ return BT_NOTIF_ITER_STATUS_OK
569 status
= request_medium_bytes(notit
);
576 void reset_clock_value(struct clock_value
*cv
)
579 cv
->clock_class
= NULL
;
580 cv
->raw_value
= UINT64_C(-1);
584 enum bt_notif_iter_status
read_dscope_begin_state(
585 struct bt_notif_iter
*notit
,
586 struct bt_field_type
*dscope_field_type
,
587 enum state done_state
, enum state continue_state
,
588 struct bt_field
*dscope_field
)
590 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
591 enum bt_btr_status btr_status
;
592 size_t consumed_bits
;
594 notit
->cur_dscope_field
= dscope_field
;
595 BT_LOGV("Starting BTR: notit-addr=%p, btr-addr=%p, ft-addr=%p",
596 notit
, notit
->btr
, dscope_field_type
);
597 consumed_bits
= bt_btr_start(notit
->btr
, dscope_field_type
,
598 notit
->buf
.addr
, notit
->buf
.at
, packet_at(notit
),
599 notit
->buf
.sz
, &btr_status
);
600 BT_LOGV("BTR consumed bits: size=%zu", consumed_bits
);
602 switch (btr_status
) {
603 case BT_BTR_STATUS_OK
:
604 /* type was read completely */
605 BT_LOGV_STR("Field was completely decoded.");
606 notit
->state
= done_state
;
608 case BT_BTR_STATUS_EOF
:
609 BT_LOGV_STR("BTR needs more data to decode field completely.");
610 notit
->state
= continue_state
;
613 BT_LOGW("BTR failed to start: notit-addr=%p, btr-addr=%p, "
614 "status=%s", notit
, notit
->btr
,
615 bt_btr_status_string(btr_status
));
616 status
= BT_NOTIF_ITER_STATUS_ERROR
;
620 /* Consume bits now since we know we're not in an error state */
621 buf_consume_bits(notit
, consumed_bits
);
628 enum bt_notif_iter_status
read_dscope_continue_state(
629 struct bt_notif_iter
*notit
, enum state done_state
)
631 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
632 enum bt_btr_status btr_status
;
633 size_t consumed_bits
;
635 BT_LOGV("Continuing BTR: notit-addr=%p, btr-addr=%p",
638 status
= buf_ensure_available_bits(notit
);
639 if (status
!= BT_NOTIF_ITER_STATUS_OK
) {
641 BT_LOGW("Cannot ensure that buffer has at least one byte: "
642 "notif-addr=%p, status=%s",
643 notit
, bt_notif_iter_status_string(status
));
645 BT_LOGV("Cannot ensure that buffer has at least one byte: "
646 "notif-addr=%p, status=%s",
647 notit
, bt_notif_iter_status_string(status
));
654 consumed_bits
= bt_btr_continue(notit
->btr
, notit
->buf
.addr
,
655 notit
->buf
.sz
, &btr_status
);
656 BT_LOGV("BTR consumed bits: size=%zu", consumed_bits
);
658 switch (btr_status
) {
659 case BT_BTR_STATUS_OK
:
660 /* Type was read completely. */
661 BT_LOGV_STR("Field was completely decoded.");
662 notit
->state
= done_state
;
664 case BT_BTR_STATUS_EOF
:
665 /* Stay in this continue state. */
666 BT_LOGV_STR("BTR needs more data to decode field completely.");
669 BT_LOGW("BTR failed to continue: notit-addr=%p, btr-addr=%p, "
670 "status=%s", notit
, notit
->btr
,
671 bt_btr_status_string(btr_status
));
672 status
= BT_NOTIF_ITER_STATUS_ERROR
;
676 /* Consume bits now since we know we're not in an error state. */
677 buf_consume_bits(notit
, consumed_bits
);
683 void release_event_dscopes(struct bt_notif_iter
*notit
)
685 notit
->dscopes
.stream_event_header
= NULL
;
687 if (notit
->event_header_field
) {
688 bt_event_header_field_release(notit
->event_header_field
);
689 notit
->event_header_field
= NULL
;
692 notit
->dscopes
.stream_event_context
= NULL
;
693 notit
->dscopes
.event_context
= NULL
;
694 notit
->dscopes
.event_payload
= NULL
;
698 void release_all_dscopes(struct bt_notif_iter
*notit
)
700 notit
->dscopes
.trace_packet_header
= NULL
;
702 if (notit
->packet_header_field
) {
703 bt_packet_header_field_release(notit
->packet_header_field
);
704 notit
->packet_header_field
= NULL
;
707 notit
->dscopes
.stream_packet_context
= NULL
;
709 if (notit
->packet_context_field
) {
710 bt_packet_context_field_release(notit
->packet_context_field
);
711 notit
->packet_context_field
= NULL
;
714 release_event_dscopes(notit
);
718 enum bt_notif_iter_status
read_packet_header_begin_state(
719 struct bt_notif_iter
*notit
)
721 struct bt_field_type
*packet_header_type
= NULL
;
722 enum bt_notif_iter_status ret
= BT_NOTIF_ITER_STATUS_OK
;
724 if (bt_notif_iter_switch_packet(notit
)) {
725 BT_LOGW("Cannot switch packet: notit-addr=%p", notit
);
726 ret
= BT_NOTIF_ITER_STATUS_ERROR
;
730 /* Packet header type is common to the whole trace. */
731 packet_header_type
= bt_trace_borrow_packet_header_field_type(
733 if (!packet_header_type
) {
734 notit
->state
= STATE_AFTER_TRACE_PACKET_HEADER
;
739 * Create free packet header field from trace. This field is
740 * going to be moved to the packet once we create it. We cannot
741 * create the packet now because:
743 * 1. A packet is created from a stream.
744 * 2. A stream is created from a stream class.
745 * 3. We need the packet header field's content to know the ID
746 * of the stream class to select.
748 BT_ASSERT(!notit
->packet_header_field
);
749 notit
->packet_header_field
= bt_trace_create_packet_header_field(
751 if (!notit
->packet_header_field
) {
752 BT_LOGE_STR("Cannot create packet header field wrapper from trace.");
753 ret
= BT_NOTIF_ITER_STATUS_ERROR
;
757 notit
->dscopes
.trace_packet_header
=
758 bt_packet_header_field_borrow_field(notit
->packet_header_field
);
759 BT_ASSERT(notit
->dscopes
.trace_packet_header
);
760 BT_LOGV("Decoding packet header field:"
761 "notit-addr=%p, trace-addr=%p, trace-name=\"%s\", ft-addr=%p",
762 notit
, notit
->meta
.trace
,
763 bt_trace_get_name(notit
->meta
.trace
), packet_header_type
);
764 ret
= read_dscope_begin_state(notit
, packet_header_type
,
765 STATE_AFTER_TRACE_PACKET_HEADER
,
766 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
,
767 notit
->dscopes
.trace_packet_header
);
769 BT_LOGW("Cannot decode packet header field: "
770 "notit-addr=%p, trace-addr=%p, "
771 "trace-name=\"%s\", ft-addr=%p",
772 notit
, notit
->meta
.trace
,
773 bt_trace_get_name(notit
->meta
.trace
),
782 enum bt_notif_iter_status
read_packet_header_continue_state(
783 struct bt_notif_iter
*notit
)
785 return read_dscope_continue_state(notit
,
786 STATE_AFTER_TRACE_PACKET_HEADER
);
790 struct stream_class_field_path_cache
*
791 create_stream_class_field_path_cache_entry(
792 struct bt_notif_iter
*notit
,
793 struct bt_stream_class
*stream_class
)
797 int timestamp_end
= -1;
798 int packet_size
= -1;
799 int content_size
= -1;
800 struct stream_class_field_path_cache
*cache_entry
= g_new0(
801 struct stream_class_field_path_cache
, 1);
802 struct bt_field_type
*event_header
= NULL
, *packet_context
= NULL
;
805 BT_LOGE_STR("Failed to allocate one stream class field path cache.");
809 event_header
= bt_stream_class_borrow_event_header_field_type(
811 if (event_header
&& bt_field_type_is_structure(event_header
)) {
814 count
= bt_field_type_structure_get_field_count(
816 BT_ASSERT(count
>= 0);
818 for (i
= 0; i
< count
; i
++) {
822 ret
= bt_field_type_structure_borrow_field_by_index(
823 event_header
, &name
, NULL
, i
);
825 BT_LOGE("Cannot get event header structure field type's field: "
826 "notit-addr=%p, stream-class-addr=%p, "
827 "stream-class-name=\"%s\", "
828 "stream-class-id=%" PRId64
", "
829 "ft-addr=%p, index=%d",
831 bt_stream_class_get_name(stream_class
),
832 bt_stream_class_get_id(stream_class
),
837 if (v
!= -1 && id
!= -1) {
841 if (v
== -1 && strcmp(name
, "v") == 0) {
843 } else if (id
== -1 && !strcmp(name
, "id")) {
849 packet_context
= bt_stream_class_borrow_packet_context_field_type(
851 if (packet_context
&& bt_field_type_is_structure(packet_context
)) {
854 count
= bt_field_type_structure_get_field_count(
856 BT_ASSERT(count
>= 0);
858 for (i
= 0; i
< count
; i
++) {
861 struct bt_field_type
*field_type
;
863 if (timestamp_end
!= -1 && packet_size
!= -1 &&
864 content_size
!= -1) {
868 ret
= bt_field_type_structure_borrow_field_by_index(
869 packet_context
, &name
, &field_type
, i
);
871 BT_LOGE("Cannot get packet context structure field type's field: "
872 "notit-addr=%p, stream-class-addr=%p, "
873 "stream-class-name=\"%s\", "
874 "stream-class-id=%" PRId64
", "
875 "ft-addr=%p, index=%d",
877 bt_stream_class_get_name(stream_class
),
878 bt_stream_class_get_id(stream_class
),
883 if (timestamp_end
== -1 &&
884 strcmp(name
, "timestamp_end") == 0) {
885 struct field_cb_override
*override
= g_new0(
886 struct field_cb_override
, 1);
892 override
->func
= btr_timestamp_end_cb
;
893 override
->data
= notit
;
894 g_hash_table_insert(notit
->field_overrides
,
895 field_type
, override
);
897 } else if (packet_size
== -1 &&
898 !strcmp(name
, "packet_size")) {
900 } else if (content_size
== -1 &&
901 !strcmp(name
, "content_size")) {
908 cache_entry
->id
= id
;
909 cache_entry
->timestamp_end
= timestamp_end
;
910 cache_entry
->packet_size
= packet_size
;
911 cache_entry
->content_size
= content_size
;
923 struct stream_class_field_path_cache
*get_stream_class_field_path_cache(
924 struct bt_notif_iter
*notit
,
925 struct bt_stream_class
*stream_class
)
927 bool cache_entry_found
;
928 struct stream_class_field_path_cache
*cache_entry
;
930 cache_entry_found
= g_hash_table_lookup_extended(
931 notit
->sc_field_path_caches
,
932 stream_class
, NULL
, (gpointer
) &cache_entry
);
933 if (unlikely(!cache_entry_found
)) {
934 cache_entry
= create_stream_class_field_path_cache_entry(notit
,
936 g_hash_table_insert(notit
->sc_field_path_caches
,
937 stream_class
, (gpointer
) cache_entry
);
944 enum bt_notif_iter_status
set_current_stream_class(
945 struct bt_notif_iter
*notit
)
947 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
948 struct bt_field_type
*packet_header_type
= NULL
;
949 struct bt_field_type
*stream_id_field_type
= NULL
;
950 struct bt_stream_class
*new_stream_class
= NULL
;
953 /* Clear the current stream class field path cache. */
954 notit
->cur_sc_field_path_cache
= NULL
;
956 /* Is there any "stream_id" field in the packet header? */
957 packet_header_type
= bt_trace_borrow_packet_header_field_type(
959 if (!packet_header_type
) {
961 * No packet header, therefore no `stream_id` field,
962 * therefore only one stream class.
964 goto single_stream_class
;
967 BT_ASSERT(bt_field_type_is_structure(packet_header_type
));
970 stream_id_field_type
=
971 bt_field_type_structure_borrow_field_type_by_name(
972 packet_header_type
, "stream_id");
973 if (stream_id_field_type
) {
974 /* Find appropriate stream class using current stream ID */
976 struct bt_field
*stream_id_field
= NULL
;
978 BT_ASSERT(notit
->dscopes
.trace_packet_header
);
981 stream_id_field
= bt_field_structure_borrow_field_by_name(
982 notit
->dscopes
.trace_packet_header
, "stream_id");
983 BT_ASSERT(stream_id_field
);
984 ret
= bt_field_integer_unsigned_get_value(
985 stream_id_field
, &stream_id
);
989 /* Only one stream: pick the first stream class */
990 BT_ASSERT(bt_trace_get_stream_class_count(
991 notit
->meta
.trace
) == 1);
995 BT_LOGV("Found stream class ID to use: notit-addr=%p, "
996 "stream-class-id=%" PRIu64
", "
997 "trace-addr=%p, trace-name=\"%s\"",
998 notit
, stream_id
, notit
->meta
.trace
,
999 bt_trace_get_name(notit
->meta
.trace
));
1001 new_stream_class
= bt_trace_borrow_stream_class_by_id(
1002 notit
->meta
.trace
, stream_id
);
1003 if (!new_stream_class
) {
1004 BT_LOGW("No stream class with ID of stream class ID to use in trace: "
1005 "notit-addr=%p, stream-class-id=%" PRIu64
", "
1006 "trace-addr=%p, trace-name=\"%s\"",
1007 notit
, stream_id
, notit
->meta
.trace
,
1008 bt_trace_get_name(notit
->meta
.trace
));
1009 status
= BT_NOTIF_ITER_STATUS_ERROR
;
1013 if (notit
->meta
.stream_class
) {
1014 if (new_stream_class
!= notit
->meta
.stream_class
) {
1015 BT_LOGW("Two packets refer to two different stream classes within the same packet sequence: "
1016 "notit-addr=%p, prev-stream-class-addr=%p, "
1017 "prev-stream-class-name=\"%s\", "
1018 "prev-stream-class-id=%" PRId64
", "
1019 "next-stream-class-addr=%p, "
1020 "next-stream-class-name=\"%s\", "
1021 "next-stream-class-id=%" PRId64
", "
1022 "trace-addr=%p, trace-name=\"%s\"",
1023 notit
, notit
->meta
.stream_class
,
1024 bt_stream_class_get_name(notit
->meta
.stream_class
),
1025 bt_stream_class_get_id(notit
->meta
.stream_class
),
1027 bt_stream_class_get_name(new_stream_class
),
1028 bt_stream_class_get_id(new_stream_class
),
1030 bt_trace_get_name(notit
->meta
.trace
));
1031 status
= BT_NOTIF_ITER_STATUS_ERROR
;
1035 notit
->meta
.stream_class
= new_stream_class
;
1038 BT_LOGV("Set current stream class: "
1039 "notit-addr=%p, stream-class-addr=%p, "
1040 "stream-class-name=\"%s\", stream-class-id=%" PRId64
,
1041 notit
, notit
->meta
.stream_class
,
1042 bt_stream_class_get_name(notit
->meta
.stream_class
),
1043 bt_stream_class_get_id(notit
->meta
.stream_class
));
1046 * Retrieve (or lazily create) the current stream class field path
1049 notit
->cur_sc_field_path_cache
= get_stream_class_field_path_cache(
1050 notit
, notit
->meta
.stream_class
);
1051 if (!notit
->cur_sc_field_path_cache
) {
1052 BT_LOGW("Cannot retrieve stream class field path from cache: "
1053 "notit-addr=%p, stream-class-addr=%p, "
1054 "stream-class-name=\"%s\", stream-class-id=%" PRId64
,
1055 notit
, notit
->meta
.stream_class
,
1056 bt_stream_class_get_name(notit
->meta
.stream_class
),
1057 bt_stream_class_get_id(notit
->meta
.stream_class
));
1058 status
= BT_NOTIF_ITER_STATUS_ERROR
;
1067 uint64_t get_cur_stream_instance_id(struct bt_notif_iter
*notit
)
1069 struct bt_field
*stream_instance_id_field
= NULL
;
1070 uint64_t stream_instance_id
= -1ULL;
1073 if (!notit
->dscopes
.trace_packet_header
) {
1077 stream_instance_id_field
= bt_field_structure_borrow_field_by_name(
1078 notit
->dscopes
.trace_packet_header
, "stream_instance_id");
1079 if (!stream_instance_id_field
) {
1083 ret
= bt_field_integer_unsigned_get_value(stream_instance_id_field
,
1084 &stream_instance_id
);
1086 stream_instance_id
= -1ULL;
1091 return stream_instance_id
;
1095 enum bt_notif_iter_status
set_current_stream(struct bt_notif_iter
*notit
)
1097 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
1098 struct bt_stream
*stream
= NULL
;
1100 BT_LOGV("Calling user function (get stream): notit-addr=%p, "
1101 "stream-class-addr=%p, stream-class-name=\"%s\", "
1102 "stream-class-id=%" PRId64
,
1103 notit
, notit
->meta
.stream_class
,
1104 bt_stream_class_get_name(notit
->meta
.stream_class
),
1105 bt_stream_class_get_id(notit
->meta
.stream_class
));
1106 stream
= bt_get(notit
->medium
.medops
.borrow_stream(
1107 notit
->meta
.stream_class
, get_cur_stream_instance_id(notit
),
1108 notit
->medium
.data
));
1109 BT_LOGV("User function returned: stream-addr=%p", stream
);
1111 BT_LOGW_STR("User function failed to return a stream object for the given stream class.");
1112 status
= BT_NOTIF_ITER_STATUS_ERROR
;
1116 if (notit
->stream
&& stream
!= notit
->stream
) {
1117 BT_LOGW("User function returned a different stream than the previous one for the same sequence of packets.");
1118 status
= BT_NOTIF_ITER_STATUS_ERROR
;
1122 BT_MOVE(notit
->stream
, stream
);
1130 enum bt_notif_iter_status
set_current_packet(struct bt_notif_iter
*notit
)
1132 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
1133 struct bt_packet
*packet
= NULL
;
1135 BT_LOGV("Creating packet for packet notification: "
1136 "notit-addr=%p", notit
);
1137 BT_LOGV("Creating packet from stream: "
1138 "notit-addr=%p, stream-addr=%p, "
1139 "stream-class-addr=%p, "
1140 "stream-class-name=\"%s\", "
1141 "stream-class-id=%" PRId64
,
1142 notit
, notit
->stream
, notit
->meta
.stream_class
,
1143 bt_stream_class_get_name(notit
->meta
.stream_class
),
1144 bt_stream_class_get_id(notit
->meta
.stream_class
));
1147 BT_ASSERT(notit
->stream
);
1148 packet
= bt_packet_create(notit
->stream
, notit
->prev_packet_avail
,
1149 notit
->prev_packet
);
1151 BT_LOGE("Cannot create packet from stream: "
1152 "notit-addr=%p, stream-addr=%p, "
1153 "stream-class-addr=%p, "
1154 "stream-class-name=\"%s\", "
1155 "stream-class-id=%" PRId64
,
1156 notit
, notit
->stream
, notit
->meta
.stream_class
,
1157 bt_stream_class_get_name(notit
->meta
.stream_class
),
1158 bt_stream_class_get_id(notit
->meta
.stream_class
));
1166 status
= BT_NOTIF_ITER_STATUS_ERROR
;
1169 BT_MOVE(notit
->packet
, packet
);
1174 enum bt_notif_iter_status
after_packet_header_state(
1175 struct bt_notif_iter
*notit
)
1177 enum bt_notif_iter_status status
;
1179 status
= set_current_stream_class(notit
);
1180 if (status
!= BT_NOTIF_ITER_STATUS_OK
) {
1184 notit
->state
= STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
;
1191 enum bt_notif_iter_status
read_packet_context_begin_state(
1192 struct bt_notif_iter
*notit
)
1194 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
1195 struct bt_field_type
*packet_context_type
;
1197 BT_ASSERT(notit
->meta
.stream_class
);
1198 packet_context_type
= bt_stream_class_borrow_packet_context_field_type(
1199 notit
->meta
.stream_class
);
1200 if (!packet_context_type
) {
1201 BT_LOGV("No packet packet context field type in stream class: continuing: "
1202 "notit-addr=%p, stream-class-addr=%p, "
1203 "stream-class-name=\"%s\", stream-class-id=%" PRId64
,
1204 notit
, notit
->meta
.stream_class
,
1205 bt_stream_class_get_name(notit
->meta
.stream_class
),
1206 bt_stream_class_get_id(notit
->meta
.stream_class
));
1207 notit
->state
= STATE_AFTER_STREAM_PACKET_CONTEXT
;
1212 * Create free packet context field from stream class. This
1213 * field is going to be moved to the packet once we create it.
1214 * We cannot create the packet now because a packet is created
1215 * from a stream, and this API must be able to return the packet
1216 * header and context fields without creating a stream
1217 * (bt_notif_iter_get_packet_header_context_fields()).
1219 BT_ASSERT(!notit
->packet_context_field
);
1220 notit
->packet_context_field
=
1221 bt_stream_class_create_packet_context_field(
1222 notit
->meta
.stream_class
);
1223 if (!notit
->packet_context_field
) {
1224 BT_LOGE_STR("Cannot create packet context field wrapper from stream class.");
1225 status
= BT_NOTIF_ITER_STATUS_ERROR
;
1229 notit
->dscopes
.stream_packet_context
=
1230 bt_packet_context_field_borrow_field(notit
->packet_context_field
);
1231 BT_ASSERT(notit
->dscopes
.stream_packet_context
);
1232 BT_LOGV("Decoding packet context field: "
1233 "notit-addr=%p, stream-class-addr=%p, "
1234 "stream-class-name=\"%s\", stream-class-id=%" PRId64
", "
1236 notit
, notit
->meta
.stream_class
,
1237 bt_stream_class_get_name(notit
->meta
.stream_class
),
1238 bt_stream_class_get_id(notit
->meta
.stream_class
),
1239 packet_context_type
);
1240 status
= read_dscope_begin_state(notit
, packet_context_type
,
1241 STATE_AFTER_STREAM_PACKET_CONTEXT
,
1242 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
,
1243 notit
->dscopes
.stream_packet_context
);
1245 BT_LOGW("Cannot decode packet context field: "
1246 "notit-addr=%p, stream-class-addr=%p, "
1247 "stream-class-name=\"%s\", "
1248 "stream-class-id=%" PRId64
", ft-addr=%p",
1249 notit
, notit
->meta
.stream_class
,
1250 bt_stream_class_get_name(notit
->meta
.stream_class
),
1251 bt_stream_class_get_id(notit
->meta
.stream_class
),
1252 packet_context_type
);
1260 enum bt_notif_iter_status
read_packet_context_continue_state(
1261 struct bt_notif_iter
*notit
)
1263 return read_dscope_continue_state(notit
,
1264 STATE_AFTER_STREAM_PACKET_CONTEXT
);
1268 uint64_t get_field_raw_clock_value(struct bt_field
*base_field
,
1269 const char *field_name
, struct bt_clock_class
**user_cc
)
1271 struct bt_field
*field
;
1272 struct bt_field_type
*ft
;
1273 struct bt_clock_class
*clock_class
= NULL
;
1274 uint64_t val
= UINT64_C(-1);
1277 field
= bt_field_structure_borrow_field_by_name(base_field
, field_name
);
1282 ft
= bt_field_borrow_type(field
);
1285 if (!bt_field_type_is_integer(ft
)) {
1289 clock_class
= bt_field_type_integer_borrow_mapped_clock_class(ft
);
1294 ret
= bt_field_integer_unsigned_get_value(field
, &val
);
1295 BT_ASSERT(ret
== 0);
1298 *user_cc
= clock_class
;
1303 enum bt_notif_iter_status
set_current_packet_content_sizes(
1304 struct bt_notif_iter
*notit
)
1306 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
1307 struct bt_field
*packet_size_field
= NULL
;
1308 struct bt_field
*content_size_field
= NULL
;
1309 uint64_t content_size
= -1ULL, packet_size
= -1ULL;
1311 if (!notit
->dscopes
.stream_packet_context
) {
1315 packet_size_field
= bt_field_structure_borrow_field_by_name(
1316 notit
->dscopes
.stream_packet_context
, "packet_size");
1317 content_size_field
= bt_field_structure_borrow_field_by_name(
1318 notit
->dscopes
.stream_packet_context
, "content_size");
1319 if (packet_size_field
) {
1320 int ret
= bt_field_integer_unsigned_get_value(
1321 packet_size_field
, &packet_size
);
1323 BT_ASSERT(ret
== 0);
1324 if (packet_size
== 0) {
1325 BT_LOGW("Invalid packet size: packet context field indicates packet size is zero: "
1326 "notit-addr=%p, packet-context-field-addr=%p",
1327 notit
, notit
->dscopes
.stream_packet_context
);
1328 status
= BT_NOTIF_ITER_STATUS_ERROR
;
1330 } else if ((packet_size
% 8) != 0) {
1331 BT_LOGW("Invalid packet size: packet context field indicates packet size is not a multiple of 8: "
1332 "notit-addr=%p, packet-context-field-addr=%p, "
1333 "packet-size=%" PRIu64
,
1334 notit
, notit
->dscopes
.stream_packet_context
,
1336 status
= BT_NOTIF_ITER_STATUS_ERROR
;
1341 if (content_size_field
) {
1342 int ret
= bt_field_integer_unsigned_get_value(
1343 content_size_field
, &content_size
);
1345 BT_ASSERT(ret
== 0);
1347 content_size
= packet_size
;
1350 if (content_size
> packet_size
) {
1351 BT_LOGW("Invalid packet or content size: packet context field indicates content size is greater than packet size: "
1352 "notit-addr=%p, packet-context-field-addr=%p, "
1353 "packet-size=%" PRIu64
", content-size=%" PRIu64
,
1354 notit
, notit
->dscopes
.stream_packet_context
,
1355 packet_size
, content_size
);
1356 status
= BT_NOTIF_ITER_STATUS_ERROR
;
1360 if (packet_size
!= -1ULL) {
1361 notit
->cur_packet_size
= packet_size
;
1364 * Use the content size as packet size indicator if the
1365 * packet size field is missing. This means there is no
1366 * padding in this stream.
1368 notit
->cur_packet_size
= content_size
;
1370 notit
->cur_content_size
= content_size
;
1371 BT_LOGV("Set current packet and content sizes: "
1372 "notit-addr=%p, packet-size=%" PRIu64
", content-size=%" PRIu64
,
1373 notit
, packet_size
, content_size
);
1379 enum bt_notif_iter_status
after_packet_context_state(
1380 struct bt_notif_iter
*notit
)
1382 enum bt_notif_iter_status status
;
1384 status
= set_current_packet_content_sizes(notit
);
1385 if (status
!= BT_NOTIF_ITER_STATUS_OK
) {
1389 if (notit
->stream_begin_emitted
) {
1390 notit
->state
= STATE_EMIT_NOTIF_NEW_PACKET
;
1392 notit
->state
= STATE_EMIT_NOTIF_NEW_STREAM
;
1400 enum bt_notif_iter_status
read_event_header_begin_state(
1401 struct bt_notif_iter
*notit
)
1403 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
1404 struct bt_field_type
*event_header_type
= NULL
;
1406 /* Reset the position of the last event header */
1407 notit
->buf
.last_eh_at
= notit
->buf
.at
;
1409 /* Check if we have some content left */
1410 if (notit
->cur_content_size
>= 0) {
1411 if (packet_at(notit
) == notit
->cur_content_size
) {
1412 /* No more events! */
1413 BT_LOGV("Reached end of packet: notit-addr=%p, "
1414 "cur=%zu", notit
, packet_at(notit
));
1415 notit
->state
= STATE_EMIT_NOTIF_END_OF_PACKET
;
1417 } else if (packet_at(notit
) > notit
->cur_content_size
) {
1418 /* That's not supposed to happen */
1419 BT_LOGV("Before decoding event header field: cursor is passed the packet's content: "
1420 "notit-addr=%p, content-size=%" PRId64
", "
1421 "cur=%zu", notit
, notit
->cur_content_size
,
1423 status
= BT_NOTIF_ITER_STATUS_ERROR
;
1428 release_event_dscopes(notit
);
1429 BT_ASSERT(notit
->meta
.stream_class
);
1430 event_header_type
= bt_stream_class_borrow_event_header_field_type(
1431 notit
->meta
.stream_class
);
1432 if (!event_header_type
) {
1433 notit
->state
= STATE_AFTER_STREAM_EVENT_HEADER
;
1437 BT_ASSERT(!notit
->event_header_field
);
1438 notit
->event_header_field
= bt_stream_class_create_event_header_field(
1439 notit
->meta
.stream_class
);
1440 if (!notit
->event_header_field
) {
1441 BT_LOGE_STR("Cannot create event header field wrapper from trace.");
1442 status
= BT_NOTIF_ITER_STATUS_ERROR
;
1446 notit
->dscopes
.stream_event_header
=
1447 bt_event_header_field_borrow_field(notit
->event_header_field
);
1448 BT_ASSERT(notit
->dscopes
.stream_event_header
);
1449 BT_LOGV("Decoding event header field: "
1450 "notit-addr=%p, stream-class-addr=%p, "
1451 "stream-class-name=\"%s\", stream-class-id=%" PRId64
", "
1453 notit
, notit
->meta
.stream_class
,
1454 bt_stream_class_get_name(notit
->meta
.stream_class
),
1455 bt_stream_class_get_id(notit
->meta
.stream_class
),
1457 status
= read_dscope_begin_state(notit
, event_header_type
,
1458 STATE_AFTER_STREAM_EVENT_HEADER
,
1459 STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE
,
1460 notit
->dscopes
.stream_event_header
);
1462 BT_LOGW("Cannot decode event header field: "
1463 "notit-addr=%p, stream-class-addr=%p, "
1464 "stream-class-name=\"%s\", "
1465 "stream-class-id=%" PRId64
", ft-addr=%p",
1466 notit
, notit
->meta
.stream_class
,
1467 bt_stream_class_get_name(notit
->meta
.stream_class
),
1468 bt_stream_class_get_id(notit
->meta
.stream_class
),
1477 enum bt_notif_iter_status
read_event_header_continue_state(
1478 struct bt_notif_iter
*notit
)
1480 return read_dscope_continue_state(notit
,
1481 STATE_AFTER_STREAM_EVENT_HEADER
);
1485 enum bt_notif_iter_status
set_current_event_class(struct bt_notif_iter
*notit
)
1488 * The assert() calls in this function are okay because it is
1489 * assumed here that all the metadata objects have been
1490 * validated for CTF correctness before decoding actual streams.
1493 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
1494 struct bt_field_type
*event_header_type
;
1495 struct bt_field_type
*id_field_type
= NULL
;
1496 struct bt_field_type
*v_field_type
= NULL
;
1497 uint64_t event_id
= -1ULL;
1500 event_header_type
= bt_stream_class_borrow_event_header_field_type(
1501 notit
->meta
.stream_class
);
1502 if (!event_header_type
) {
1504 * No event header, therefore no event class ID field,
1505 * therefore only one event class.
1507 goto single_event_class
;
1510 /* Is there any "id"/"v" field in the event header? */
1511 BT_ASSERT(bt_field_type_is_structure(event_header_type
));
1512 id_field_type
= bt_field_type_structure_borrow_field_type_by_name(
1513 event_header_type
, "id");
1514 v_field_type
= bt_field_type_structure_borrow_field_type_by_name(
1515 event_header_type
, "v");
1516 BT_ASSERT(notit
->dscopes
.stream_event_header
);
1520 * | | |_ _|_ _| __ __ _
1521 * | | | | | || '_ \ / _` |
1522 * | |___| | | || | | | (_| | S P E C I A L
1523 * |_____|_| |_||_| |_|\__, | C A S E â„¢
1526 struct bt_field
*v_field
= NULL
;
1527 struct bt_field
*v_struct_field
= NULL
;
1528 struct bt_field
*v_struct_id_field
= NULL
;
1530 // TODO: optimalize!
1531 v_field
= bt_field_structure_borrow_field_by_name(
1532 notit
->dscopes
.stream_event_header
, "v");
1536 bt_field_variant_borrow_current_field(v_field
);
1537 if (!v_struct_field
) {
1538 goto end_v_field_type
;
1541 // TODO: optimalize!
1542 v_struct_id_field
= bt_field_structure_borrow_field_by_name(
1543 v_struct_field
, "id");
1544 if (!v_struct_id_field
) {
1545 goto end_v_field_type
;
1548 if (bt_field_is_integer(v_struct_id_field
)) {
1549 ret
= bt_field_integer_unsigned_get_value(
1550 v_struct_id_field
, &event_id
);
1552 BT_LOGV("Cannot get value of unsigned integer field (`id`): continuing: "
1553 "notit=%p, field-addr=%p",
1554 notit
, v_struct_id_field
);
1561 if (id_field_type
&& event_id
== -1ULL) {
1562 /* Check "id" field */
1563 struct bt_field
*id_field
= NULL
;
1564 int ret_get_value
= 0;
1566 // TODO: optimalize!
1567 id_field
= bt_field_structure_borrow_field_by_name(
1568 notit
->dscopes
.stream_event_header
, "id");
1570 goto check_event_id
;
1573 ret_get_value
= bt_field_integer_unsigned_get_value(
1574 id_field
, &event_id
);
1575 BT_ASSERT(ret_get_value
== 0);
1579 if (event_id
== -1ULL) {
1581 /* Event ID not found: single event? */
1582 BT_ASSERT(bt_stream_class_get_event_class_count(
1583 notit
->meta
.stream_class
) == 1);
1587 BT_LOGV("Found event class ID to use: notit-addr=%p, "
1588 "stream-class-addr=%p, stream-class-name=\"%s\", "
1589 "stream-class-id=%" PRId64
", "
1590 "event-class-id=%" PRIu64
,
1591 notit
, notit
->meta
.stream_class
,
1592 bt_stream_class_get_name(notit
->meta
.stream_class
),
1593 bt_stream_class_get_id(notit
->meta
.stream_class
),
1595 notit
->meta
.event_class
= bt_stream_class_borrow_event_class_by_id(
1596 notit
->meta
.stream_class
, event_id
);
1597 if (!notit
->meta
.event_class
) {
1598 BT_LOGW("No event class with ID of event class ID to use in stream class: "
1599 "notit-addr=%p, stream-class-addr=%p, "
1600 "stream-class-name=\"%s\", "
1601 "stream-class-id=%" PRId64
", "
1602 "event-class-id=%" PRIu64
,
1603 notit
, notit
->meta
.stream_class
,
1604 bt_stream_class_get_name(notit
->meta
.stream_class
),
1605 bt_stream_class_get_id(notit
->meta
.stream_class
),
1607 status
= BT_NOTIF_ITER_STATUS_ERROR
;
1611 BT_LOGV("Set current event class: "
1612 "notit-addr=%p, event-class-addr=%p, "
1613 "event-class-name=\"%s\", event-class-id=%" PRId64
,
1614 notit
, notit
->meta
.event_class
,
1615 bt_event_class_get_name(notit
->meta
.event_class
),
1616 bt_event_class_get_id(notit
->meta
.event_class
));
1623 enum bt_notif_iter_status
set_current_event_notification(
1624 struct bt_notif_iter
*notit
)
1626 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
1627 struct bt_notification
*notif
= NULL
;
1629 BT_ASSERT(notit
->meta
.event_class
);
1630 BT_ASSERT(notit
->packet
);
1631 BT_LOGV("Creating event notification from event class and packet: "
1632 "notit-addr=%p, ec-addr=%p, ec-name=\"%s\", packet-addr=%p",
1633 notit
, notit
->meta
.event_class
,
1634 bt_event_class_get_name(notit
->meta
.event_class
),
1636 BT_ASSERT(notit
->notif_iter
);
1637 notif
= bt_notification_event_create(notit
->notif_iter
,
1638 notit
->meta
.event_class
, notit
->packet
);
1640 BT_LOGE("Cannot create event notification: "
1641 "notit-addr=%p, ec-addr=%p, ec-name=\"%s\", "
1643 notit
, notit
->meta
.event_class
,
1644 bt_event_class_get_name(notit
->meta
.event_class
),
1653 status
= BT_NOTIF_ITER_STATUS_ERROR
;
1656 BT_MOVE(notit
->event_notif
, notif
);
1661 enum bt_notif_iter_status
after_event_header_state(
1662 struct bt_notif_iter
*notit
)
1664 enum bt_notif_iter_status status
;
1666 status
= set_current_event_class(notit
);
1667 if (status
!= BT_NOTIF_ITER_STATUS_OK
) {
1671 status
= set_current_event_notification(notit
);
1672 if (status
!= BT_NOTIF_ITER_STATUS_OK
) {
1676 notit
->event
= bt_notification_event_borrow_event(notit
->event_notif
);
1677 BT_ASSERT(notit
->event
);
1679 if (notit
->event_header_field
) {
1682 BT_ASSERT(notit
->event
);
1683 ret
= bt_event_move_header(notit
->event
,
1684 notit
->event_header_field
);
1687 status
= BT_NOTIF_ITER_STATUS_ERROR
;
1691 notit
->event_header_field
= NULL
;
1694 * At this point notit->dscopes.stream_event_header has
1695 * the same value as the event header field within
1698 BT_ASSERT(bt_event_borrow_header(notit
->event
) ==
1699 notit
->dscopes
.stream_event_header
);
1702 notit
->state
= STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN
;
1709 enum bt_notif_iter_status
read_stream_event_context_begin_state(
1710 struct bt_notif_iter
*notit
)
1712 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
1713 struct bt_field_type
*stream_event_context_type
;
1715 stream_event_context_type
=
1716 bt_stream_class_borrow_event_context_field_type(
1717 notit
->meta
.stream_class
);
1718 if (!stream_event_context_type
) {
1719 notit
->state
= STATE_DSCOPE_EVENT_CONTEXT_BEGIN
;
1723 BT_ASSERT(!notit
->dscopes
.stream_event_context
);
1724 notit
->dscopes
.stream_event_context
=
1725 bt_event_borrow_stream_event_context(notit
->event
);
1726 BT_ASSERT(notit
->dscopes
.stream_event_context
);
1727 BT_LOGV("Decoding stream event context field: "
1728 "notit-addr=%p, stream-class-addr=%p, "
1729 "stream-class-name=\"%s\", stream-class-id=%" PRId64
", "
1731 notit
, notit
->meta
.stream_class
,
1732 bt_stream_class_get_name(notit
->meta
.stream_class
),
1733 bt_stream_class_get_id(notit
->meta
.stream_class
),
1734 stream_event_context_type
);
1735 status
= read_dscope_begin_state(notit
, stream_event_context_type
,
1736 STATE_DSCOPE_EVENT_CONTEXT_BEGIN
,
1737 STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE
,
1738 notit
->dscopes
.stream_event_context
);
1740 BT_LOGW("Cannot decode stream event context field: "
1741 "notit-addr=%p, stream-class-addr=%p, "
1742 "stream-class-name=\"%s\", "
1743 "stream-class-id=%" PRId64
", ft-addr=%p",
1744 notit
, notit
->meta
.stream_class
,
1745 bt_stream_class_get_name(notit
->meta
.stream_class
),
1746 bt_stream_class_get_id(notit
->meta
.stream_class
),
1747 stream_event_context_type
);
1755 enum bt_notif_iter_status
read_stream_event_context_continue_state(
1756 struct bt_notif_iter
*notit
)
1758 return read_dscope_continue_state(notit
,
1759 STATE_DSCOPE_EVENT_CONTEXT_BEGIN
);
1763 enum bt_notif_iter_status
read_event_context_begin_state(
1764 struct bt_notif_iter
*notit
)
1766 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
1767 struct bt_field_type
*event_context_type
;
1769 event_context_type
= bt_event_class_borrow_context_field_type(
1770 notit
->meta
.event_class
);
1771 if (!event_context_type
) {
1772 notit
->state
= STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
;
1776 BT_ASSERT(!notit
->dscopes
.event_context
);
1777 notit
->dscopes
.event_context
= bt_event_borrow_context(notit
->event
);
1778 BT_ASSERT(notit
->dscopes
.event_context
);
1779 BT_LOGV("Decoding event context field: "
1780 "notit-addr=%p, event-class-addr=%p, "
1781 "event-class-name=\"%s\", event-class-id=%" PRId64
", "
1783 notit
, notit
->meta
.event_class
,
1784 bt_event_class_get_name(notit
->meta
.event_class
),
1785 bt_event_class_get_id(notit
->meta
.event_class
),
1786 event_context_type
);
1787 status
= read_dscope_begin_state(notit
, event_context_type
,
1788 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
,
1789 STATE_DSCOPE_EVENT_CONTEXT_CONTINUE
,
1790 notit
->dscopes
.event_context
);
1792 BT_LOGW("Cannot decode event context field: "
1793 "notit-addr=%p, event-class-addr=%p, "
1794 "event-class-name=\"%s\", "
1795 "event-class-id=%" PRId64
", ft-addr=%p",
1796 notit
, notit
->meta
.event_class
,
1797 bt_event_class_get_name(notit
->meta
.event_class
),
1798 bt_event_class_get_id(notit
->meta
.event_class
),
1799 event_context_type
);
1807 enum bt_notif_iter_status
read_event_context_continue_state(
1808 struct bt_notif_iter
*notit
)
1810 return read_dscope_continue_state(notit
,
1811 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
);
1815 enum bt_notif_iter_status
read_event_payload_begin_state(
1816 struct bt_notif_iter
*notit
)
1818 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
1819 struct bt_field_type
*event_payload_type
;
1821 event_payload_type
= bt_event_class_borrow_payload_field_type(
1822 notit
->meta
.event_class
);
1823 if (!event_payload_type
) {
1824 notit
->state
= STATE_EMIT_NOTIF_EVENT
;
1828 BT_ASSERT(!notit
->dscopes
.event_payload
);
1829 notit
->dscopes
.event_payload
= bt_event_borrow_payload(notit
->event
);
1830 BT_ASSERT(notit
->dscopes
.event_payload
);
1831 BT_LOGV("Decoding event payload field: "
1832 "notit-addr=%p, event-class-addr=%p, "
1833 "event-class-name=\"%s\", event-class-id=%" PRId64
", "
1835 notit
, notit
->meta
.event_class
,
1836 bt_event_class_get_name(notit
->meta
.event_class
),
1837 bt_event_class_get_id(notit
->meta
.event_class
),
1838 event_payload_type
);
1839 status
= read_dscope_begin_state(notit
, event_payload_type
,
1840 STATE_EMIT_NOTIF_EVENT
,
1841 STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
,
1842 notit
->dscopes
.event_payload
);
1844 BT_LOGW("Cannot decode event payload field: "
1845 "notit-addr=%p, event-class-addr=%p, "
1846 "event-class-name=\"%s\", "
1847 "event-class-id=%" PRId64
", ft-addr=%p",
1848 notit
, notit
->meta
.event_class
,
1849 bt_event_class_get_name(notit
->meta
.event_class
),
1850 bt_event_class_get_id(notit
->meta
.event_class
),
1851 event_payload_type
);
1859 enum bt_notif_iter_status
read_event_payload_continue_state(
1860 struct bt_notif_iter
*notit
)
1862 return read_dscope_continue_state(notit
, STATE_EMIT_NOTIF_EVENT
);
1866 enum bt_notif_iter_status
skip_packet_padding_state(
1867 struct bt_notif_iter
*notit
)
1869 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
1870 size_t bits_to_skip
;
1872 BT_ASSERT(notit
->cur_packet_size
> 0);
1873 bits_to_skip
= notit
->cur_packet_size
- packet_at(notit
);
1874 if (bits_to_skip
== 0) {
1875 notit
->state
= STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
;
1878 size_t bits_to_consume
;
1880 BT_LOGV("Trying to skip %zu bits of padding: notit-addr=%p, size=%zu",
1881 bits_to_skip
, notit
, bits_to_skip
);
1882 status
= buf_ensure_available_bits(notit
);
1883 if (status
!= BT_NOTIF_ITER_STATUS_OK
) {
1887 bits_to_consume
= MIN(buf_available_bits(notit
), bits_to_skip
);
1888 BT_LOGV("Skipping %zu bits of padding: notit-addr=%p, size=%zu",
1889 bits_to_consume
, notit
, bits_to_consume
);
1890 buf_consume_bits(notit
, bits_to_consume
);
1891 bits_to_skip
= notit
->cur_packet_size
- packet_at(notit
);
1892 if (bits_to_skip
== 0) {
1893 notit
->state
= STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
;
1903 enum bt_notif_iter_status
handle_state(struct bt_notif_iter
*notit
)
1905 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
1906 const enum state state
= notit
->state
;
1908 BT_LOGV("Handling state: notit-addr=%p, state=%s",
1909 notit
, state_string(state
));
1911 // TODO: optimalize!
1914 notit
->state
= STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
;
1916 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
:
1917 status
= read_packet_header_begin_state(notit
);
1919 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
:
1920 status
= read_packet_header_continue_state(notit
);
1922 case STATE_AFTER_TRACE_PACKET_HEADER
:
1923 status
= after_packet_header_state(notit
);
1925 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
:
1926 status
= read_packet_context_begin_state(notit
);
1928 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
:
1929 status
= read_packet_context_continue_state(notit
);
1931 case STATE_AFTER_STREAM_PACKET_CONTEXT
:
1932 status
= after_packet_context_state(notit
);
1934 case STATE_EMIT_NOTIF_NEW_STREAM
:
1935 notit
->state
= STATE_EMIT_NOTIF_NEW_PACKET
;
1937 case STATE_EMIT_NOTIF_NEW_PACKET
:
1938 notit
->state
= STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN
;
1940 case STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN
:
1941 status
= read_event_header_begin_state(notit
);
1943 case STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE
:
1944 status
= read_event_header_continue_state(notit
);
1946 case STATE_AFTER_STREAM_EVENT_HEADER
:
1947 status
= after_event_header_state(notit
);
1949 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN
:
1950 status
= read_stream_event_context_begin_state(notit
);
1952 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE
:
1953 status
= read_stream_event_context_continue_state(notit
);
1955 case STATE_DSCOPE_EVENT_CONTEXT_BEGIN
:
1956 status
= read_event_context_begin_state(notit
);
1958 case STATE_DSCOPE_EVENT_CONTEXT_CONTINUE
:
1959 status
= read_event_context_continue_state(notit
);
1961 case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
:
1962 status
= read_event_payload_begin_state(notit
);
1964 case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
:
1965 status
= read_event_payload_continue_state(notit
);
1967 case STATE_EMIT_NOTIF_EVENT
:
1968 notit
->state
= STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN
;
1970 case STATE_SKIP_PACKET_PADDING
:
1971 status
= skip_packet_padding_state(notit
);
1973 case STATE_EMIT_NOTIF_END_OF_PACKET
:
1974 notit
->state
= STATE_SKIP_PACKET_PADDING
;
1977 BT_LOGD("Unknown CTF plugin notification iterator state: "
1978 "notit-addr=%p, state=%d", notit
, notit
->state
);
1982 BT_LOGV("Handled state: notit-addr=%p, status=%s, "
1983 "prev-state=%s, cur-state=%s",
1984 notit
, bt_notif_iter_status_string(status
),
1985 state_string(state
), state_string(notit
->state
));
1990 * Resets the internal state of a CTF notification iterator.
1993 void bt_notif_iter_reset(struct bt_notif_iter
*notit
)
1996 BT_LOGD("Resetting notification iterator: addr=%p", notit
);
1997 stack_clear(notit
->stack
);
1998 notit
->meta
.stream_class
= NULL
;
1999 notit
->meta
.event_class
= NULL
;
2000 BT_PUT(notit
->packet
);
2001 notit
->prev_packet_avail
= BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NONE
;
2002 BT_PUT(notit
->prev_packet
);
2003 BT_PUT(notit
->stream
);
2004 BT_PUT(notit
->event_notif
);
2005 release_all_dscopes(notit
);
2006 notit
->cur_dscope_field
= NULL
;
2008 if (notit
->packet_header_field
) {
2009 bt_packet_header_field_release(notit
->packet_header_field
);
2010 notit
->packet_header_field
= NULL
;
2013 if (notit
->packet_context_field
) {
2014 bt_packet_context_field_release(notit
->packet_context_field
);
2015 notit
->packet_context_field
= NULL
;
2018 if (notit
->event_header_field
) {
2019 bt_event_header_field_release(notit
->event_header_field
);
2020 notit
->event_header_field
= NULL
;
2023 notit
->buf
.addr
= NULL
;
2026 notit
->buf
.last_eh_at
= SIZE_MAX
;
2027 notit
->buf
.packet_offset
= 0;
2028 notit
->state
= STATE_INIT
;
2029 notit
->cur_content_size
= -1;
2030 notit
->cur_packet_size
= -1;
2031 notit
->cur_packet_offset
= -1;
2032 notit
->stream_begin_emitted
= false;
2033 notit
->cur_timestamp_end
= NULL
;
2037 int bt_notif_iter_switch_packet(struct bt_notif_iter
*notit
)
2042 * We don't put the stream class here because we need to make
2043 * sure that all the packets processed by the same notification
2044 * iterator refer to the same stream class (the first one).
2048 if (notit
->cur_packet_size
!= -1) {
2049 notit
->cur_packet_offset
+= notit
->cur_packet_size
;
2052 BT_LOGV("Switching packet: notit-addr=%p, cur=%zu, "
2053 "packet-offset=%" PRId64
, notit
, notit
->buf
.at
,
2054 notit
->cur_packet_offset
);
2055 stack_clear(notit
->stack
);
2056 notit
->meta
.event_class
= NULL
;
2057 BT_PUT(notit
->packet
);
2058 BT_PUT(notit
->event_notif
);
2059 notit
->cur_timestamp_end
= NULL
;
2060 release_all_dscopes(notit
);
2061 notit
->cur_dscope_field
= NULL
;
2064 * Adjust current buffer so that addr points to the beginning of the new
2067 if (notit
->buf
.addr
) {
2068 size_t consumed_bytes
= (size_t) (notit
->buf
.at
/ CHAR_BIT
);
2070 /* Packets are assumed to start on a byte frontier. */
2071 if (notit
->buf
.at
% CHAR_BIT
) {
2072 BT_LOGW("Cannot switch packet: current position is not a multiple of 8: "
2073 "notit-addr=%p, cur=%zu", notit
, notit
->buf
.at
);
2078 notit
->buf
.addr
+= consumed_bytes
;
2079 notit
->buf
.sz
-= consumed_bytes
;
2081 notit
->buf
.packet_offset
= 0;
2082 BT_LOGV("Adjusted buffer: addr=%p, size=%zu",
2083 notit
->buf
.addr
, notit
->buf
.sz
);
2086 notit
->cur_content_size
= -1;
2087 notit
->cur_packet_size
= -1;
2088 notit
->cur_sc_field_path_cache
= NULL
;
2095 struct bt_field
*borrow_next_field(struct bt_notif_iter
*notit
)
2097 struct bt_field
*next_field
= NULL
;
2098 struct bt_field
*base_field
;
2099 struct bt_field_type
*base_type
;
2102 BT_ASSERT(!stack_empty(notit
->stack
));
2103 index
= stack_top(notit
->stack
)->index
;
2104 base_field
= stack_top(notit
->stack
)->base
;
2105 BT_ASSERT(base_field
);
2106 base_type
= bt_field_borrow_type(base_field
);
2107 BT_ASSERT(base_type
);
2109 switch (bt_field_type_get_type_id(base_type
)) {
2110 case BT_FIELD_TYPE_ID_STRUCT
:
2112 next_field
= bt_field_structure_borrow_field_by_index(
2116 case BT_FIELD_TYPE_ID_ARRAY
:
2117 next_field
= bt_field_array_borrow_field(base_field
, index
);
2119 case BT_FIELD_TYPE_ID_SEQUENCE
:
2120 next_field
= bt_field_sequence_borrow_field(base_field
, index
);
2122 case BT_FIELD_TYPE_ID_VARIANT
:
2123 next_field
= bt_field_variant_borrow_current_field(base_field
);
2126 BT_LOGF("Unknown base field type ID: "
2127 "notit-addr=%p, ft-addr=%p, ft-id=%s",
2129 bt_common_field_type_id_string(
2130 bt_field_type_get_type_id(base_type
)));
2138 void update_clock_state(uint64_t *state
, struct bt_field
*value_field
,
2139 struct bt_field_type
*value_type
)
2141 uint64_t requested_new_value
;
2142 uint64_t requested_new_value_mask
;
2143 uint64_t cur_value_masked
;
2144 int requested_new_value_size
;
2147 BT_ASSERT(value_type
);
2148 BT_ASSERT(bt_field_type_is_integer(value_type
));
2149 requested_new_value_size
=
2150 bt_field_type_integer_get_size(value_type
);
2151 BT_ASSERT(requested_new_value_size
> 0);
2152 ret
= bt_field_integer_unsigned_get_value(value_field
,
2153 &requested_new_value
);
2157 * Special case for a 64-bit new value, which is the limit
2158 * of a clock value as of this version: overwrite the
2159 * current value directly.
2161 if (requested_new_value_size
== 64) {
2162 *state
= requested_new_value
;
2166 requested_new_value_mask
= (1ULL << requested_new_value_size
) - 1;
2167 cur_value_masked
= *state
& requested_new_value_mask
;
2169 if (requested_new_value
< cur_value_masked
) {
2171 * It looks like a wrap happened on the number of bits
2172 * of the requested new value. Assume that the clock
2173 * value wrapped only one time.
2175 *state
+= requested_new_value_mask
+ 1;
2178 /* Clear the low bits of the current clock value. */
2179 *state
&= ~requested_new_value_mask
;
2181 /* Set the low bits of the current clock value. */
2182 *state
|= requested_new_value
;
2185 BT_LOGV("Updated clock's value from integer field's value: "
2186 "value=%" PRIu64
, *state
);
2190 enum bt_btr_status
update_clock(struct bt_notif_iter
*notit
,
2191 struct bt_field
*int_field
)
2193 gboolean clock_class_found
;
2194 uint64_t *clock_state
= NULL
;
2195 struct bt_field_type
*int_field_type
= NULL
;
2196 enum bt_btr_status ret
= BT_BTR_STATUS_OK
;
2197 struct bt_clock_class
*clock_class
= NULL
;
2199 int_field_type
= bt_field_borrow_type(int_field
);
2200 BT_ASSERT(int_field_type
);
2202 if (bt_field_type_is_enumeration(int_field_type
)) {
2204 bt_field_type_enumeration_borrow_container_field_type(
2208 clock_class
= bt_field_type_integer_borrow_mapped_clock_class(
2210 if (likely(!clock_class
)) {
2214 clock_class_found
= g_hash_table_lookup_extended(notit
->clock_states
,
2215 clock_class
, NULL
, (gpointer
) &clock_state
);
2216 if (!clock_class_found
) {
2217 clock_state
= g_new0(uint64_t, 1);
2219 BT_LOGE_STR("Failed to allocate a uint64_t.");
2220 ret
= BT_BTR_STATUS_ENOMEM
;
2224 g_hash_table_insert(notit
->clock_states
, clock_class
,
2228 /* Update the clock's state. */
2229 BT_LOGV("Updating notification iterator's clock's value from integer field: "
2230 "notit-addr=%p, clock-class-addr=%p, "
2231 "clock-class-name=\"%s\", value=%" PRIu64
,
2233 bt_clock_class_get_name(clock_class
), *clock_state
);
2234 update_clock_state(clock_state
, int_field
, int_field_type
);
2241 enum bt_btr_status
btr_unsigned_int_common(uint64_t value
,
2242 struct bt_field_type
*type
, void *data
,
2243 struct bt_field
**out_field
)
2245 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
2246 struct bt_field
*field
= NULL
;
2247 struct bt_notif_iter
*notit
= data
;
2250 BT_LOGV("Common unsigned integer function called from BTR: "
2251 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2252 "ft-id=%s, value=%" PRIu64
,
2253 notit
, notit
->btr
, type
,
2254 bt_common_field_type_id_string(
2255 bt_field_type_get_type_id(type
)),
2257 field
= borrow_next_field(notit
);
2259 BT_LOGW("Cannot borrow next field: notit-addr=%p", notit
);
2260 status
= BT_BTR_STATUS_ERROR
;
2264 BT_ASSERT(bt_field_is_integer(field
) || bt_field_is_enumeration(field
));
2265 ret
= bt_field_integer_unsigned_set_value(field
, value
);
2266 BT_ASSERT(ret
== 0);
2267 stack_top(notit
->stack
)->index
++;
2275 enum bt_btr_status
btr_timestamp_end_cb(void *value
,
2276 struct bt_field_type
*type
, void *data
)
2278 enum bt_btr_status status
;
2279 struct bt_field
*field
= NULL
;
2280 struct bt_notif_iter
*notit
= data
;
2281 uint64_t uvalue
= *((uint64_t *) value
);
2283 BT_LOGV("`timestamp_end` unsigned integer function called from BTR: "
2284 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2286 notit
, notit
->btr
, type
,
2287 bt_common_field_type_id_string(
2288 bt_field_type_get_type_id(type
)));
2290 status
= btr_unsigned_int_common(uvalue
, type
, data
, &field
);
2292 /* Set as the current packet's end timestamp field */
2293 notit
->cur_timestamp_end
= field
;
2298 enum bt_btr_status
btr_unsigned_int_cb(uint64_t value
,
2299 struct bt_field_type
*type
, void *data
)
2301 struct bt_notif_iter
*notit
= data
;
2302 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
2303 struct bt_field
*field
= NULL
;
2304 struct field_cb_override
*override
;
2306 BT_LOGV("Unsigned integer function called from BTR: "
2307 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2308 "ft-id=%s, value=%" PRIu64
,
2309 notit
, notit
->btr
, type
,
2310 bt_common_field_type_id_string(
2311 bt_field_type_get_type_id(type
)),
2313 override
= g_hash_table_lookup(notit
->field_overrides
, type
);
2314 if (unlikely(override
)) {
2315 /* Override function logs errors */
2316 status
= override
->func(&value
, type
, override
->data
);
2320 status
= btr_unsigned_int_common(value
, type
, data
, &field
);
2321 if (status
!= BT_BTR_STATUS_OK
) {
2322 /* btr_unsigned_int_common() logs errors */
2326 status
= update_clock(notit
, field
);
2333 enum bt_btr_status
btr_signed_int_cb(int64_t value
,
2334 struct bt_field_type
*type
, void *data
)
2336 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
2337 struct bt_field
*field
= NULL
;
2338 struct bt_notif_iter
*notit
= data
;
2341 BT_LOGV("Signed integer function called from BTR: "
2342 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2343 "ft-id=%s, value=%" PRId64
,
2344 notit
, notit
->btr
, type
,
2345 bt_common_field_type_id_string(
2346 bt_field_type_get_type_id(type
)),
2348 field
= borrow_next_field(notit
);
2350 BT_LOGW("Cannot borrow next field: notit-addr=%p", notit
);
2351 status
= BT_BTR_STATUS_ERROR
;
2355 BT_ASSERT(bt_field_is_integer(field
) || bt_field_is_enumeration(field
));
2356 ret
= bt_field_integer_signed_set_value(field
, value
);
2357 BT_ASSERT(ret
== 0);
2358 stack_top(notit
->stack
)->index
++;
2365 enum bt_btr_status
btr_floating_point_cb(double value
,
2366 struct bt_field_type
*type
, void *data
)
2368 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
2369 struct bt_field
*field
= NULL
;
2370 struct bt_notif_iter
*notit
= data
;
2373 BT_LOGV("Floating point number function called from BTR: "
2374 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2375 "ft-id=%s, value=%f",
2376 notit
, notit
->btr
, type
,
2377 bt_common_field_type_id_string(
2378 bt_field_type_get_type_id(type
)),
2380 field
= borrow_next_field(notit
);
2382 BT_LOGW("Cannot borrow next field: notit-addr=%p", notit
);
2383 status
= BT_BTR_STATUS_ERROR
;
2387 ret
= bt_field_floating_point_set_value(field
, value
);
2389 stack_top(notit
->stack
)->index
++;
2396 enum bt_btr_status
btr_string_begin_cb(
2397 struct bt_field_type
*type
, void *data
)
2399 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
2400 struct bt_field
*field
= NULL
;
2401 struct bt_notif_iter
*notit
= data
;
2404 BT_LOGV("String (beginning) function called from BTR: "
2405 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2407 notit
, notit
->btr
, type
,
2408 bt_common_field_type_id_string(
2409 bt_field_type_get_type_id(type
)));
2410 field
= borrow_next_field(notit
);
2412 BT_LOGW("Cannot get next field: notit-addr=%p", notit
);
2413 status
= BT_BTR_STATUS_ERROR
;
2417 ret
= bt_field_string_clear(field
);
2418 BT_ASSERT(ret
== 0);
2421 * Push on stack. Not a compound type per se, but we know that only
2422 * btr_string_cb() may be called between this call and a subsequent
2423 * call to btr_string_end_cb().
2425 ret
= stack_push(notit
->stack
, field
);
2427 BT_LOGE("Cannot push string field on stack: "
2428 "notit-addr=%p, field-addr=%p", notit
, field
);
2429 status
= BT_BTR_STATUS_ERROR
;
2438 enum bt_btr_status
btr_string_cb(const char *value
,
2439 size_t len
, struct bt_field_type
*type
, void *data
)
2441 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
2442 struct bt_field
*field
= NULL
;
2443 struct bt_notif_iter
*notit
= data
;
2446 BT_LOGV("String (substring) function called from BTR: "
2447 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2448 "ft-id=%s, string-length=%zu",
2449 notit
, notit
->btr
, type
,
2450 bt_common_field_type_id_string(
2451 bt_field_type_get_type_id(type
)),
2453 field
= stack_top(notit
->stack
)->base
;
2456 /* Append current substring */
2457 ret
= bt_field_string_append_len(field
, value
, len
);
2459 BT_LOGE("Cannot append substring to string field's value: "
2460 "notit-addr=%p, field-addr=%p, string-length=%zu, "
2461 "ret=%d", notit
, field
, len
, ret
);
2462 status
= BT_BTR_STATUS_ERROR
;
2471 enum bt_btr_status
btr_string_end_cb(
2472 struct bt_field_type
*type
, void *data
)
2474 struct bt_notif_iter
*notit
= data
;
2476 BT_LOGV("String (end) function called from BTR: "
2477 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2479 notit
, notit
->btr
, type
,
2480 bt_common_field_type_id_string(
2481 bt_field_type_get_type_id(type
)));
2483 /* Pop string field */
2484 stack_pop(notit
->stack
);
2486 /* Go to next field */
2487 stack_top(notit
->stack
)->index
++;
2488 return BT_BTR_STATUS_OK
;
2491 enum bt_btr_status
btr_compound_begin_cb(
2492 struct bt_field_type
*type
, void *data
)
2494 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
2495 struct bt_notif_iter
*notit
= data
;
2496 struct bt_field
*field
;
2499 BT_LOGV("Compound (beginning) function called from BTR: "
2500 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2502 notit
, notit
->btr
, type
,
2503 bt_common_field_type_id_string(
2504 bt_field_type_get_type_id(type
)));
2507 if (stack_empty(notit
->stack
)) {
2508 /* Root: already set by read_dscope_begin_state() */
2509 field
= notit
->cur_dscope_field
;
2511 field
= borrow_next_field(notit
);
2513 BT_LOGW("Cannot borrow next field: notit-addr=%p", notit
);
2514 status
= BT_BTR_STATUS_ERROR
;
2521 ret
= stack_push(notit
->stack
, field
);
2523 BT_LOGE("Cannot push compound field onto the stack: "
2524 "notit-addr=%p, ft-addr=%p, ft-id=%s, ret=%d",
2526 bt_common_field_type_id_string(
2527 bt_field_type_get_type_id(type
)),
2529 status
= BT_BTR_STATUS_ERROR
;
2537 enum bt_btr_status
btr_compound_end_cb(
2538 struct bt_field_type
*type
, void *data
)
2540 struct bt_notif_iter
*notit
= data
;
2542 BT_LOGV("Compound (end) function called from BTR: "
2543 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2545 notit
, notit
->btr
, type
,
2546 bt_common_field_type_id_string(
2547 bt_field_type_get_type_id(type
)));
2548 BT_ASSERT(!stack_empty(notit
->stack
));
2551 stack_pop(notit
->stack
);
2553 /* If the stack is not empty, increment the base's index */
2554 if (!stack_empty(notit
->stack
)) {
2555 stack_top(notit
->stack
)->index
++;
2558 return BT_BTR_STATUS_OK
;
2562 struct bt_field
*resolve_field(struct bt_notif_iter
*notit
,
2563 struct bt_field_path
*path
)
2565 struct bt_field
*field
= NULL
;
2568 if (BT_LOG_ON_VERBOSE
) {
2569 GString
*gstr
= bt_field_path_string(path
);
2571 BT_LOGV("Resolving field path: notit-addr=%p, field-path=\"%s\"",
2572 notit
, gstr
? gstr
->str
: NULL
);
2575 g_string_free(gstr
, TRUE
);
2579 switch (bt_field_path_get_root_scope(path
)) {
2580 case BT_SCOPE_TRACE_PACKET_HEADER
:
2581 field
= notit
->dscopes
.trace_packet_header
;
2583 case BT_SCOPE_STREAM_PACKET_CONTEXT
:
2584 field
= notit
->dscopes
.stream_packet_context
;
2586 case BT_SCOPE_STREAM_EVENT_HEADER
:
2587 field
= notit
->dscopes
.stream_event_header
;
2589 case BT_SCOPE_STREAM_EVENT_CONTEXT
:
2590 field
= notit
->dscopes
.stream_event_context
;
2592 case BT_SCOPE_EVENT_CONTEXT
:
2593 field
= notit
->dscopes
.event_context
;
2595 case BT_SCOPE_EVENT_FIELDS
:
2596 field
= notit
->dscopes
.event_payload
;
2599 BT_LOGF("Cannot resolve field path: unknown scope: "
2600 "notit-addr=%p, root-scope=%s",
2601 notit
, bt_common_scope_string(
2602 bt_field_path_get_root_scope(path
)));
2607 BT_LOGW("Cannot resolve field path: root field not found: "
2608 "notit-addr=%p, root-scope=%s",
2609 notit
, bt_common_scope_string(
2610 bt_field_path_get_root_scope(path
)));
2614 for (i
= 0; i
< bt_field_path_get_index_count(path
); ++i
) {
2615 struct bt_field
*next_field
= NULL
;
2616 struct bt_field_type
*field_type
;
2617 int index
= bt_field_path_get_index(path
, i
);
2619 field_type
= bt_field_borrow_type(field
);
2620 BT_ASSERT(field_type
);
2622 if (bt_field_type_is_structure(field_type
)) {
2623 next_field
= bt_field_structure_borrow_field_by_index(
2625 } else if (bt_field_type_is_variant(field_type
)) {
2627 bt_field_variant_borrow_current_field(field
);
2633 BT_LOGW("Cannot find next field: "
2634 "notit-addr=%p, ft-addr=%p, ft-id=%s, index=%d",
2636 bt_common_field_type_id_string(
2637 bt_field_type_get_type_id(field_type
)),
2642 /* Move next field -> field */
2651 int64_t btr_get_sequence_length_cb(struct bt_field_type
*type
, void *data
)
2655 struct bt_field
*seq_field
;
2656 struct bt_field_path
*field_path
;
2657 struct bt_notif_iter
*notit
= data
;
2658 struct bt_field
*length_field
= NULL
;
2661 field_path
= bt_field_type_sequence_borrow_length_field_path(type
);
2662 BT_ASSERT(field_path
);
2663 length_field
= resolve_field(notit
, field_path
);
2664 if (!length_field
) {
2665 BT_LOGW("Cannot resolve sequence field type's length field path: "
2666 "notit-addr=%p, ft-addr=%p",
2671 iret
= bt_field_integer_unsigned_get_value(length_field
, &length
);
2673 BT_LOGE("Cannot get value of sequence length field: "
2674 "notit-addr=%p, field-addr=%p",
2675 notit
, length_field
);
2679 seq_field
= stack_top(notit
->stack
)->base
;
2680 iret
= bt_field_sequence_set_length(seq_field
, length
);
2682 BT_LOGE("Cannot set sequence field's length field: "
2683 "notit-addr=%p, seq-field-addr=%p, "
2685 notit
, seq_field
, length
);
2689 ret
= (int64_t) length
;
2696 struct bt_field_type
*btr_borrow_variant_field_type_cb(
2697 struct bt_field_type
*type
, void *data
)
2700 struct bt_field_path
*path
;
2701 struct bt_notif_iter
*notit
= data
;
2702 struct bt_field
*var_field
;
2703 struct bt_field
*tag_field
= NULL
;
2704 struct bt_field_type
*tag_ft
= NULL
;
2705 struct bt_field_type
*tag_int_ft
= NULL
;
2706 struct bt_field
*selected_field
= NULL
;
2707 struct bt_field_type
*selected_field_type
= NULL
;
2709 path
= bt_field_type_variant_borrow_tag_field_path(type
);
2711 tag_field
= resolve_field(notit
, path
);
2713 BT_LOGW("Cannot resolve variant field type's tag field path: "
2714 "notit-addr=%p, ft-addr=%p",
2720 * We found the enumeration tag field instance which should be
2721 * able to select a current field for this variant. This
2722 * callback function we're in is called _after_
2723 * compound_begin(), so the current stack top's base field is
2724 * the variant field in question. We set the variant field's tag
2725 * here and then get the current (selected) field thanks to this
2726 * tag field's value. This current field will also provide us
2727 * with its type. Then, this current field will remain the
2728 * current selected one until the next callback function call
2729 * which is used to fill it.
2731 var_field
= stack_top(notit
->stack
)->base
;
2732 tag_ft
= bt_field_borrow_type(tag_field
);
2733 tag_int_ft
= bt_field_type_enumeration_borrow_container_field_type(
2736 if (bt_field_type_integer_is_signed(tag_int_ft
)) {
2739 ret
= bt_field_integer_signed_get_value(tag_field
, &tag_value
);
2740 BT_ASSERT(ret
== 0);
2741 ret
= bt_field_variant_set_tag_signed(var_field
, tag_value
);
2742 BT_ASSERT(ret
== 0);
2746 ret
= bt_field_integer_unsigned_get_value(tag_field
,
2748 BT_ASSERT(ret
== 0);
2749 ret
= bt_field_variant_set_tag_unsigned(var_field
, tag_value
);
2750 BT_ASSERT(ret
== 0);
2753 selected_field
= bt_field_variant_borrow_current_field(var_field
);
2754 if (!selected_field
) {
2755 BT_LOGW("Cannot borrow variant field's current field: "
2756 "notit-addr=%p, var-field-addr=%p",
2761 selected_field_type
= bt_field_borrow_type(selected_field
);
2764 return selected_field_type
;
2768 int set_event_clocks(struct bt_notif_iter
*notit
)
2771 GHashTableIter iter
;
2772 struct bt_clock_class
*clock_class
;
2773 uint64_t *clock_state
;
2775 g_hash_table_iter_init(&iter
, notit
->clock_states
);
2777 while (g_hash_table_iter_next(&iter
, (gpointer
) &clock_class
,
2778 (gpointer
) &clock_state
)) {
2779 ret
= bt_event_set_clock_value(notit
->event
, clock_class
,
2780 *clock_state
, BT_TRUE
);
2782 BT_LOGE("Cannot set event's default clock value: "
2783 "notit-addr=%p, clock-class-addr=%p, "
2784 "clock-class-name=\"%s\"",
2786 bt_clock_class_get_name(clock_class
));
2799 void notify_new_stream(struct bt_notif_iter
*notit
,
2800 struct bt_notification
**notification
)
2802 enum bt_notif_iter_status status
;
2803 struct bt_notification
*ret
= NULL
;
2805 status
= set_current_stream(notit
);
2806 if (status
!= BT_NOTIF_ITER_STATUS_OK
) {
2811 BT_ASSERT(notit
->stream
);
2812 BT_ASSERT(notit
->notif_iter
);
2813 ret
= bt_notification_stream_begin_create(notit
->notif_iter
,
2816 BT_LOGE("Cannot create stream beginning notification: "
2817 "notit-addr=%p, stream-addr=%p",
2818 notit
, notit
->stream
);
2823 *notification
= ret
;
2827 void notify_end_of_stream(struct bt_notif_iter
*notit
,
2828 struct bt_notification
**notification
)
2830 struct bt_notification
*ret
;
2832 if (!notit
->stream
) {
2833 BT_LOGE("Cannot create stream for stream notification: "
2834 "notit-addr=%p", notit
);
2838 BT_ASSERT(notit
->notif_iter
);
2839 ret
= bt_notification_stream_end_create(notit
->notif_iter
,
2842 BT_LOGE("Cannot create stream beginning notification: "
2843 "notit-addr=%p, stream-addr=%p",
2844 notit
, notit
->stream
);
2847 *notification
= ret
;
2851 void notify_new_packet(struct bt_notif_iter
*notit
,
2852 struct bt_notification
**notification
)
2855 enum bt_notif_iter_status status
;
2856 struct bt_notification
*notif
= NULL
;
2858 status
= set_current_packet(notit
);
2859 if (status
!= BT_NOTIF_ITER_STATUS_OK
) {
2863 BT_ASSERT(notit
->packet
);
2865 if (notit
->packet_header_field
) {
2866 ret
= bt_packet_move_header(notit
->packet
,
2867 notit
->packet_header_field
);
2872 notit
->packet_header_field
= NULL
;
2875 * At this point notit->dscopes.trace_packet_header has
2876 * the same value as the packet header field within
2879 BT_ASSERT(bt_packet_borrow_header(notit
->packet
) ==
2880 notit
->dscopes
.trace_packet_header
);
2883 if (notit
->packet_context_field
) {
2884 ret
= bt_packet_move_context(notit
->packet
,
2885 notit
->packet_context_field
);
2890 notit
->packet_context_field
= NULL
;
2893 * At this point notit->dscopes.trace_packet_header has
2894 * the same value as the packet header field within
2897 BT_ASSERT(bt_packet_borrow_context(notit
->packet
) ==
2898 notit
->dscopes
.stream_packet_context
);
2901 BT_ASSERT(notit
->notif_iter
);
2902 notif
= bt_notification_packet_begin_create(notit
->notif_iter
,
2905 BT_LOGE("Cannot create packet beginning notification: "
2906 "notit-addr=%p, packet-addr=%p",
2907 notit
, notit
->packet
);
2911 *notification
= notif
;
2918 void notify_end_of_packet(struct bt_notif_iter
*notit
,
2919 struct bt_notification
**notification
)
2921 struct bt_notification
*notif
;
2923 if (!notit
->packet
) {
2927 BT_ASSERT(notit
->notif_iter
);
2928 notif
= bt_notification_packet_end_create(notit
->notif_iter
,
2931 BT_LOGE("Cannot create packet end notification: "
2932 "notit-addr=%p, packet-addr=%p",
2933 notit
, notit
->packet
);
2938 BT_MOVE(notit
->prev_packet
, notit
->packet
);
2939 notit
->prev_packet_avail
=
2940 BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_AVAILABLE
;
2941 *notification
= notif
;
2945 void init_trace_field_path_cache(struct bt_trace
*trace
,
2946 struct trace_field_path_cache
*trace_field_path_cache
)
2949 int stream_instance_id
= -1;
2951 struct bt_field_type
*packet_header
= NULL
;
2953 packet_header
= bt_trace_borrow_packet_header_field_type(trace
);
2954 if (!packet_header
) {
2958 if (!bt_field_type_is_structure(packet_header
)) {
2962 count
= bt_field_type_structure_get_field_count(packet_header
);
2963 BT_ASSERT(count
>= 0);
2965 for (i
= 0; (i
< count
&& (stream_id
== -1 || stream_instance_id
== -1)); i
++) {
2967 const char *field_name
;
2969 ret
= bt_field_type_structure_borrow_field_by_index(
2970 packet_header
, &field_name
, NULL
, i
);
2972 BT_LOGE("Cannot get structure field's field: "
2973 "field-addr=%p, index=%d",
2978 if (stream_id
== -1 && !strcmp(field_name
, "stream_id")) {
2980 } else if (stream_instance_id
== -1 &&
2981 !strcmp(field_name
, "stream_instance_id")) {
2982 stream_instance_id
= i
;
2987 trace_field_path_cache
->stream_id
= stream_id
;
2988 trace_field_path_cache
->stream_instance_id
= stream_instance_id
;
2992 struct bt_notif_iter
*bt_notif_iter_create(struct bt_trace
*trace
,
2993 size_t max_request_sz
,
2994 struct bt_notif_iter_medium_ops medops
, void *data
)
2996 struct bt_notif_iter
*notit
= NULL
;
2997 struct bt_btr_cbs cbs
= {
2999 .signed_int
= btr_signed_int_cb
,
3000 .unsigned_int
= btr_unsigned_int_cb
,
3001 .floating_point
= btr_floating_point_cb
,
3002 .string_begin
= btr_string_begin_cb
,
3003 .string
= btr_string_cb
,
3004 .string_end
= btr_string_end_cb
,
3005 .compound_begin
= btr_compound_begin_cb
,
3006 .compound_end
= btr_compound_end_cb
,
3009 .get_sequence_length
= btr_get_sequence_length_cb
,
3010 .borrow_variant_field_type
= btr_borrow_variant_field_type_cb
,
3015 BT_ASSERT(medops
.request_bytes
);
3016 BT_ASSERT(medops
.borrow_stream
);
3017 BT_LOGD("Creating CTF plugin notification iterator: "
3018 "trace-addr=%p, trace-name=\"%s\", max-request-size=%zu, "
3020 trace
, bt_trace_get_name(trace
), max_request_sz
, data
);
3021 notit
= g_new0(struct bt_notif_iter
, 1);
3023 BT_LOGE_STR("Failed to allocate one CTF plugin notification iterator.");
3026 notit
->clock_states
= g_hash_table_new_full(g_direct_hash
,
3027 g_direct_equal
, NULL
, g_free
);
3028 if (!notit
->clock_states
) {
3029 BT_LOGE_STR("Failed to allocate a GHashTable.");
3032 notit
->meta
.trace
= trace
;
3033 notit
->medium
.medops
= medops
;
3034 notit
->medium
.max_request_sz
= max_request_sz
;
3035 notit
->medium
.data
= data
;
3036 notit
->stack
= stack_new(notit
);
3037 if (!notit
->stack
) {
3038 BT_LOGE_STR("Failed to create field stack.");
3042 notit
->btr
= bt_btr_create(cbs
, notit
);
3044 BT_LOGE_STR("Failed to create binary type reader (BTR).");
3048 bt_notif_iter_reset(notit
);
3049 init_trace_field_path_cache(trace
, ¬it
->trace_field_path_cache
);
3050 notit
->sc_field_path_caches
= g_hash_table_new_full(g_direct_hash
,
3051 g_direct_equal
, NULL
, g_free
);
3052 if (!notit
->sc_field_path_caches
) {
3053 BT_LOGE_STR("Failed to allocate a GHashTable.");
3057 notit
->field_overrides
= g_hash_table_new_full(g_direct_hash
,
3058 g_direct_equal
, NULL
, g_free
);
3059 if (!notit
->field_overrides
) {
3060 BT_LOGE_STR("Failed to allocate a GHashTable.");
3064 BT_LOGD("Created CTF plugin notification iterator: "
3065 "trace-addr=%p, trace-name=\"%s\", max-request-size=%zu, "
3066 "data=%p, notit-addr=%p",
3067 trace
, bt_trace_get_name(trace
), max_request_sz
, data
,
3069 notit
->cur_packet_offset
= 0;
3075 bt_notif_iter_destroy(notit
);
3080 void bt_notif_iter_destroy(struct bt_notif_iter
*notit
)
3082 BT_PUT(notit
->packet
);
3083 BT_PUT(notit
->prev_packet
);
3084 BT_PUT(notit
->stream
);
3085 release_all_dscopes(notit
);
3087 BT_LOGD("Destroying CTF plugin notification iterator: addr=%p", notit
);
3090 BT_LOGD_STR("Destroying field stack.");
3091 stack_destroy(notit
->stack
);
3095 BT_LOGD("Destroying BTR: btr-addr=%p", notit
->btr
);
3096 bt_btr_destroy(notit
->btr
);
3099 if (notit
->clock_states
) {
3100 g_hash_table_destroy(notit
->clock_states
);
3103 if (notit
->sc_field_path_caches
) {
3104 g_hash_table_destroy(notit
->sc_field_path_caches
);
3107 if (notit
->field_overrides
) {
3108 g_hash_table_destroy(notit
->field_overrides
);
3114 enum bt_notif_iter_status
bt_notif_iter_get_next_notification(
3115 struct bt_notif_iter
*notit
,
3116 struct bt_private_connection_private_notification_iterator
*notif_iter
,
3117 struct bt_notification
**notification
)
3120 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
3123 BT_ASSERT(notification
);
3125 if (notit
->state
== STATE_DONE
) {
3126 status
= BT_NOTIF_ITER_STATUS_EOF
;
3130 notit
->notif_iter
= notif_iter
;
3132 BT_LOGV("Getting next notification: notit-addr=%p", notit
);
3135 status
= handle_state(notit
);
3136 if (status
== BT_NOTIF_ITER_STATUS_AGAIN
) {
3137 BT_LOGV_STR("Medium returned BT_NOTIF_ITER_STATUS_AGAIN.");
3141 if (status
!= BT_NOTIF_ITER_STATUS_OK
) {
3142 if (status
== BT_NOTIF_ITER_STATUS_EOF
) {
3143 enum state next_state
= notit
->state
;
3145 BT_LOGV_STR("Medium returned BT_NOTIF_ITER_STATUS_EOF.");
3147 if (notit
->packet
) {
3148 notify_end_of_packet(notit
,
3151 notify_end_of_stream(notit
,
3153 next_state
= STATE_DONE
;
3156 if (!*notification
) {
3157 status
= BT_NOTIF_ITER_STATUS_ERROR
;
3161 status
= BT_NOTIF_ITER_STATUS_OK
;
3162 notit
->state
= next_state
;
3164 BT_LOGW("Cannot handle state: "
3165 "notit-addr=%p, state=%s",
3166 notit
, state_string(notit
->state
));
3172 switch (notit
->state
) {
3173 case STATE_EMIT_NOTIF_NEW_STREAM
:
3174 /* notify_new_stream() logs errors */
3175 notify_new_stream(notit
, notification
);
3176 if (!*notification
) {
3177 status
= BT_NOTIF_ITER_STATUS_ERROR
;
3179 notit
->stream_begin_emitted
= true;
3181 case STATE_EMIT_NOTIF_NEW_PACKET
:
3182 /* notify_new_packet() logs errors */
3183 notify_new_packet(notit
, notification
);
3184 if (!*notification
) {
3185 status
= BT_NOTIF_ITER_STATUS_ERROR
;
3189 case STATE_EMIT_NOTIF_EVENT
:
3190 BT_ASSERT(notit
->event_notif
);
3191 ret
= set_event_clocks(notit
);
3193 status
= BT_NOTIF_ITER_STATUS_ERROR
;
3197 *notification
= notit
->event_notif
;
3198 notit
->event_notif
= NULL
;
3200 case STATE_EMIT_NOTIF_END_OF_PACKET
:
3201 /* Update clock with timestamp_end field. */
3202 if (notit
->cur_timestamp_end
) {
3203 enum bt_btr_status btr_status
;
3205 btr_status
= update_clock(notit
,
3206 notit
->cur_timestamp_end
);
3207 if (btr_status
!= BT_BTR_STATUS_OK
) {
3208 BT_LOGW("Cannot update stream's clock value: "
3209 "notit-addr=%p", notit
);
3210 status
= BT_NOTIF_ITER_STATUS_ERROR
;
3215 /* notify_end_of_packet() logs errors */
3216 notify_end_of_packet(notit
, notification
);
3217 if (!*notification
) {
3218 status
= BT_NOTIF_ITER_STATUS_ERROR
;
3223 /* Non-emitting state: continue */
3233 enum bt_notif_iter_status
bt_notif_iter_borrow_packet_header_context_fields(
3234 struct bt_notif_iter
*notit
,
3235 struct bt_field
**packet_header_field
,
3236 struct bt_field
**packet_context_field
)
3239 enum bt_notif_iter_status status
= BT_NOTIF_ITER_STATUS_OK
;
3243 if (notit
->state
== STATE_EMIT_NOTIF_NEW_PACKET
) {
3244 /* We're already there */
3249 status
= handle_state(notit
);
3250 if (status
== BT_NOTIF_ITER_STATUS_AGAIN
) {
3251 BT_LOGV_STR("Medium returned BT_NOTIF_ITER_STATUS_AGAIN.");
3254 if (status
!= BT_NOTIF_ITER_STATUS_OK
) {
3255 if (status
== BT_NOTIF_ITER_STATUS_EOF
) {
3256 BT_LOGV_STR("Medium returned BT_NOTIF_ITER_STATUS_EOF.");
3258 BT_LOGW("Cannot handle state: "
3259 "notit-addr=%p, state=%s",
3260 notit
, state_string(notit
->state
));
3265 switch (notit
->state
) {
3266 case STATE_EMIT_NOTIF_NEW_PACKET
:
3268 * Packet header and context fields are
3269 * potentially decoded (or they don't exist).
3273 case STATE_EMIT_NOTIF_NEW_STREAM
:
3274 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
:
3275 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
:
3276 case STATE_AFTER_TRACE_PACKET_HEADER
:
3277 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
:
3278 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
:
3279 case STATE_AFTER_STREAM_PACKET_CONTEXT
:
3280 /* Non-emitting state: continue */
3284 * We should never get past the
3285 * STATE_EMIT_NOTIF_NEW_PACKET state.
3287 BT_LOGF("Unexpected state: notit-addr=%p, state=%s",
3288 notit
, state_string(notit
->state
));
3294 ret
= set_current_packet_content_sizes(notit
);
3296 status
= BT_NOTIF_ITER_STATUS_ERROR
;
3300 if (packet_header_field
) {
3301 *packet_header_field
= notit
->dscopes
.trace_packet_header
;
3304 if (packet_context_field
) {
3305 *packet_context_field
= notit
->dscopes
.stream_packet_context
;
3313 void bt_notif_iter_set_medops_data(struct bt_notif_iter
*notit
,
3317 notit
->medium
.data
= medops_data
;
3321 enum bt_notif_iter_status
bt_notif_iter_seek(
3322 struct bt_notif_iter
*notit
, off_t offset
)
3324 enum bt_notif_iter_status ret
= BT_NOTIF_ITER_STATUS_OK
;
3325 enum bt_notif_iter_medium_status medium_status
;
3329 BT_LOGE("Cannot seek to negative offset: offset=%jd", offset
);
3330 ret
= BT_NOTIF_ITER_STATUS_INVAL
;
3334 if (!notit
->medium
.medops
.seek
) {
3335 ret
= BT_NOTIF_ITER_STATUS_UNSUPPORTED
;
3336 BT_LOGD("Aborting seek as the iterator's underlying media does not implement seek support.");
3340 medium_status
= notit
->medium
.medops
.seek(
3341 BT_NOTIF_ITER_SEEK_WHENCE_SET
, offset
,
3342 notit
->medium
.data
);
3343 if (medium_status
!= BT_NOTIF_ITER_MEDIUM_STATUS_OK
) {
3344 if (medium_status
== BT_NOTIF_ITER_MEDIUM_STATUS_EOF
) {
3345 ret
= BT_NOTIF_ITER_STATUS_EOF
;
3347 ret
= BT_NOTIF_ITER_STATUS_ERROR
;
3352 bt_notif_iter_reset(notit
);
3353 notit
->cur_packet_offset
= offset
;
3359 off_t
bt_notif_iter_get_current_packet_offset(
3360 struct bt_notif_iter
*notit
)
3363 return notit
->cur_packet_offset
;
3367 off_t
bt_notif_iter_get_current_packet_size(
3368 struct bt_notif_iter
*notit
)
3371 return notit
->cur_packet_size
;