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"
36 #include <babeltrace/ctf-ir/field-types.h>
37 #include <babeltrace/ctf-ir/field-types-internal.h>
38 #include <babeltrace/ctf-ir/field-path.h>
39 #include <babeltrace/ctf-ir/field-path-internal.h>
40 #include <babeltrace/ctf-ir/fields.h>
41 #include <babeltrace/ctf-ir/stream-class.h>
42 #include <babeltrace/ctf-ir/packet.h>
43 #include <babeltrace/ctf-ir/stream.h>
44 #include <babeltrace/ctf-ir/clock-class.h>
45 #include <babeltrace/ctf-ir/event-class.h>
46 #include <babeltrace/graph/notification-packet.h>
47 #include <babeltrace/graph/notification-event.h>
48 #include <babeltrace/graph/notification-stream.h>
49 #include <babeltrace/graph/clock-class-priority-map.h>
50 #include <babeltrace/ref.h>
54 #include "notif-iter.h"
55 #include "../btr/btr.h"
57 struct bt_ctf_notif_iter
;
59 /* A visit stack entry */
62 * Current base field, one of:
70 * Field is owned by this.
72 struct bt_ctf_field
*base
;
74 /* index of next field to set */
80 /* Entries (struct stack_entry *) (top is last element) */
87 STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
,
88 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
,
89 STATE_AFTER_TRACE_PACKET_HEADER
,
90 STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
,
91 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
,
92 STATE_AFTER_STREAM_PACKET_CONTEXT
,
93 STATE_EMIT_NOTIF_NEW_PACKET
,
94 STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN
,
95 STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE
,
96 STATE_AFTER_STREAM_EVENT_HEADER
,
97 STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN
,
98 STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE
,
99 STATE_DSCOPE_EVENT_CONTEXT_BEGIN
,
100 STATE_DSCOPE_EVENT_CONTEXT_CONTINUE
,
101 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
,
102 STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
,
103 STATE_EMIT_NOTIF_EVENT
,
104 STATE_EMIT_NOTIF_END_OF_PACKET
,
105 STATE_SKIP_PACKET_PADDING
,
108 struct trace_field_path_cache
{
110 * Indexes of the stream_id and stream_instance_id field in the packet
111 * header structure, -1 if unset.
114 int stream_instance_id
;
117 struct stream_class_field_path_cache
{
119 * Indexes of the v and id fields in the stream event header structure,
126 * index of the timestamp_end, packet_size and content_size fields in
127 * the stream packet context structure. Set to -1 if the fields were
135 struct field_cb_override
{
136 enum bt_ctf_btr_status (* func
)(void *value
,
137 struct bt_ctf_field_type
*type
, void *data
);
141 /* CTF notification iterator */
142 struct bt_ctf_notif_iter
{
147 * Current dynamic scope field pointer.
149 * This is set when a dynamic scope field is first created by
150 * btr_compound_begin_cb(). It points to one of the fields in
153 struct bt_ctf_field
**cur_dscope_field
;
155 /* Trace and classes (owned by this) */
157 struct bt_ctf_trace
*trace
;
158 struct bt_ctf_stream_class
*stream_class
;
159 struct bt_ctf_event_class
*event_class
;
162 /* Current packet (NULL if not created yet) */
163 struct bt_ctf_packet
*packet
;
166 * Current timestamp_end field (to consider before switching packets).
168 struct bt_ctf_field
*cur_timestamp_end
;
170 /* Database of current dynamic scopes (owned by this) */
172 struct bt_ctf_field
*trace_packet_header
;
173 struct bt_ctf_field
*stream_packet_context
;
174 struct bt_ctf_field
*stream_event_header
;
175 struct bt_ctf_field
*stream_event_context
;
176 struct bt_ctf_field
*event_context
;
177 struct bt_ctf_field
*event_payload
;
181 * Special field overrides.
183 * Overrides are used to implement the behaviours of special fields such
184 * as "timestamp_end" (which must be ignored until the end of the
185 * packet), "id" (event id) which can be present multiple times and must
186 * be updated multiple time.
188 * This should be used to implement the behaviour of integer fields
189 * mapped to clocks and other "tagged" fields (in CTF 2).
191 * bt_ctf_field_type to struct field_cb_override
193 GHashTable
*field_overrides
;
198 /* Current medium buffer data */
200 /* Last address provided by medium */
203 /* Buffer size provided by medium (bytes) */
206 /* Offset within whole packet of addr (bits) */
207 size_t packet_offset
;
209 /* Current position from addr (bits) */
213 /* Binary type reader */
214 struct bt_ctf_btr
*btr
;
216 /* Current medium data */
218 struct bt_ctf_notif_iter_medium_ops medops
;
219 size_t max_request_sz
;
223 /* Current packet size (bits) (-1 if unknown) */
224 int64_t cur_packet_size
;
226 /* Current content size (bits) (-1 if unknown) */
227 int64_t cur_content_size
;
229 /* bt_ctf_clock_class to uint64_t. */
230 GHashTable
*clock_states
;
233 * Cache of the trace-constant field paths (event header type)
234 * associated to the current trace.
236 struct trace_field_path_cache trace_field_path_cache
;
239 * Field path cache associated with the current stream class.
240 * Ownership of this structure belongs to the field_path_caches HT.
242 struct stream_class_field_path_cache
*cur_sc_field_path_cache
;
244 /* bt_ctf_stream_class to struct stream_class_field_path_cache. */
245 GHashTable
*sc_field_path_caches
;
249 const char *state_string(enum state state
)
254 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
:
255 return "STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN";
256 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
:
257 return "STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE";
258 case STATE_AFTER_TRACE_PACKET_HEADER
:
259 return "STATE_AFTER_TRACE_PACKET_HEADER";
260 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
:
261 return "STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN";
262 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
:
263 return "STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE";
264 case STATE_AFTER_STREAM_PACKET_CONTEXT
:
265 return "STATE_AFTER_STREAM_PACKET_CONTEXT";
266 case STATE_EMIT_NOTIF_NEW_PACKET
:
267 return "STATE_EMIT_NOTIF_NEW_PACKET";
268 case STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN
:
269 return "STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN";
270 case STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE
:
271 return "STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE";
272 case STATE_AFTER_STREAM_EVENT_HEADER
:
273 return "STATE_AFTER_STREAM_EVENT_HEADER";
274 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN
:
275 return "STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN";
276 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE
:
277 return "STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE";
278 case STATE_DSCOPE_EVENT_CONTEXT_BEGIN
:
279 return "STATE_DSCOPE_EVENT_CONTEXT_BEGIN";
280 case STATE_DSCOPE_EVENT_CONTEXT_CONTINUE
:
281 return "STATE_DSCOPE_EVENT_CONTEXT_CONTINUE";
282 case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
:
283 return "STATE_DSCOPE_EVENT_PAYLOAD_BEGIN";
284 case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
:
285 return "STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE";
286 case STATE_EMIT_NOTIF_EVENT
:
287 return "STATE_EMIT_NOTIF_EVENT";
288 case STATE_EMIT_NOTIF_END_OF_PACKET
:
289 return "STATE_EMIT_NOTIF_END_OF_PACKET";
290 case STATE_SKIP_PACKET_PADDING
:
291 return "STATE_SKIP_PACKET_PADDING";
298 int bt_ctf_notif_iter_switch_packet(struct bt_ctf_notif_iter
*notit
);
301 enum bt_ctf_btr_status
btr_timestamp_end_cb(void *value
,
302 struct bt_ctf_field_type
*type
, void *data
);
305 void stack_entry_free_func(gpointer data
)
307 struct stack_entry
*entry
= data
;
314 struct stack
*stack_new(struct bt_ctf_notif_iter
*notit
)
316 struct stack
*stack
= NULL
;
318 stack
= g_new0(struct stack
, 1);
320 BT_LOGE_STR("Failed to allocate one stack.");
324 stack
->entries
= g_ptr_array_new_with_free_func(stack_entry_free_func
);
325 if (!stack
->entries
) {
326 BT_LOGE_STR("Failed to allocate a GPtrArray.");
330 BT_LOGD("Created stack: notit-addr=%p, stack-addr=%p", notit
, stack
);
339 void stack_destroy(struct stack
*stack
)
342 BT_LOGD("Destroying stack: addr=%p", stack
);
343 g_ptr_array_free(stack
->entries
, TRUE
);
348 int stack_push(struct stack
*stack
, struct bt_ctf_field
*base
)
351 struct stack_entry
*entry
;
355 BT_LOGV("Pushing base field on stack: stack-addr=%p, "
356 "stack-size-before=%u, stack-size-after=%u",
357 stack
, stack
->entries
->len
, stack
->entries
->len
+ 1);
358 entry
= g_new0(struct stack_entry
, 1);
360 BT_LOGE_STR("Failed to allocate one stack entry.");
365 entry
->base
= bt_get(base
);
366 g_ptr_array_add(stack
->entries
, entry
);
373 unsigned int stack_size(struct stack
*stack
)
377 return stack
->entries
->len
;
381 void stack_pop(struct stack
*stack
)
384 assert(stack_size(stack
));
385 BT_LOGV("Popping from stack: "
386 "stack-addr=%p, stack-size-before=%u, stack-size-after=%u",
387 stack
, stack
->entries
->len
, stack
->entries
->len
- 1);
388 g_ptr_array_remove_index(stack
->entries
, stack
->entries
->len
- 1);
392 struct stack_entry
*stack_top(struct stack
*stack
)
395 assert(stack_size(stack
));
397 return g_ptr_array_index(stack
->entries
, stack
->entries
->len
- 1);
401 bool stack_empty(struct stack
*stack
)
403 return stack_size(stack
) == 0;
407 void stack_clear(struct stack
*stack
)
411 if (!stack_empty(stack
)) {
412 BT_LOGV("Clearing stack: stack-addr=%p, stack-size=%u",
413 stack
, stack
->entries
->len
);
414 g_ptr_array_remove_range(stack
->entries
, 0, stack_size(stack
));
417 assert(stack_empty(stack
));
421 enum bt_ctf_notif_iter_status
notif_iter_status_from_m_status(
422 enum bt_ctf_notif_iter_medium_status m_status
)
424 return (int) m_status
;
428 size_t buf_size_bits(struct bt_ctf_notif_iter
*notit
)
430 return notit
->buf
.sz
* 8;
434 size_t buf_available_bits(struct bt_ctf_notif_iter
*notit
)
436 return buf_size_bits(notit
) - notit
->buf
.at
;
440 size_t packet_at(struct bt_ctf_notif_iter
*notit
)
442 return notit
->buf
.packet_offset
+ notit
->buf
.at
;
446 void buf_consume_bits(struct bt_ctf_notif_iter
*notit
, size_t incr
)
448 BT_LOGV("Advancing cursor: notit-addr=%p, cur-before=%zu, cur-after=%zu",
449 notit
, notit
->buf
.at
, notit
->buf
.at
+ incr
);
450 notit
->buf
.at
+= incr
;
454 enum bt_ctf_notif_iter_status
request_medium_bytes(
455 struct bt_ctf_notif_iter
*notit
)
457 uint8_t *buffer_addr
= NULL
;
458 size_t buffer_sz
= 0;
459 enum bt_ctf_notif_iter_medium_status m_status
;
461 BT_LOGV("Calling user function (request bytes): notit-addr=%p, "
462 "request-size=%zu", notit
, notit
->medium
.max_request_sz
);
463 m_status
= notit
->medium
.medops
.request_bytes(
464 notit
->medium
.max_request_sz
, &buffer_addr
,
465 &buffer_sz
, notit
->medium
.data
);
466 BT_LOGV("User function returned: status=%s, buf-addr=%p, buf-size=%zu",
467 bt_ctf_notif_iter_medium_status_string(m_status
),
468 buffer_addr
, buffer_sz
);
469 if (m_status
== BT_CTF_NOTIF_ITER_MEDIUM_STATUS_OK
) {
470 assert(buffer_sz
!= 0);
472 /* New packet offset is old one + old size (in bits) */
473 notit
->buf
.packet_offset
+= buf_size_bits(notit
);
475 /* Restart at the beginning of the new medium buffer */
478 /* New medium buffer size */
479 notit
->buf
.sz
= buffer_sz
;
481 /* New medium buffer address */
482 notit
->buf
.addr
= buffer_addr
;
484 BT_LOGV("User function returned new bytes: "
485 "packet-offset=%zu, cur=%zu, size=%zu, addr=%p",
486 notit
->buf
.packet_offset
, notit
->buf
.at
,
487 notit
->buf
.sz
, notit
->buf
.addr
);
488 BT_LOGV_MEM(buffer_addr
, buffer_sz
, "Returned bytes at %p:",
490 } else if (m_status
< 0) {
491 BT_LOGW("User function failed: status=%s",
492 bt_ctf_notif_iter_medium_status_string(m_status
));
495 return notif_iter_status_from_m_status(m_status
);
499 enum bt_ctf_notif_iter_status
buf_ensure_available_bits(
500 struct bt_ctf_notif_iter
*notit
)
502 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
504 if (buf_available_bits(notit
) == 0) {
506 * This _cannot_ return BT_CTF_NOTIF_ITER_STATUS_OK
509 status
= request_medium_bytes(notit
);
516 enum bt_ctf_notif_iter_status
read_dscope_begin_state(
517 struct bt_ctf_notif_iter
*notit
,
518 struct bt_ctf_field_type
*dscope_field_type
,
519 enum state done_state
, enum state continue_state
,
520 struct bt_ctf_field
**dscope_field
)
522 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
523 enum bt_ctf_btr_status btr_status
;
524 size_t consumed_bits
;
526 status
= buf_ensure_available_bits(notit
);
527 if (status
!= BT_CTF_NOTIF_ITER_STATUS_OK
) {
529 BT_LOGW("Cannot ensure that buffer has at least one byte: "
530 "notif-addr=%p, status=%s",
531 notit
, bt_ctf_notif_iter_status_string(status
));
533 BT_LOGV("Cannot ensure that buffer has at least one byte: "
534 "notif-addr=%p, status=%s",
535 notit
, bt_ctf_notif_iter_status_string(status
));
541 bt_put(*dscope_field
);
542 notit
->cur_dscope_field
= dscope_field
;
543 BT_LOGV("Starting BTR: notit-addr=%p, btr-addr=%p, ft-addr=%p",
544 notit
, notit
->btr
, dscope_field_type
);
545 consumed_bits
= bt_ctf_btr_start(notit
->btr
, dscope_field_type
,
546 notit
->buf
.addr
, notit
->buf
.at
, packet_at(notit
),
547 notit
->buf
.sz
, &btr_status
);
548 BT_LOGV("BTR consumed bits: size=%zu", consumed_bits
);
550 switch (btr_status
) {
551 case BT_CTF_BTR_STATUS_OK
:
552 /* type was read completely */
553 BT_LOGV_STR("Field was completely decoded.");
554 notit
->state
= done_state
;
556 case BT_CTF_BTR_STATUS_EOF
:
557 BT_LOGV_STR("BTR needs more data to decode field completely.");
558 notit
->state
= continue_state
;
561 BT_LOGW("BTR failed to start: notit-addr=%p, btr-addr=%p, "
562 "status=%s", notit
, notit
->btr
,
563 bt_ctf_btr_status_string(btr_status
));
564 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
568 /* Consume bits now since we know we're not in an error state */
569 buf_consume_bits(notit
, consumed_bits
);
576 enum bt_ctf_notif_iter_status
read_dscope_continue_state(
577 struct bt_ctf_notif_iter
*notit
, enum state done_state
)
579 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
580 enum bt_ctf_btr_status btr_status
;
581 size_t consumed_bits
;
583 status
= buf_ensure_available_bits(notit
);
584 if (status
!= BT_CTF_NOTIF_ITER_STATUS_OK
) {
586 BT_LOGW("Cannot ensure that buffer has at least one byte: "
587 "notif-addr=%p, status=%s",
588 notit
, bt_ctf_notif_iter_status_string(status
));
590 BT_LOGV("Cannot ensure that buffer has at least one byte: "
591 "notif-addr=%p, status=%s",
592 notit
, bt_ctf_notif_iter_status_string(status
));
598 BT_LOGV("Continuing BTR: notit-addr=%p, btr-addr=%p",
600 consumed_bits
= bt_ctf_btr_continue(notit
->btr
, notit
->buf
.addr
,
601 notit
->buf
.sz
, &btr_status
);
602 BT_LOGV("BTR consumed bits: size=%zu", consumed_bits
);
604 switch (btr_status
) {
605 case BT_CTF_BTR_STATUS_OK
:
606 /* Type was read completely. */
607 BT_LOGV_STR("Field was completely decoded.");
608 notit
->state
= done_state
;
610 case BT_CTF_BTR_STATUS_EOF
:
611 /* Stay in this continue state. */
612 BT_LOGV_STR("BTR needs more data to decode field completely.");
615 BT_LOGW("BTR failed to continue: notit-addr=%p, btr-addr=%p, "
616 "status=%s", notit
, notit
->btr
,
617 bt_ctf_btr_status_string(btr_status
));
618 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
622 /* Consume bits now since we know we're not in an error state. */
623 buf_consume_bits(notit
, consumed_bits
);
629 void put_event_dscopes(struct bt_ctf_notif_iter
*notit
)
631 BT_LOGV_STR("Putting event header field.");
632 BT_PUT(notit
->dscopes
.stream_event_header
);
633 BT_LOGV_STR("Putting stream event context field.");
634 BT_PUT(notit
->dscopes
.stream_event_context
);
635 BT_LOGV_STR("Putting event context field.");
636 BT_PUT(notit
->dscopes
.event_context
);
637 BT_LOGV_STR("Putting event payload field.");
638 BT_PUT(notit
->dscopes
.event_payload
);
642 void put_all_dscopes(struct bt_ctf_notif_iter
*notit
)
644 BT_LOGV_STR("Putting packet header field.");
645 BT_PUT(notit
->dscopes
.trace_packet_header
);
646 BT_LOGV_STR("Putting packet context field.");
647 BT_PUT(notit
->dscopes
.stream_packet_context
);
648 put_event_dscopes(notit
);
652 enum bt_ctf_notif_iter_status
read_packet_header_begin_state(
653 struct bt_ctf_notif_iter
*notit
)
655 struct bt_ctf_field_type
*packet_header_type
= NULL
;
656 enum bt_ctf_notif_iter_status ret
= BT_CTF_NOTIF_ITER_STATUS_OK
;
658 if (bt_ctf_notif_iter_switch_packet(notit
)) {
659 BT_LOGW("Cannot switch packet: notit-addr=%p", notit
);
660 ret
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
664 /* Packet header type is common to the whole trace. */
665 packet_header_type
= bt_ctf_trace_get_packet_header_type(
667 if (!packet_header_type
) {
668 notit
->state
= STATE_AFTER_TRACE_PACKET_HEADER
;
672 BT_LOGV("Decoding packet header field:"
673 "notit-addr=%p, trace-addr=%p, trace-name=\"%s\", ft-addr=%p",
674 notit
, notit
->meta
.trace
,
675 bt_ctf_trace_get_name(notit
->meta
.trace
), packet_header_type
);
676 ret
= read_dscope_begin_state(notit
, packet_header_type
,
677 STATE_AFTER_TRACE_PACKET_HEADER
,
678 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
,
679 ¬it
->dscopes
.trace_packet_header
);
681 BT_LOGW("Cannot decode packet header field: "
682 "notit-addr=%p, trace-addr=%p, "
683 "trace-name=\"%s\", ft-addr=%p",
684 notit
, notit
->meta
.trace
,
685 bt_ctf_trace_get_name(notit
->meta
.trace
),
689 BT_PUT(packet_header_type
);
694 enum bt_ctf_notif_iter_status
read_packet_header_continue_state(
695 struct bt_ctf_notif_iter
*notit
)
697 return read_dscope_continue_state(notit
,
698 STATE_AFTER_TRACE_PACKET_HEADER
);
702 bool is_struct_type(struct bt_ctf_field_type
*field_type
)
704 return bt_ctf_field_type_get_type_id(field_type
) ==
705 BT_CTF_FIELD_TYPE_ID_STRUCT
;
709 bool is_variant_type(struct bt_ctf_field_type
*field_type
)
711 return bt_ctf_field_type_get_type_id(field_type
) ==
712 BT_CTF_FIELD_TYPE_ID_VARIANT
;
716 struct stream_class_field_path_cache
*
717 create_stream_class_field_path_cache_entry(
718 struct bt_ctf_notif_iter
*notit
,
719 struct bt_ctf_stream_class
*stream_class
)
723 int timestamp_end
= -1;
724 int packet_size
= -1;
725 int content_size
= -1;
726 struct stream_class_field_path_cache
*cache_entry
= g_new0(
727 struct stream_class_field_path_cache
, 1);
728 struct bt_ctf_field_type
*event_header
= NULL
, *packet_context
= NULL
;
731 BT_LOGE_STR("Failed to allocate one stream class field path cache.");
735 event_header
= bt_ctf_stream_class_get_event_header_type(stream_class
);
736 if (event_header
&& bt_ctf_field_type_is_structure(event_header
)) {
739 count
= bt_ctf_field_type_structure_get_field_count(
743 for (i
= 0; i
< count
; i
++) {
747 ret
= bt_ctf_field_type_structure_get_field(
748 event_header
, &name
, NULL
, i
);
750 BT_LOGE("Cannot get event header structure field type's field: "
751 "notit-addr=%p, stream-class-addr=%p, "
752 "stream-class-name=\"%s\", "
753 "stream-class-id=%" PRId64
", "
754 "ft-addr=%p, index=%d",
756 bt_ctf_stream_class_get_name(stream_class
),
757 bt_ctf_stream_class_get_id(stream_class
),
762 if (v
!= -1 && id
!= -1) {
766 if (v
== -1 && strcmp(name
, "v") == 0) {
768 } else if (id
== -1 && !strcmp(name
, "id")) {
774 packet_context
= bt_ctf_stream_class_get_packet_context_type(
776 if (packet_context
&& bt_ctf_field_type_is_structure(packet_context
)) {
779 count
= bt_ctf_field_type_structure_get_field_count(
783 for (i
= 0; i
< count
; i
++) {
786 struct bt_ctf_field_type
*field_type
;
788 if (timestamp_end
!= -1 && packet_size
!= -1 &&
789 content_size
!= -1) {
793 ret
= bt_ctf_field_type_structure_get_field(
794 packet_context
, &name
, &field_type
, i
);
796 BT_LOGE("Cannot get packet context structure field type's field: "
797 "notit-addr=%p, stream-class-addr=%p, "
798 "stream-class-name=\"%s\", "
799 "stream-class-id=%" PRId64
", "
800 "ft-addr=%p, index=%d",
802 bt_ctf_stream_class_get_name(stream_class
),
803 bt_ctf_stream_class_get_id(stream_class
),
808 if (timestamp_end
== -1 &&
809 strcmp(name
, "timestamp_end") == 0) {
810 struct field_cb_override
*override
= g_new0(
811 struct field_cb_override
, 1);
818 override
->func
= btr_timestamp_end_cb
;
819 override
->data
= notit
;
820 g_hash_table_insert(notit
->field_overrides
,
821 bt_get(field_type
), override
);
823 } else if (packet_size
== -1 &&
824 !strcmp(name
, "packet_size")) {
826 } else if (content_size
== -1 &&
827 !strcmp(name
, "content_size")) {
835 cache_entry
->id
= id
;
836 cache_entry
->timestamp_end
= timestamp_end
;
837 cache_entry
->packet_size
= packet_size
;
838 cache_entry
->content_size
= content_size
;
840 BT_PUT(event_header
);
841 BT_PUT(packet_context
);
850 struct stream_class_field_path_cache
*get_stream_class_field_path_cache(
851 struct bt_ctf_notif_iter
*notit
,
852 struct bt_ctf_stream_class
*stream_class
)
854 bool cache_entry_found
;
855 struct stream_class_field_path_cache
*cache_entry
;
857 cache_entry_found
= g_hash_table_lookup_extended(
858 notit
->sc_field_path_caches
,
859 stream_class
, NULL
, (gpointer
) &cache_entry
);
860 if (unlikely(!cache_entry_found
)) {
861 cache_entry
= create_stream_class_field_path_cache_entry(notit
,
863 g_hash_table_insert(notit
->sc_field_path_caches
,
864 bt_get(stream_class
), (gpointer
) cache_entry
);
871 enum bt_ctf_notif_iter_status
set_current_stream_class(
872 struct bt_ctf_notif_iter
*notit
)
874 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
875 struct bt_ctf_field_type
*packet_header_type
= NULL
;
876 struct bt_ctf_field_type
*stream_id_field_type
= NULL
;
879 /* Clear the current stream class field path cache. */
880 notit
->cur_sc_field_path_cache
= NULL
;
882 /* Is there any "stream_id" field in the packet header? */
883 packet_header_type
= bt_ctf_trace_get_packet_header_type(
885 if (!packet_header_type
) {
887 * No packet header, therefore no `stream_id` field,
888 * therefore only one stream class.
890 goto single_stream_class
;
893 assert(is_struct_type(packet_header_type
));
896 stream_id_field_type
=
897 bt_ctf_field_type_structure_get_field_type_by_name(
898 packet_header_type
, "stream_id");
899 if (stream_id_field_type
) {
900 /* Find appropriate stream class using current stream ID */
902 struct bt_ctf_field
*stream_id_field
= NULL
;
904 assert(notit
->dscopes
.trace_packet_header
);
907 stream_id_field
= bt_ctf_field_structure_get_field(
908 notit
->dscopes
.trace_packet_header
, "stream_id");
909 assert(stream_id_field
);
910 ret
= bt_ctf_field_unsigned_integer_get_value(
911 stream_id_field
, &stream_id
);
913 BT_PUT(stream_id_field
);
916 /* Only one stream: pick the first stream class */
917 assert(bt_ctf_trace_get_stream_class_count(
918 notit
->meta
.trace
) == 1);
922 BT_LOGV("Found stream class ID to use: notit-addr=%p, "
923 "stream-class-id=%" PRIu64
", "
924 "trace-addr=%p, trace-name=\"%s\"",
925 notit
, stream_id
, notit
->meta
.trace
,
926 bt_ctf_trace_get_name(notit
->meta
.trace
));
928 BT_PUT(notit
->meta
.stream_class
);
929 notit
->meta
.stream_class
= bt_ctf_trace_get_stream_class_by_id(
930 notit
->meta
.trace
, stream_id
);
931 if (!notit
->meta
.stream_class
) {
932 BT_LOGW("No stream class with ID of stream class ID to use in trace: "
933 "notit-addr=%p, stream-class-id=%" PRIu64
", "
934 "trace-addr=%p, trace-name=\"%s\"",
935 notit
, stream_id
, notit
->meta
.trace
,
936 bt_ctf_trace_get_name(notit
->meta
.trace
));
937 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
941 BT_LOGV("Set current stream class: "
942 "notit-addr=%p, stream-class-addr=%p, "
943 "stream-class-name=\"%s\", stream-class-id=%" PRId64
,
944 notit
, notit
->meta
.stream_class
,
945 bt_ctf_stream_class_get_name(notit
->meta
.stream_class
),
946 bt_ctf_stream_class_get_id(notit
->meta
.stream_class
));
949 * Retrieve (or lazily create) the current stream class field path
952 notit
->cur_sc_field_path_cache
= get_stream_class_field_path_cache(
953 notit
, notit
->meta
.stream_class
);
954 if (!notit
->cur_sc_field_path_cache
) {
955 BT_LOGW("Cannot retrieve stream class field path from cache: "
956 "notit-addr=%p, stream-class-addr=%p, "
957 "stream-class-name=\"%s\", stream-class-id=%" PRId64
,
958 notit
, notit
->meta
.stream_class
,
959 bt_ctf_stream_class_get_name(notit
->meta
.stream_class
),
960 bt_ctf_stream_class_get_id(notit
->meta
.stream_class
));
961 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
965 BT_PUT(packet_header_type
);
966 BT_PUT(stream_id_field_type
);
972 enum bt_ctf_notif_iter_status
after_packet_header_state(
973 struct bt_ctf_notif_iter
*notit
)
975 enum bt_ctf_notif_iter_status status
;
977 status
= set_current_stream_class(notit
);
978 if (status
== BT_CTF_NOTIF_ITER_STATUS_OK
) {
979 notit
->state
= STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
;
986 enum bt_ctf_notif_iter_status
read_packet_context_begin_state(
987 struct bt_ctf_notif_iter
*notit
)
989 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
990 struct bt_ctf_field_type
*packet_context_type
;
992 assert(notit
->meta
.stream_class
);
993 packet_context_type
= bt_ctf_stream_class_get_packet_context_type(
994 notit
->meta
.stream_class
);
995 if (!packet_context_type
) {
996 BT_LOGV("No packet packet context field type in stream class: continuing: "
997 "notit-addr=%p, stream-class-addr=%p, "
998 "stream-class-name=\"%s\", stream-class-id=%" PRId64
,
999 notit
, notit
->meta
.stream_class
,
1000 bt_ctf_stream_class_get_name(notit
->meta
.stream_class
),
1001 bt_ctf_stream_class_get_id(notit
->meta
.stream_class
));
1002 notit
->state
= STATE_AFTER_STREAM_PACKET_CONTEXT
;
1006 BT_LOGV("Decoding packet context field: "
1007 "notit-addr=%p, stream-class-addr=%p, "
1008 "stream-class-name=\"%s\", stream-class-id=%" PRId64
", "
1010 notit
, notit
->meta
.stream_class
,
1011 bt_ctf_stream_class_get_name(notit
->meta
.stream_class
),
1012 bt_ctf_stream_class_get_id(notit
->meta
.stream_class
),
1013 packet_context_type
);
1014 status
= read_dscope_begin_state(notit
, packet_context_type
,
1015 STATE_AFTER_STREAM_PACKET_CONTEXT
,
1016 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
,
1017 ¬it
->dscopes
.stream_packet_context
);
1019 BT_LOGW("Cannot decode packet context field: "
1020 "notit-addr=%p, stream-class-addr=%p, "
1021 "stream-class-name=\"%s\", "
1022 "stream-class-id=%" PRId64
", ft-addr=%p",
1023 notit
, notit
->meta
.stream_class
,
1024 bt_ctf_stream_class_get_name(notit
->meta
.stream_class
),
1025 bt_ctf_stream_class_get_id(notit
->meta
.stream_class
),
1026 packet_context_type
);
1030 BT_PUT(packet_context_type
);
1035 enum bt_ctf_notif_iter_status
read_packet_context_continue_state(
1036 struct bt_ctf_notif_iter
*notit
)
1038 return read_dscope_continue_state(notit
,
1039 STATE_AFTER_STREAM_PACKET_CONTEXT
);
1043 enum bt_ctf_notif_iter_status
set_current_packet_content_sizes(
1044 struct bt_ctf_notif_iter
*notit
)
1046 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
1047 struct bt_ctf_field
*packet_size_field
= NULL
;
1048 struct bt_ctf_field
*content_size_field
= NULL
;
1049 uint64_t content_size
= -1, packet_size
= -1;
1051 assert(notit
->dscopes
.stream_packet_context
);
1053 packet_size_field
= bt_ctf_field_structure_get_field(
1054 notit
->dscopes
.stream_packet_context
, "packet_size");
1055 content_size_field
= bt_ctf_field_structure_get_field(
1056 notit
->dscopes
.stream_packet_context
, "content_size");
1057 if (packet_size_field
) {
1058 int ret
= bt_ctf_field_unsigned_integer_get_value(
1059 packet_size_field
, &packet_size
);
1062 if (packet_size
== 0) {
1063 BT_LOGW("Invalid packet size: packet context field indicates packet size is zero: "
1064 "notit-addr=%p, packet-context-field-addr=%p",
1065 notit
, notit
->dscopes
.stream_packet_context
);
1066 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
1068 } else if ((packet_size
% 8) != 0) {
1069 BT_LOGW("Invalid packet size: packet context field indicates packet size is not a multiple of 8: "
1070 "notit-addr=%p, packet-context-field-addr=%p, "
1071 "packet-size=%" PRIu64
,
1072 notit
, notit
->dscopes
.stream_packet_context
,
1074 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
1079 if (content_size_field
) {
1080 int ret
= bt_ctf_field_unsigned_integer_get_value(
1081 content_size_field
, &content_size
);
1085 content_size
= packet_size
;
1088 if (content_size
> packet_size
) {
1089 BT_LOGW("Invalid packet or content size: packet context field indicates content size is greater than packet size: "
1090 "notit-addr=%p, packet-context-field-addr=%p, "
1091 "packet-size=%" PRIu64
", content-size=%" PRIu64
,
1092 notit
, notit
->dscopes
.stream_packet_context
,
1093 packet_size
, content_size
);
1094 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
1098 notit
->cur_packet_size
= packet_size
;
1099 notit
->cur_content_size
= content_size
;
1100 BT_LOGV("Set current packet and content sizes: "
1101 "notit-addr=%p, packet-size=%" PRIu64
", content-size=%" PRIu64
,
1102 notit
, packet_size
, content_size
);
1104 BT_PUT(packet_size_field
);
1105 BT_PUT(content_size_field
);
1110 enum bt_ctf_notif_iter_status
after_packet_context_state(
1111 struct bt_ctf_notif_iter
*notit
)
1113 enum bt_ctf_notif_iter_status status
;
1115 status
= set_current_packet_content_sizes(notit
);
1116 if (status
== BT_CTF_NOTIF_ITER_STATUS_OK
) {
1117 notit
->state
= STATE_EMIT_NOTIF_NEW_PACKET
;
1124 enum bt_ctf_notif_iter_status
read_event_header_begin_state(
1125 struct bt_ctf_notif_iter
*notit
)
1127 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
1128 struct bt_ctf_field_type
*event_header_type
= NULL
;
1130 /* Check if we have some content left */
1131 if (notit
->cur_content_size
>= 0) {
1132 if (packet_at(notit
) == notit
->cur_content_size
) {
1133 /* No more events! */
1134 BT_LOGV("Reached end of packet: notit-addr=%p, "
1135 "cur=%zu", notit
, packet_at(notit
));
1136 notit
->state
= STATE_EMIT_NOTIF_END_OF_PACKET
;
1138 } else if (packet_at(notit
) > notit
->cur_content_size
) {
1139 /* That's not supposed to happen */
1140 BT_LOGV("Before decoding event header field: cursor is passed the packet's content: "
1141 "notit-addr=%p, content-size=%zu, "
1142 "cur=%zu", notit
, notit
->cur_content_size
,
1144 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
1149 event_header_type
= bt_ctf_stream_class_get_event_header_type(
1150 notit
->meta
.stream_class
);
1151 if (!event_header_type
) {
1152 notit
->state
= STATE_AFTER_STREAM_EVENT_HEADER
;
1156 put_event_dscopes(notit
);
1157 BT_LOGV("Decoding event header field: "
1158 "notit-addr=%p, stream-class-addr=%p, "
1159 "stream-class-name=\"%s\", stream-class-id=%" PRId64
", "
1161 notit
, notit
->meta
.stream_class
,
1162 bt_ctf_stream_class_get_name(notit
->meta
.stream_class
),
1163 bt_ctf_stream_class_get_id(notit
->meta
.stream_class
),
1165 status
= read_dscope_begin_state(notit
, event_header_type
,
1166 STATE_AFTER_STREAM_EVENT_HEADER
,
1167 STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE
,
1168 ¬it
->dscopes
.stream_event_header
);
1170 BT_LOGW("Cannot decode event header field: "
1171 "notit-addr=%p, stream-class-addr=%p, "
1172 "stream-class-name=\"%s\", "
1173 "stream-class-id=%" PRId64
", ft-addr=%p",
1174 notit
, notit
->meta
.stream_class
,
1175 bt_ctf_stream_class_get_name(notit
->meta
.stream_class
),
1176 bt_ctf_stream_class_get_id(notit
->meta
.stream_class
),
1180 BT_PUT(event_header_type
);
1186 enum bt_ctf_notif_iter_status
read_event_header_continue_state(
1187 struct bt_ctf_notif_iter
*notit
)
1189 return read_dscope_continue_state(notit
,
1190 STATE_AFTER_STREAM_EVENT_HEADER
);
1194 enum bt_ctf_notif_iter_status
set_current_event_class(struct bt_ctf_notif_iter
*notit
)
1197 * The assert() calls in this function are okay because it is
1198 * assumed here that all the metadata objects have been
1199 * validated for CTF correctness before decoding actual streams.
1202 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
1203 struct bt_ctf_field_type
*event_header_type
;
1204 struct bt_ctf_field_type
*id_field_type
= NULL
;
1205 struct bt_ctf_field_type
*v_field_type
= NULL
;
1206 uint64_t event_id
= -1ULL;
1209 event_header_type
= bt_ctf_stream_class_get_event_header_type(
1210 notit
->meta
.stream_class
);
1211 if (!event_header_type
) {
1213 * No event header, therefore no event class ID field,
1214 * therefore only one event class.
1216 goto single_event_class
;
1219 /* Is there any "id"/"v" field in the event header? */
1220 assert(is_struct_type(event_header_type
));
1221 id_field_type
= bt_ctf_field_type_structure_get_field_type_by_name(
1222 event_header_type
, "id");
1223 v_field_type
= bt_ctf_field_type_structure_get_field_type_by_name(
1224 event_header_type
, "v");
1225 assert(notit
->dscopes
.stream_event_header
);
1229 * | | |_ _|_ _| __ __ _
1230 * | | | | | || '_ \ / _` |
1231 * | |___| | | || | | | (_| | S P E C I A L
1232 * |_____|_| |_||_| |_|\__, | C A S E â„¢
1235 struct bt_ctf_field
*v_field
= NULL
;
1236 struct bt_ctf_field
*v_struct_field
= NULL
;
1237 struct bt_ctf_field
*v_struct_id_field
= NULL
;
1239 // TODO: optimalize!
1240 v_field
= bt_ctf_field_structure_get_field(
1241 notit
->dscopes
.stream_event_header
, "v");
1245 bt_ctf_field_variant_get_current_field(v_field
);
1246 if (!v_struct_field
) {
1247 goto end_v_field_type
;
1250 // TODO: optimalize!
1252 bt_ctf_field_structure_get_field(v_struct_field
, "id");
1253 if (!v_struct_id_field
) {
1254 goto end_v_field_type
;
1257 if (bt_ctf_field_is_integer(v_struct_id_field
)) {
1258 ret
= bt_ctf_field_unsigned_integer_get_value(
1259 v_struct_id_field
, &event_id
);
1261 BT_LOGV("Cannot get value of unsigned integer field (`id`): continuing: "
1262 "notit=%p, field-addr=%p",
1263 notit
, v_struct_id_field
);
1270 BT_PUT(v_struct_field
);
1271 BT_PUT(v_struct_id_field
);
1274 if (id_field_type
&& event_id
== -1ULL) {
1275 /* Check "id" field */
1276 struct bt_ctf_field
*id_field
= NULL
;
1279 // TODO: optimalize!
1280 id_field
= bt_ctf_field_structure_get_field(
1281 notit
->dscopes
.stream_event_header
, "id");
1283 goto check_event_id
;
1286 if (bt_ctf_field_is_integer(id_field
)) {
1287 ret
= bt_ctf_field_unsigned_integer_get_value(
1288 id_field
, &event_id
);
1289 } else if (bt_ctf_field_is_enumeration(id_field
)) {
1290 struct bt_ctf_field
*container
;
1292 container
= bt_ctf_field_enumeration_get_container(
1295 ret
= bt_ctf_field_unsigned_integer_get_value(
1296 container
, &event_id
);
1305 if (event_id
== -1ULL) {
1307 /* Event ID not found: single event? */
1308 assert(bt_ctf_stream_class_get_event_class_count(
1309 notit
->meta
.stream_class
) == 1);
1313 BT_LOGV("Found event class ID to use: notit-addr=%p, "
1314 "stream-class-addr=%p, stream-class-name=\"%s\", "
1315 "stream-class-id=%" PRId64
", "
1316 "event-class-id=%" PRIu64
,
1317 notit
, notit
->meta
.stream_class
,
1318 bt_ctf_stream_class_get_name(notit
->meta
.stream_class
),
1319 bt_ctf_stream_class_get_id(notit
->meta
.stream_class
),
1321 BT_PUT(notit
->meta
.event_class
);
1322 notit
->meta
.event_class
= bt_ctf_stream_class_get_event_class_by_id(
1323 notit
->meta
.stream_class
, event_id
);
1324 if (!notit
->meta
.event_class
) {
1325 BT_LOGW("No event class with ID of event class ID to use in stream class: "
1326 "notit-addr=%p, stream-class-addr=%p, "
1327 "stream-class-name=\"%s\", "
1328 "stream-class-id=%" PRId64
", "
1329 "event-class-id=%" PRIu64
,
1330 notit
, notit
->meta
.stream_class
,
1331 bt_ctf_stream_class_get_name(notit
->meta
.stream_class
),
1332 bt_ctf_stream_class_get_id(notit
->meta
.stream_class
),
1334 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
1338 BT_LOGV("Set current event class: "
1339 "notit-addr=%p, event-class-addr=%p, "
1340 "event-class-name=\"%s\", event-class-id=%" PRId64
,
1341 notit
, notit
->meta
.event_class
,
1342 bt_ctf_event_class_get_name(notit
->meta
.event_class
),
1343 bt_ctf_event_class_get_id(notit
->meta
.event_class
));
1346 BT_PUT(event_header_type
);
1347 BT_PUT(id_field_type
);
1348 BT_PUT(v_field_type
);
1354 enum bt_ctf_notif_iter_status
after_event_header_state(
1355 struct bt_ctf_notif_iter
*notit
)
1357 enum bt_ctf_notif_iter_status status
;
1359 status
= set_current_event_class(notit
);
1360 if (status
!= BT_CTF_NOTIF_ITER_STATUS_OK
) {
1364 notit
->state
= STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN
;
1371 enum bt_ctf_notif_iter_status
read_stream_event_context_begin_state(
1372 struct bt_ctf_notif_iter
*notit
)
1374 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
1375 struct bt_ctf_field_type
*stream_event_context_type
;
1377 stream_event_context_type
= bt_ctf_stream_class_get_event_context_type(
1378 notit
->meta
.stream_class
);
1379 if (!stream_event_context_type
) {
1380 notit
->state
= STATE_DSCOPE_EVENT_CONTEXT_BEGIN
;
1384 BT_LOGV("Decoding stream event context field: "
1385 "notit-addr=%p, stream-class-addr=%p, "
1386 "stream-class-name=\"%s\", stream-class-id=%" PRId64
", "
1388 notit
, notit
->meta
.stream_class
,
1389 bt_ctf_stream_class_get_name(notit
->meta
.stream_class
),
1390 bt_ctf_stream_class_get_id(notit
->meta
.stream_class
),
1391 stream_event_context_type
);
1392 status
= read_dscope_begin_state(notit
, stream_event_context_type
,
1393 STATE_DSCOPE_EVENT_CONTEXT_BEGIN
,
1394 STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE
,
1395 ¬it
->dscopes
.stream_event_context
);
1397 BT_LOGW("Cannot decode stream event context field: "
1398 "notit-addr=%p, stream-class-addr=%p, "
1399 "stream-class-name=\"%s\", "
1400 "stream-class-id=%" PRId64
", ft-addr=%p",
1401 notit
, notit
->meta
.stream_class
,
1402 bt_ctf_stream_class_get_name(notit
->meta
.stream_class
),
1403 bt_ctf_stream_class_get_id(notit
->meta
.stream_class
),
1404 stream_event_context_type
);
1408 BT_PUT(stream_event_context_type
);
1414 enum bt_ctf_notif_iter_status
read_stream_event_context_continue_state(
1415 struct bt_ctf_notif_iter
*notit
)
1417 return read_dscope_continue_state(notit
,
1418 STATE_DSCOPE_EVENT_CONTEXT_BEGIN
);
1422 enum bt_ctf_notif_iter_status
read_event_context_begin_state(
1423 struct bt_ctf_notif_iter
*notit
)
1425 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
1426 struct bt_ctf_field_type
*event_context_type
;
1428 event_context_type
= bt_ctf_event_class_get_context_type(
1429 notit
->meta
.event_class
);
1430 if (!event_context_type
) {
1431 notit
->state
= STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
;
1435 BT_LOGV("Decoding event context field: "
1436 "notit-addr=%p, event-class-addr=%p, "
1437 "event-class-name=\"%s\", event-class-id=%" PRId64
", "
1439 notit
, notit
->meta
.event_class
,
1440 bt_ctf_event_class_get_name(notit
->meta
.event_class
),
1441 bt_ctf_event_class_get_id(notit
->meta
.event_class
),
1442 event_context_type
);
1443 status
= read_dscope_begin_state(notit
, event_context_type
,
1444 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
,
1445 STATE_DSCOPE_EVENT_CONTEXT_CONTINUE
,
1446 ¬it
->dscopes
.event_context
);
1448 BT_LOGW("Cannot decode event context field: "
1449 "notit-addr=%p, event-class-addr=%p, "
1450 "event-class-name=\"%s\", "
1451 "event-class-id=%" PRId64
", ft-addr=%p",
1452 notit
, notit
->meta
.event_class
,
1453 bt_ctf_event_class_get_name(notit
->meta
.event_class
),
1454 bt_ctf_event_class_get_id(notit
->meta
.event_class
),
1455 event_context_type
);
1459 BT_PUT(event_context_type
);
1465 enum bt_ctf_notif_iter_status
read_event_context_continue_state(
1466 struct bt_ctf_notif_iter
*notit
)
1468 return read_dscope_continue_state(notit
,
1469 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
);
1473 enum bt_ctf_notif_iter_status
read_event_payload_begin_state(
1474 struct bt_ctf_notif_iter
*notit
)
1476 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
1477 struct bt_ctf_field_type
*event_payload_type
;
1479 event_payload_type
= bt_ctf_event_class_get_payload_type(
1480 notit
->meta
.event_class
);
1481 if (!event_payload_type
) {
1482 notit
->state
= STATE_EMIT_NOTIF_EVENT
;
1486 BT_LOGV("Decoding event payload field: "
1487 "notit-addr=%p, event-class-addr=%p, "
1488 "event-class-name=\"%s\", event-class-id=%" PRId64
", "
1490 notit
, notit
->meta
.event_class
,
1491 bt_ctf_event_class_get_name(notit
->meta
.event_class
),
1492 bt_ctf_event_class_get_id(notit
->meta
.event_class
),
1493 event_payload_type
);
1494 status
= read_dscope_begin_state(notit
, event_payload_type
,
1495 STATE_EMIT_NOTIF_EVENT
,
1496 STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
,
1497 ¬it
->dscopes
.event_payload
);
1499 BT_LOGW("Cannot decode event payload field: "
1500 "notit-addr=%p, event-class-addr=%p, "
1501 "event-class-name=\"%s\", "
1502 "event-class-id=%" PRId64
", ft-addr=%p",
1503 notit
, notit
->meta
.event_class
,
1504 bt_ctf_event_class_get_name(notit
->meta
.event_class
),
1505 bt_ctf_event_class_get_id(notit
->meta
.event_class
),
1506 event_payload_type
);
1510 BT_PUT(event_payload_type
);
1516 enum bt_ctf_notif_iter_status
read_event_payload_continue_state(
1517 struct bt_ctf_notif_iter
*notit
)
1519 return read_dscope_continue_state(notit
, STATE_EMIT_NOTIF_EVENT
);
1523 enum bt_ctf_notif_iter_status
skip_packet_padding_state(
1524 struct bt_ctf_notif_iter
*notit
)
1526 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
1527 size_t bits_to_skip
;
1529 assert(notit
->cur_packet_size
> 0);
1530 bits_to_skip
= notit
->cur_packet_size
- packet_at(notit
);
1531 if (bits_to_skip
== 0) {
1532 notit
->state
= STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
;
1535 size_t bits_to_consume
;
1537 BT_LOGV("Trying to skip %zu bits of padding: notit-addr=%p, size=%zu",
1538 bits_to_skip
, notit
, bits_to_skip
);
1539 status
= buf_ensure_available_bits(notit
);
1540 if (status
!= BT_CTF_NOTIF_ITER_STATUS_OK
) {
1544 bits_to_consume
= MIN(buf_available_bits(notit
), bits_to_skip
);
1545 BT_LOGV("Skipping %zu bits of padding: notit-addr=%p, size=%zu",
1546 bits_to_consume
, notit
, bits_to_consume
);
1547 buf_consume_bits(notit
, bits_to_consume
);
1548 bits_to_skip
= notit
->cur_packet_size
- packet_at(notit
);
1549 if (bits_to_skip
== 0) {
1550 notit
->state
= STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
;
1560 enum bt_ctf_notif_iter_status
handle_state(struct bt_ctf_notif_iter
*notit
)
1562 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
1563 const enum state state
= notit
->state
;
1565 BT_LOGV("Handling state: notit-addr=%p, state=%s",
1566 notit
, state_string(state
));
1568 // TODO: optimalize!
1571 notit
->state
= STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
;
1573 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
:
1574 status
= read_packet_header_begin_state(notit
);
1576 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
:
1577 status
= read_packet_header_continue_state(notit
);
1579 case STATE_AFTER_TRACE_PACKET_HEADER
:
1580 status
= after_packet_header_state(notit
);
1582 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
:
1583 status
= read_packet_context_begin_state(notit
);
1585 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
:
1586 status
= read_packet_context_continue_state(notit
);
1588 case STATE_AFTER_STREAM_PACKET_CONTEXT
:
1589 status
= after_packet_context_state(notit
);
1591 case STATE_EMIT_NOTIF_NEW_PACKET
:
1592 notit
->state
= STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN
;
1594 case STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN
:
1595 status
= read_event_header_begin_state(notit
);
1597 case STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE
:
1598 status
= read_event_header_continue_state(notit
);
1600 case STATE_AFTER_STREAM_EVENT_HEADER
:
1601 status
= after_event_header_state(notit
);
1603 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN
:
1604 status
= read_stream_event_context_begin_state(notit
);
1606 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE
:
1607 status
= read_stream_event_context_continue_state(notit
);
1609 case STATE_DSCOPE_EVENT_CONTEXT_BEGIN
:
1610 status
= read_event_context_begin_state(notit
);
1612 case STATE_DSCOPE_EVENT_CONTEXT_CONTINUE
:
1613 status
= read_event_context_continue_state(notit
);
1615 case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
:
1616 status
= read_event_payload_begin_state(notit
);
1618 case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
:
1619 status
= read_event_payload_continue_state(notit
);
1621 case STATE_EMIT_NOTIF_EVENT
:
1622 notit
->state
= STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN
;
1624 case STATE_SKIP_PACKET_PADDING
:
1625 status
= skip_packet_padding_state(notit
);
1627 case STATE_EMIT_NOTIF_END_OF_PACKET
:
1628 notit
->state
= STATE_SKIP_PACKET_PADDING
;
1631 BT_LOGD("Unknown CTF plugin notification iterator state: "
1632 "notit-addr=%p, state=%d", notit
, notit
->state
);
1636 BT_LOGV("Handled state: notit-addr=%p, status=%s, "
1637 "prev-state=%s, cur-state=%s",
1638 notit
, bt_ctf_notif_iter_status_string(status
),
1639 state_string(state
), state_string(notit
->state
));
1644 * Resets the internal state of a CTF notification iterator.
1647 void bt_ctf_notif_iter_reset(struct bt_ctf_notif_iter
*notit
)
1650 BT_LOGD("Resetting notification iterator: addr=%p", notit
);
1651 stack_clear(notit
->stack
);
1652 BT_PUT(notit
->meta
.stream_class
);
1653 BT_PUT(notit
->meta
.event_class
);
1654 BT_PUT(notit
->packet
);
1655 put_all_dscopes(notit
);
1656 notit
->buf
.addr
= NULL
;
1659 notit
->buf
.packet_offset
= 0;
1660 notit
->state
= STATE_INIT
;
1661 notit
->cur_content_size
= -1;
1662 notit
->cur_packet_size
= -1;
1666 int bt_ctf_notif_iter_switch_packet(struct bt_ctf_notif_iter
*notit
)
1671 BT_LOGV("Switching packet: notit-addr=%p, cur=%zu",
1672 notit
, notit
->buf
.at
);
1673 stack_clear(notit
->stack
);
1674 BT_PUT(notit
->meta
.stream_class
);
1675 BT_PUT(notit
->meta
.event_class
);
1676 BT_PUT(notit
->packet
);
1677 BT_PUT(notit
->cur_timestamp_end
);
1678 put_all_dscopes(notit
);
1681 * Adjust current buffer so that addr points to the beginning of the new
1684 if (notit
->buf
.addr
) {
1685 size_t consumed_bytes
= (size_t) (notit
->buf
.at
/ CHAR_BIT
);
1687 /* Packets are assumed to start on a byte frontier. */
1688 if (notit
->buf
.at
% CHAR_BIT
) {
1689 BT_LOGW("Cannot switch packet: current position is not a multiple of 8: "
1690 "notit-addr=%p, cur=%zu", notit
, notit
->buf
.at
);
1695 notit
->buf
.addr
+= consumed_bytes
;
1696 notit
->buf
.sz
-= consumed_bytes
;
1698 notit
->buf
.packet_offset
= 0;
1699 BT_LOGV("Adjusted buffer: addr=%p, size=%zu",
1700 notit
->buf
.addr
, notit
->buf
.sz
);
1703 notit
->cur_content_size
= -1;
1704 notit
->cur_packet_size
= -1;
1705 notit
->cur_sc_field_path_cache
= NULL
;
1712 struct bt_ctf_field
*get_next_field(struct bt_ctf_notif_iter
*notit
)
1714 struct bt_ctf_field
*next_field
= NULL
;
1715 struct bt_ctf_field
*base_field
;
1716 struct bt_ctf_field_type
*base_type
;
1719 assert(!stack_empty(notit
->stack
));
1720 index
= stack_top(notit
->stack
)->index
;
1721 base_field
= stack_top(notit
->stack
)->base
;
1723 base_type
= bt_ctf_field_get_type(base_field
);
1726 switch (bt_ctf_field_type_get_type_id(base_type
)) {
1727 case BT_CTF_FIELD_TYPE_ID_STRUCT
:
1728 next_field
= bt_ctf_field_structure_get_field_by_index(
1731 case BT_CTF_FIELD_TYPE_ID_ARRAY
:
1732 next_field
= bt_ctf_field_array_get_field(base_field
, index
);
1734 case BT_CTF_FIELD_TYPE_ID_SEQUENCE
:
1735 next_field
= bt_ctf_field_sequence_get_field(base_field
, index
);
1737 case BT_CTF_FIELD_TYPE_ID_VARIANT
:
1738 next_field
= bt_ctf_field_variant_get_current_field(base_field
);
1741 BT_LOGF("Unknown base field type ID: "
1742 "notit-addr=%p, ft-addr=%p, ft-id=%s",
1744 bt_ctf_field_type_id_string(
1745 bt_ctf_field_type_get_type_id(base_type
)));
1754 void update_clock_state(uint64_t *state
,
1755 struct bt_ctf_field
*value_field
)
1757 struct bt_ctf_field_type
*value_type
= NULL
;
1758 uint64_t requested_new_value
;
1759 uint64_t requested_new_value_mask
;
1760 uint64_t cur_value_masked
;
1761 int requested_new_value_size
;
1764 value_type
= bt_ctf_field_get_type(value_field
);
1766 assert(bt_ctf_field_type_is_integer(value_type
));
1767 requested_new_value_size
=
1768 bt_ctf_field_type_integer_get_size(value_type
);
1769 assert(requested_new_value_size
> 0);
1770 ret
= bt_ctf_field_unsigned_integer_get_value(value_field
,
1771 &requested_new_value
);
1775 * Special case for a 64-bit new value, which is the limit
1776 * of a clock value as of this version: overwrite the
1777 * current value directly.
1779 if (requested_new_value_size
== 64) {
1780 *state
= requested_new_value
;
1784 requested_new_value_mask
= (1ULL << requested_new_value_size
) - 1;
1785 cur_value_masked
= *state
& requested_new_value_mask
;
1787 if (requested_new_value
< cur_value_masked
) {
1789 * It looks like a wrap happened on the number of bits
1790 * of the requested new value. Assume that the clock
1791 * value wrapped only one time.
1793 *state
+= requested_new_value_mask
+ 1;
1796 /* Clear the low bits of the current clock value. */
1797 *state
&= ~requested_new_value_mask
;
1799 /* Set the low bits of the current clock value. */
1800 *state
|= requested_new_value
;
1802 BT_LOGV("Updated clock's value from integer field's value: "
1803 "value=%" PRIu64
, *state
);
1808 enum bt_ctf_btr_status
update_clock(struct bt_ctf_notif_iter
*notit
,
1809 struct bt_ctf_field
*int_field
)
1811 gboolean clock_class_found
;
1812 uint64_t *clock_state
;
1813 struct bt_ctf_field_type
*int_field_type
= NULL
;
1814 enum bt_ctf_btr_status ret
= BT_CTF_BTR_STATUS_OK
;
1815 struct bt_ctf_clock_class
*clock_class
= NULL
;
1817 int_field_type
= bt_ctf_field_get_type(int_field
);
1818 assert(int_field_type
);
1819 clock_class
= bt_ctf_field_type_integer_get_mapped_clock_class(
1821 if (likely(!clock_class
)) {
1825 clock_class_found
= g_hash_table_lookup_extended(notit
->clock_states
,
1826 clock_class
, NULL
, (gpointer
) &clock_state
);
1827 if (unlikely(!clock_class_found
)) {
1828 ret
= BT_CTF_BTR_STATUS_ERROR
;
1832 if (unlikely(!clock_state
)) {
1833 clock_state
= g_new0(uint64_t, 1);
1835 BT_LOGE_STR("Failed to allocate a uint64_t.");
1836 ret
= BT_CTF_BTR_STATUS_ENOMEM
;
1840 g_hash_table_insert(notit
->clock_states
, bt_get(clock_class
),
1844 /* Update the clock's state. */
1845 BT_LOGV("Updating notification iterator's clock's value from integer field: "
1846 "notit-addr=%p, clock-class-addr=%p, "
1847 "clock-class-name=\"%s\", value=%" PRIu64
,
1849 bt_ctf_clock_class_get_name(clock_class
), *clock_state
);
1850 update_clock_state(clock_state
, int_field
);
1852 bt_put(int_field_type
);
1853 bt_put(clock_class
);
1858 enum bt_ctf_btr_status
btr_unsigned_int_common(uint64_t value
,
1859 struct bt_ctf_field_type
*type
, void *data
,
1860 struct bt_ctf_field
**out_int_field
)
1862 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1863 struct bt_ctf_field
*field
= NULL
;
1864 struct bt_ctf_field
*int_field
= NULL
;
1865 struct bt_ctf_notif_iter
*notit
= data
;
1868 BT_LOGV("Common unsigned integer function called from BTR: "
1869 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
1870 "ft-id=%s, value=%" PRIu64
,
1871 notit
, notit
->btr
, type
,
1872 bt_ctf_field_type_id_string(
1873 bt_ctf_field_type_get_type_id(type
)),
1876 /* Create next field */
1877 field
= get_next_field(notit
);
1879 BT_LOGW("Cannot get next field: notit-addr=%p", notit
);
1880 status
= BT_CTF_BTR_STATUS_ERROR
;
1884 switch(bt_ctf_field_type_get_type_id(type
)) {
1885 case BT_CTF_FIELD_TYPE_ID_INTEGER
:
1886 /* Integer field is created field */
1887 BT_MOVE(int_field
, field
);
1890 case BT_CTF_FIELD_TYPE_ID_ENUM
:
1891 int_field
= bt_ctf_field_enumeration_get_container(field
);
1893 type
= bt_ctf_field_get_type(int_field
);
1897 BT_LOGF("Unexpected field type ID: "
1898 "notit-addr=%p, ft-addr=%p, ft-id=%s",
1900 bt_ctf_field_type_id_string(
1901 bt_ctf_field_type_get_type_id(type
)));
1906 ret
= bt_ctf_field_unsigned_integer_set_value(int_field
, value
);
1908 stack_top(notit
->stack
)->index
++;
1909 *out_int_field
= int_field
;
1918 enum bt_ctf_btr_status
btr_timestamp_end_cb(void *value
,
1919 struct bt_ctf_field_type
*type
, void *data
)
1921 enum bt_ctf_btr_status status
;
1922 struct bt_ctf_field
*field
= NULL
;
1923 struct bt_ctf_notif_iter
*notit
= data
;
1925 BT_LOGV("`timestamp_end` unsigned integer function called from BTR: "
1926 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
1928 notit
, notit
->btr
, type
,
1929 bt_ctf_field_type_id_string(
1930 bt_ctf_field_type_get_type_id(type
)));
1931 status
= btr_unsigned_int_common(*((uint64_t *) value
), type
, data
,
1934 /* Set as the current packet's timestamp_end field. */
1935 BT_MOVE(notit
->cur_timestamp_end
, field
);
1940 enum bt_ctf_btr_status
btr_unsigned_int_cb(uint64_t value
,
1941 struct bt_ctf_field_type
*type
, void *data
)
1943 struct bt_ctf_notif_iter
*notit
= data
;
1944 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1945 struct bt_ctf_field
*field
= NULL
;
1946 struct field_cb_override
*override
;
1948 BT_LOGV("Unsigned integer function called from BTR: "
1949 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
1950 "ft-id=%s, value=%" PRIu64
,
1951 notit
, notit
->btr
, type
,
1952 bt_ctf_field_type_id_string(
1953 bt_ctf_field_type_get_type_id(type
)),
1955 override
= g_hash_table_lookup(notit
->field_overrides
, type
);
1956 if (unlikely(override
)) {
1957 /* Override function logs errors */
1958 status
= override
->func(&value
, type
, override
->data
);
1962 status
= btr_unsigned_int_common(value
, type
, data
, &field
);
1963 if (status
!= BT_CTF_BTR_STATUS_OK
) {
1964 /* btr_unsigned_int_common() logs errors */
1968 status
= update_clock(notit
, field
);
1975 enum bt_ctf_btr_status
btr_signed_int_cb(int64_t value
,
1976 struct bt_ctf_field_type
*type
, void *data
)
1978 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1979 struct bt_ctf_field
*field
= NULL
;
1980 struct bt_ctf_field
*int_field
= NULL
;
1981 struct bt_ctf_notif_iter
*notit
= data
;
1984 BT_LOGV("Signed integer function called from BTR: "
1985 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
1986 "ft-id=%s, value=%" PRId64
,
1987 notit
, notit
->btr
, type
,
1988 bt_ctf_field_type_id_string(
1989 bt_ctf_field_type_get_type_id(type
)),
1992 /* create next field */
1993 field
= get_next_field(notit
);
1995 BT_LOGW("Cannot get next field: notit-addr=%p", notit
);
1996 status
= BT_CTF_BTR_STATUS_ERROR
;
2000 switch(bt_ctf_field_type_get_type_id(type
)) {
2001 case BT_CTF_FIELD_TYPE_ID_INTEGER
:
2002 /* Integer field is created field */
2003 BT_MOVE(int_field
, field
);
2006 case BT_CTF_FIELD_TYPE_ID_ENUM
:
2007 int_field
= bt_ctf_field_enumeration_get_container(field
);
2009 type
= bt_ctf_field_get_type(int_field
);
2013 BT_LOGF("Unexpected field type ID: "
2014 "notit-addr=%p, ft-addr=%p, ft-id=%s",
2016 bt_ctf_field_type_id_string(
2017 bt_ctf_field_type_get_type_id(type
)));
2022 ret
= bt_ctf_field_signed_integer_set_value(int_field
, value
);
2024 stack_top(notit
->stack
)->index
++;
2025 status
= update_clock(notit
, int_field
);
2035 enum bt_ctf_btr_status
btr_floating_point_cb(double value
,
2036 struct bt_ctf_field_type
*type
, void *data
)
2038 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
2039 struct bt_ctf_field
*field
= NULL
;
2040 struct bt_ctf_notif_iter
*notit
= data
;
2043 BT_LOGV("Floating point number function called from BTR: "
2044 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2045 "ft-id=%s, value=%f",
2046 notit
, notit
->btr
, type
,
2047 bt_ctf_field_type_id_string(
2048 bt_ctf_field_type_get_type_id(type
)),
2051 /* Create next field */
2052 field
= get_next_field(notit
);
2054 BT_LOGW("Cannot get next field: notit-addr=%p", notit
);
2055 status
= BT_CTF_BTR_STATUS_ERROR
;
2059 ret
= bt_ctf_field_floating_point_set_value(field
, value
);
2061 stack_top(notit
->stack
)->index
++;
2069 enum bt_ctf_btr_status
btr_string_begin_cb(
2070 struct bt_ctf_field_type
*type
, void *data
)
2072 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
2073 struct bt_ctf_field
*field
= NULL
;
2074 struct bt_ctf_notif_iter
*notit
= data
;
2077 BT_LOGV("String (beginning) function called from BTR: "
2078 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2080 notit
, notit
->btr
, type
,
2081 bt_ctf_field_type_id_string(
2082 bt_ctf_field_type_get_type_id(type
)));
2084 /* Create next field */
2085 field
= get_next_field(notit
);
2087 BT_LOGW("Cannot get next field: notit-addr=%p", notit
);
2088 status
= BT_CTF_BTR_STATUS_ERROR
;
2093 * Push on stack. Not a compound type per se, but we know that only
2094 * btr_string_cb() may be called between this call and a subsequent
2095 * call to btr_string_end_cb().
2097 ret
= stack_push(notit
->stack
, field
);
2099 BT_LOGE("Cannot push string field on stack: "
2100 "notit-addr=%p, field-addr=%p", notit
, field
);
2101 status
= BT_CTF_BTR_STATUS_ERROR
;
2106 * Initialize string field payload to an empty string since in the
2107 * case of a length 0 string the btr_string_cb won't be called and
2108 * we will end up with an unset string payload.
2110 ret
= bt_ctf_field_string_set_value(field
, "");
2112 BT_LOGE("Cannot initialize string field's value to an empty string: "
2113 "notit-addr=%p, field-addr=%p, ret=%d",
2115 status
= BT_CTF_BTR_STATUS_ERROR
;
2126 enum bt_ctf_btr_status
btr_string_cb(const char *value
,
2127 size_t len
, struct bt_ctf_field_type
*type
, void *data
)
2129 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
2130 struct bt_ctf_field
*field
= NULL
;
2131 struct bt_ctf_notif_iter
*notit
= data
;
2134 BT_LOGV("String (substring) function called from BTR: "
2135 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2136 "ft-id=%s, string-length=%zu",
2137 notit
, notit
->btr
, type
,
2138 bt_ctf_field_type_id_string(
2139 bt_ctf_field_type_get_type_id(type
)),
2142 /* Get string field */
2143 field
= stack_top(notit
->stack
)->base
;
2146 /* Append current string */
2147 ret
= bt_ctf_field_string_append_len(field
, value
, len
);
2149 BT_LOGE("Cannot append substring to string field's value: "
2150 "notit-addr=%p, field-addr=%p, string-length=%zu, "
2151 "ret=%d", notit
, field
, len
, ret
);
2152 status
= BT_CTF_BTR_STATUS_ERROR
;
2161 enum bt_ctf_btr_status
btr_string_end_cb(
2162 struct bt_ctf_field_type
*type
, void *data
)
2164 struct bt_ctf_notif_iter
*notit
= data
;
2166 BT_LOGV("String (end) function called from BTR: "
2167 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2169 notit
, notit
->btr
, type
,
2170 bt_ctf_field_type_id_string(
2171 bt_ctf_field_type_get_type_id(type
)));
2173 /* Pop string field */
2174 stack_pop(notit
->stack
);
2176 /* Go to next field */
2177 stack_top(notit
->stack
)->index
++;
2178 return BT_CTF_BTR_STATUS_OK
;
2181 enum bt_ctf_btr_status
btr_compound_begin_cb(
2182 struct bt_ctf_field_type
*type
, void *data
)
2184 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
2185 struct bt_ctf_notif_iter
*notit
= data
;
2186 struct bt_ctf_field
*field
;
2189 BT_LOGV("Compound (beginning) function called from BTR: "
2190 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2192 notit
, notit
->btr
, type
,
2193 bt_ctf_field_type_id_string(
2194 bt_ctf_field_type_get_type_id(type
)));
2197 if (stack_empty(notit
->stack
)) {
2198 /* Root: create dynamic scope field */
2199 *notit
->cur_dscope_field
= bt_ctf_field_create(type
);
2200 field
= *notit
->cur_dscope_field
;
2203 * Field will be put at the end of this function
2204 * (stack_push() will take one reference, but this
2205 * reference is lost upon the equivalent stack_pop()
2206 * later), so also get it for our context to own it.
2208 bt_get(*notit
->cur_dscope_field
);
2211 BT_LOGE("Cannot create compound field: "
2212 "notit-addr=%p, ft-addr=%p, ft-id=%s",
2214 bt_ctf_field_type_id_string(
2215 bt_ctf_field_type_get_type_id(type
)));
2216 status
= BT_CTF_BTR_STATUS_ERROR
;
2220 field
= get_next_field(notit
);
2222 BT_LOGW("Cannot get next field: notit-addr=%p", notit
);
2223 status
= BT_CTF_BTR_STATUS_ERROR
;
2230 ret
= stack_push(notit
->stack
, field
);
2232 BT_LOGE("Cannot push compound field onto the stack: "
2233 "notit-addr=%p, ft-addr=%p, ft-id=%s, ret=%d",
2235 bt_ctf_field_type_id_string(
2236 bt_ctf_field_type_get_type_id(type
)),
2238 status
= BT_CTF_BTR_STATUS_ERROR
;
2248 enum bt_ctf_btr_status
btr_compound_end_cb(
2249 struct bt_ctf_field_type
*type
, void *data
)
2251 struct bt_ctf_notif_iter
*notit
= data
;
2253 BT_LOGV("Compound (end) function called from BTR: "
2254 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2256 notit
, notit
->btr
, type
,
2257 bt_ctf_field_type_id_string(
2258 bt_ctf_field_type_get_type_id(type
)));
2259 assert(!stack_empty(notit
->stack
));
2262 stack_pop(notit
->stack
);
2264 /* If the stack is not empty, increment the base's index */
2265 if (!stack_empty(notit
->stack
)) {
2266 stack_top(notit
->stack
)->index
++;
2269 return BT_CTF_BTR_STATUS_OK
;
2273 struct bt_ctf_field
*resolve_field(struct bt_ctf_notif_iter
*notit
,
2274 struct bt_ctf_field_path
*path
)
2276 struct bt_ctf_field
*field
= NULL
;
2279 if (BT_LOG_ON_VERBOSE
) {
2280 GString
*gstr
= bt_ctf_field_path_string(path
);
2282 BT_LOGV("Resolving field path: notit-addr=%p, field-path=\"%s\"",
2283 notit
, gstr
? gstr
->str
: NULL
);
2286 g_string_free(gstr
, TRUE
);
2290 switch (bt_ctf_field_path_get_root_scope(path
)) {
2291 case BT_CTF_SCOPE_TRACE_PACKET_HEADER
:
2292 field
= notit
->dscopes
.trace_packet_header
;
2294 case BT_CTF_SCOPE_STREAM_PACKET_CONTEXT
:
2295 field
= notit
->dscopes
.stream_packet_context
;
2297 case BT_CTF_SCOPE_STREAM_EVENT_HEADER
:
2298 field
= notit
->dscopes
.stream_event_header
;
2300 case BT_CTF_SCOPE_STREAM_EVENT_CONTEXT
:
2301 field
= notit
->dscopes
.stream_event_context
;
2303 case BT_CTF_SCOPE_EVENT_CONTEXT
:
2304 field
= notit
->dscopes
.event_context
;
2306 case BT_CTF_SCOPE_EVENT_FIELDS
:
2307 field
= notit
->dscopes
.event_payload
;
2310 BT_LOGF("Cannot resolve field path: unknown scope: "
2311 "notit-addr=%p, root-scope=%s",
2312 notit
, bt_ctf_scope_string(
2313 bt_ctf_field_path_get_root_scope(path
)));
2318 BT_LOGW("Cannot resolve field path: root field not found: "
2319 "notit-addr=%p, root-scope=%s",
2320 notit
, bt_ctf_scope_string(
2321 bt_ctf_field_path_get_root_scope(path
)));
2327 for (i
= 0; i
< bt_ctf_field_path_get_index_count(path
); ++i
) {
2328 struct bt_ctf_field
*next_field
= NULL
;
2329 struct bt_ctf_field_type
*field_type
;
2330 int index
= bt_ctf_field_path_get_index(path
, i
);
2332 field_type
= bt_ctf_field_get_type(field
);
2335 if (is_struct_type(field_type
)) {
2336 next_field
= bt_ctf_field_structure_get_field_by_index(
2338 } else if (is_variant_type(field_type
)) {
2340 bt_ctf_field_variant_get_current_field(field
);
2347 BT_LOGW("Cannot find next field: "
2348 "notit-addr=%p, ft-addr=%p, ft-id=%s, index=%d",
2350 bt_ctf_field_type_id_string(
2351 bt_ctf_field_type_get_type_id(field_type
)),
2356 /* Move next field -> field */
2357 BT_MOVE(field
, next_field
);
2365 int64_t btr_get_sequence_length_cb(struct bt_ctf_field_type
*type
, void *data
)
2369 struct bt_ctf_field
*seq_field
;
2370 struct bt_ctf_field_path
*field_path
;
2371 struct bt_ctf_notif_iter
*notit
= data
;
2372 struct bt_ctf_field
*length_field
= NULL
;
2375 field_path
= bt_ctf_field_type_sequence_get_length_field_path(type
);
2377 length_field
= resolve_field(notit
, field_path
);
2378 if (!length_field
) {
2379 BT_LOGW("Cannot resolve sequence field type's length field path: "
2380 "notit-addr=%p, ft-addr=%p",
2385 iret
= bt_ctf_field_unsigned_integer_get_value(length_field
, &length
);
2387 BT_LOGE("Cannot get value of sequence length field: "
2388 "notit-addr=%p, field-addr=%p",
2389 notit
, length_field
);
2393 seq_field
= stack_top(notit
->stack
)->base
;
2394 iret
= bt_ctf_field_sequence_set_length(seq_field
, length_field
);
2396 BT_LOGE("Cannot set sequence field's length field: "
2397 "notit-addr=%p, seq-field-addr=%p, "
2398 "length-field-addr=%p, ",
2399 notit
, seq_field
, length_field
);
2403 ret
= (int64_t) length
;
2406 BT_PUT(length_field
);
2413 struct bt_ctf_field_type
*btr_get_variant_type_cb(
2414 struct bt_ctf_field_type
*type
, void *data
)
2416 struct bt_ctf_field_path
*path
;
2417 struct bt_ctf_notif_iter
*notit
= data
;
2418 struct bt_ctf_field
*var_field
;
2419 struct bt_ctf_field
*tag_field
= NULL
;
2420 struct bt_ctf_field
*selected_field
= NULL
;
2421 struct bt_ctf_field_type
*selected_field_type
= NULL
;
2423 path
= bt_ctf_field_type_variant_get_tag_field_path(type
);
2425 tag_field
= resolve_field(notit
, path
);
2427 BT_LOGW("Cannot resolve variant field type's tag field path: "
2428 "notit-addr=%p, ft-addr=%p",
2434 * We found the enumeration tag field instance which should be
2435 * able to select a current field for this variant. This
2436 * callback function we're in is called _after_
2437 * compound_begin(), so the current stack top's base field is
2438 * the variant field in question. We get the selected field here
2439 * thanks to this tag field (thus creating the selected field),
2440 * which will also provide us with its type. Then, this field
2441 * will remain the current selected one until the next callback
2442 * function call which is used to fill the current selected
2445 var_field
= stack_top(notit
->stack
)->base
;
2446 selected_field
= bt_ctf_field_variant_get_field(var_field
, tag_field
);
2447 if (!selected_field
) {
2448 BT_LOGW("Cannot get variant field's selection using tag field: "
2449 "notit-addr=%p, var-field-addr=%p, tag-field-addr=%p",
2450 notit
, var_field
, tag_field
);
2454 selected_field_type
= bt_ctf_field_get_type(selected_field
);
2458 BT_PUT(selected_field
);
2461 return selected_field_type
;
2465 int set_event_clocks(struct bt_ctf_event
*event
,
2466 struct bt_ctf_notif_iter
*notit
)
2469 GHashTableIter iter
;
2470 struct bt_ctf_clock_class
*clock_class
;
2471 uint64_t *clock_state
;
2473 g_hash_table_iter_init(&iter
, notit
->clock_states
);
2475 while (g_hash_table_iter_next(&iter
, (gpointer
) &clock_class
,
2476 (gpointer
) &clock_state
)) {
2477 struct bt_ctf_clock_value
*clock_value
;
2479 clock_value
= bt_ctf_clock_value_create(clock_class
,
2482 BT_LOGE("Cannot create clock value from clock class: "
2483 "notit-addr=%p, clock-class-addr=%p, "
2484 "clock-class-name=\"%s\"",
2486 bt_ctf_clock_class_get_name(clock_class
));
2490 ret
= bt_ctf_event_set_clock_value(event
, clock_value
);
2491 bt_put(clock_value
);
2493 struct bt_ctf_event_class
*event_class
=
2494 bt_ctf_event_get_class(event
);
2496 assert(event_class
);
2497 BT_LOGE("Cannot set event's clock value: "
2498 "notit-addr=%p, event-addr=%p, "
2499 "event-class-name=\"%s\", "
2500 "event-class-id=%" PRId64
", "
2501 "clock-class-addr=%p, "
2502 "clock-class-name=\"%s\", "
2503 "clock-value-addr=%p",
2505 bt_ctf_event_class_get_name(event_class
),
2506 bt_ctf_event_class_get_id(event_class
),
2508 bt_ctf_clock_class_get_name(clock_class
),
2510 bt_put(event_class
);
2521 struct bt_ctf_event
*create_event(struct bt_ctf_notif_iter
*notit
)
2524 struct bt_ctf_event
*event
;
2526 BT_LOGV("Creating event for event notification: "
2527 "notit-addr=%p, event-class-addr=%p, "
2528 "event-class-name=\"%s\", "
2529 "event-class-id=%" PRId64
,
2530 notit
, notit
->meta
.event_class
,
2531 bt_ctf_event_class_get_name(notit
->meta
.event_class
),
2532 bt_ctf_event_class_get_id(notit
->meta
.event_class
));
2534 /* Create event object. */
2535 event
= bt_ctf_event_create(notit
->meta
.event_class
);
2537 BT_LOGE("Cannot create event: "
2538 "notit-addr=%p, event-class-addr=%p, "
2539 "event-class-name=\"%s\", "
2540 "event-class-id=%" PRId64
,
2541 notit
, notit
->meta
.event_class
,
2542 bt_ctf_event_class_get_name(notit
->meta
.event_class
),
2543 bt_ctf_event_class_get_id(notit
->meta
.event_class
));
2547 /* Set header, stream event context, context, and payload fields. */
2548 ret
= bt_ctf_event_set_header(event
,
2549 notit
->dscopes
.stream_event_header
);
2551 BT_LOGE("Cannot set event's header field: "
2552 "notit-addr=%p, event-addr=%p, event-class-addr=%p, "
2553 "event-class-name=\"%s\", "
2554 "event-class-id=%" PRId64
", field-addr=%p",
2555 notit
, event
, notit
->meta
.event_class
,
2556 bt_ctf_event_class_get_name(notit
->meta
.event_class
),
2557 bt_ctf_event_class_get_id(notit
->meta
.event_class
),
2558 notit
->dscopes
.stream_event_header
);
2562 ret
= bt_ctf_event_set_stream_event_context(event
,
2563 notit
->dscopes
.stream_event_context
);
2565 BT_LOGE("Cannot set event's context field: "
2566 "notit-addr=%p, event-addr=%p, event-class-addr=%p, "
2567 "event-class-name=\"%s\", "
2568 "event-class-id=%" PRId64
", field-addr=%p",
2569 notit
, event
, notit
->meta
.event_class
,
2570 bt_ctf_event_class_get_name(notit
->meta
.event_class
),
2571 bt_ctf_event_class_get_id(notit
->meta
.event_class
),
2572 notit
->dscopes
.stream_event_context
);
2576 ret
= bt_ctf_event_set_event_context(event
,
2577 notit
->dscopes
.event_context
);
2579 BT_LOGE("Cannot set event's stream event context field: "
2580 "notit-addr=%p, event-addr=%p, event-class-addr=%p, "
2581 "event-class-name=\"%s\", "
2582 "event-class-id=%" PRId64
", field-addr=%p",
2583 notit
, event
, notit
->meta
.event_class
,
2584 bt_ctf_event_class_get_name(notit
->meta
.event_class
),
2585 bt_ctf_event_class_get_id(notit
->meta
.event_class
),
2586 notit
->dscopes
.event_context
);
2590 ret
= bt_ctf_event_set_event_payload(event
,
2591 notit
->dscopes
.event_payload
);
2593 BT_LOGE("Cannot set event's payload field: "
2594 "notit-addr=%p, event-addr=%p, event-class-addr=%p, "
2595 "event-class-name=\"%s\", "
2596 "event-class-id=%" PRId64
", field-addr=%p",
2597 notit
, event
, notit
->meta
.event_class
,
2598 bt_ctf_event_class_get_name(notit
->meta
.event_class
),
2599 bt_ctf_event_class_get_id(notit
->meta
.event_class
),
2600 notit
->dscopes
.event_payload
);
2604 ret
= set_event_clocks(event
, notit
);
2606 BT_LOGE("Cannot set event's clock values: "
2607 "notit-addr=%p, event-addr=%p, event-class-addr=%p, "
2608 "event-class-name=\"%s\", "
2609 "event-class-id=%" PRId64
,
2610 notit
, event
, notit
->meta
.event_class
,
2611 bt_ctf_event_class_get_name(notit
->meta
.event_class
),
2612 bt_ctf_event_class_get_id(notit
->meta
.event_class
));
2616 /* Associate with current packet. */
2617 assert(notit
->packet
);
2618 ret
= bt_ctf_event_set_packet(event
, notit
->packet
);
2620 BT_LOGE("Cannot set event's header field: "
2621 "notit-addr=%p, event-addr=%p, event-class-addr=%p, "
2622 "event-class-name=\"%s\", "
2623 "event-class-id=%" PRId64
", packet-addr=%p",
2624 notit
, event
, notit
->meta
.event_class
,
2625 bt_ctf_event_class_get_name(notit
->meta
.event_class
),
2626 bt_ctf_event_class_get_id(notit
->meta
.event_class
),
2641 void create_packet(struct bt_ctf_notif_iter
*notit
)
2644 struct bt_ctf_stream
*stream
= NULL
;
2645 struct bt_ctf_packet
*packet
= NULL
;
2647 BT_LOGV("Creating packet for packet notification: "
2648 "notit-addr=%p", notit
);
2650 /* Ask the user for the stream */
2651 BT_LOGV("Calling user function (get stream): notit-addr=%p, "
2652 "stream-class-addr=%p, stream-class-name=\"%s\", "
2653 "stream-class-id=%" PRId64
,
2654 notit
, notit
->meta
.stream_class
,
2655 bt_ctf_stream_class_get_name(notit
->meta
.stream_class
),
2656 bt_ctf_stream_class_get_id(notit
->meta
.stream_class
));
2657 stream
= notit
->medium
.medops
.get_stream(notit
->meta
.stream_class
,
2658 notit
->medium
.data
);
2659 BT_LOGV("User function returned: stream-addr=%p",
2662 BT_LOGW_STR("User function failed to return a stream object for the given stream class.");
2666 BT_LOGV("Creating packet from stream: "
2667 "notit-addr=%p, stream-addr=%p, "
2668 "stream-class-addr=%p, "
2669 "stream-class-name=\"%s\", "
2670 "stream-class-id=%" PRId64
,
2671 notit
, stream
, notit
->meta
.stream_class
,
2672 bt_ctf_stream_class_get_name(notit
->meta
.stream_class
),
2673 bt_ctf_stream_class_get_id(notit
->meta
.stream_class
));
2676 packet
= bt_ctf_packet_create(stream
);
2678 BT_LOGE("Cannot create packet from stream: "
2679 "notit-addr=%p, stream-addr=%p, "
2680 "stream-class-addr=%p, "
2681 "stream-class-name=\"%s\", "
2682 "stream-class-id=%" PRId64
,
2683 notit
, stream
, notit
->meta
.stream_class
,
2684 bt_ctf_stream_class_get_name(notit
->meta
.stream_class
),
2685 bt_ctf_stream_class_get_id(notit
->meta
.stream_class
));
2689 /* Set packet's context and header fields */
2690 if (notit
->dscopes
.trace_packet_header
) {
2691 ret
= bt_ctf_packet_set_header(packet
,
2692 notit
->dscopes
.trace_packet_header
);
2694 BT_LOGE("Cannot set packet's header field: "
2695 "notit-addr=%p, packet-addr=%p, "
2697 "stream-class-addr=%p, "
2698 "stream-class-name=\"%s\", "
2699 "stream-class-id=%" PRId64
", "
2701 notit
, packet
, stream
, notit
->meta
.stream_class
,
2702 bt_ctf_stream_class_get_name(notit
->meta
.stream_class
),
2703 bt_ctf_stream_class_get_id(notit
->meta
.stream_class
),
2704 notit
->dscopes
.trace_packet_header
);
2709 if (notit
->dscopes
.stream_packet_context
) {
2710 ret
= bt_ctf_packet_set_context(packet
,
2711 notit
->dscopes
.stream_packet_context
);
2713 BT_LOGE("Cannot set packet's context field: "
2714 "notit-addr=%p, packet-addr=%p, "
2716 "stream-class-addr=%p, "
2717 "stream-class-name=\"%s\", "
2718 "stream-class-id=%" PRId64
", "
2720 notit
, packet
, stream
, notit
->meta
.stream_class
,
2721 bt_ctf_stream_class_get_name(notit
->meta
.stream_class
),
2722 bt_ctf_stream_class_get_id(notit
->meta
.stream_class
),
2723 notit
->dscopes
.trace_packet_header
);
2734 BT_MOVE(notit
->packet
, packet
);
2738 void notify_new_packet(struct bt_ctf_notif_iter
*notit
,
2739 struct bt_notification
**notification
)
2741 struct bt_notification
*ret
;
2743 /* Initialize the iterator's current packet */
2744 create_packet(notit
);
2745 if (!notit
->packet
) {
2746 BT_LOGE("Cannot create packet for packet notification: "
2747 "notit-addr=%p", notit
);
2751 ret
= bt_notification_packet_begin_create(notit
->packet
);
2753 BT_LOGE("Cannot create packet beginning notification: "
2754 "notit-addr=%p, packet-addr=%p",
2755 notit
, notit
->packet
);
2758 *notification
= ret
;
2762 void notify_end_of_packet(struct bt_ctf_notif_iter
*notit
,
2763 struct bt_notification
**notification
)
2765 struct bt_notification
*ret
;
2767 if (!notit
->packet
) {
2771 ret
= bt_notification_packet_end_create(notit
->packet
);
2773 BT_LOGE("Cannot create packet end notification: "
2774 "notit-addr=%p, packet-addr=%p",
2775 notit
, notit
->packet
);
2778 BT_PUT(notit
->packet
);
2779 *notification
= ret
;
2783 void notify_event(struct bt_ctf_notif_iter
*notit
,
2784 struct bt_clock_class_priority_map
*cc_prio_map
,
2785 struct bt_notification
**notification
)
2787 struct bt_ctf_event
*event
;
2788 struct bt_notification
*ret
= NULL
;
2791 event
= create_event(notit
);
2793 BT_LOGE("Cannot create event for event notification: "
2794 "notit-addr=%p", notit
);
2798 ret
= bt_notification_event_create(event
, cc_prio_map
);
2800 BT_LOGE("Cannot create event notification: "
2801 "notit-addr=%p, event-addr=%p, "
2802 "cc-prio-map-addr=%p",
2803 notit
, event
, cc_prio_map
);
2806 *notification
= ret
;
2812 int init_clock_states(GHashTable
*clock_states
, struct bt_ctf_trace
*trace
)
2814 int clock_class_count
, i
, ret
= 0;
2817 clock_class_count
= bt_ctf_trace_get_clock_class_count(trace
);
2818 assert(clock_class_count
>= 0);
2820 for (i
= 0; i
< clock_class_count
; i
++) {
2821 struct bt_ctf_clock_class
*clock_class
;
2823 clock_class
= bt_ctf_trace_get_clock_class_by_index(trace
, i
);
2824 assert(clock_class
);
2825 g_hash_table_insert(clock_states
, bt_get(clock_class
), NULL
);
2826 bt_put(clock_class
);
2833 void init_trace_field_path_cache(struct bt_ctf_trace
*trace
,
2834 struct trace_field_path_cache
*trace_field_path_cache
)
2837 int stream_instance_id
= -1;
2839 struct bt_ctf_field_type
*packet_header
= NULL
;
2841 packet_header
= bt_ctf_trace_get_packet_header_type(trace
);
2842 if (!packet_header
) {
2846 if (!bt_ctf_field_type_is_structure(packet_header
)) {
2850 count
= bt_ctf_field_type_structure_get_field_count(packet_header
);
2853 for (i
= 0; (i
< count
&& (stream_id
== -1 || stream_instance_id
== -1)); i
++) {
2855 const char *field_name
;
2857 ret
= bt_ctf_field_type_structure_get_field(packet_header
,
2858 &field_name
, NULL
, i
);
2860 BT_LOGE("Cannot get structure field's field: "
2861 "field-addr=%p, index=%d",
2866 if (stream_id
== -1 && !strcmp(field_name
, "stream_id")) {
2868 } else if (stream_instance_id
== -1 &&
2869 !strcmp(field_name
, "stream_instance_id")) {
2870 stream_instance_id
= i
;
2875 trace_field_path_cache
->stream_id
= stream_id
;
2876 trace_field_path_cache
->stream_instance_id
= stream_instance_id
;
2877 BT_PUT(packet_header
);
2881 struct bt_ctf_notif_iter
*bt_ctf_notif_iter_create(struct bt_ctf_trace
*trace
,
2882 size_t max_request_sz
,
2883 struct bt_ctf_notif_iter_medium_ops medops
, void *data
)
2886 struct bt_ctf_notif_iter
*notit
= NULL
;
2887 struct bt_ctf_btr_cbs cbs
= {
2889 .signed_int
= btr_signed_int_cb
,
2890 .unsigned_int
= btr_unsigned_int_cb
,
2891 .floating_point
= btr_floating_point_cb
,
2892 .string_begin
= btr_string_begin_cb
,
2893 .string
= btr_string_cb
,
2894 .string_end
= btr_string_end_cb
,
2895 .compound_begin
= btr_compound_begin_cb
,
2896 .compound_end
= btr_compound_end_cb
,
2899 .get_sequence_length
= btr_get_sequence_length_cb
,
2900 .get_variant_type
= btr_get_variant_type_cb
,
2905 assert(medops
.request_bytes
);
2906 assert(medops
.get_stream
);
2907 BT_LOGD("Creating CTF plugin notification iterator: "
2908 "trace-addr=%p, trace-name=\"%s\", max-request-size=%zu, "
2910 trace
, bt_ctf_trace_get_name(trace
), max_request_sz
, data
);
2911 notit
= g_new0(struct bt_ctf_notif_iter
, 1);
2913 BT_LOGE_STR("Failed to allocate one CTF plugin notification iterator.");
2916 notit
->clock_states
= g_hash_table_new_full(g_direct_hash
,
2917 g_direct_equal
, bt_put
, g_free
);
2918 if (!notit
->clock_states
) {
2919 BT_LOGE_STR("Failed to allocate a GHashTable.");
2922 ret
= init_clock_states(notit
->clock_states
, trace
);
2924 BT_LOGW("Cannot initialize clock values.");
2927 notit
->meta
.trace
= bt_get(trace
);
2928 notit
->medium
.medops
= medops
;
2929 notit
->medium
.max_request_sz
= max_request_sz
;
2930 notit
->medium
.data
= data
;
2931 notit
->stack
= stack_new(notit
);
2932 if (!notit
->stack
) {
2933 BT_LOGE_STR("Failed to create field stack.");
2937 notit
->btr
= bt_ctf_btr_create(cbs
, notit
);
2939 BT_LOGE_STR("Failed to create binary type reader (BTR).");
2943 bt_ctf_notif_iter_reset(notit
);
2944 init_trace_field_path_cache(trace
, ¬it
->trace_field_path_cache
);
2945 notit
->sc_field_path_caches
= g_hash_table_new_full(g_direct_hash
,
2946 g_direct_equal
, bt_put
, g_free
);
2947 if (!notit
->sc_field_path_caches
) {
2948 BT_LOGE_STR("Failed to allocate a GHashTable.");
2952 notit
->field_overrides
= g_hash_table_new_full(g_direct_hash
,
2953 g_direct_equal
, bt_put
, g_free
);
2954 if (!notit
->field_overrides
) {
2955 BT_LOGE_STR("Failed to allocate a GHashTable.");
2959 BT_LOGD("Created CTF plugin notification iterator: "
2960 "trace-addr=%p, trace-name=\"%s\", max-request-size=%zu, "
2961 "data=%p, notit-addr=%p",
2962 trace
, bt_ctf_trace_get_name(trace
), max_request_sz
, data
,
2969 bt_ctf_notif_iter_destroy(notit
);
2974 void bt_ctf_notif_iter_destroy(struct bt_ctf_notif_iter
*notit
)
2976 BT_PUT(notit
->meta
.trace
);
2977 BT_PUT(notit
->meta
.stream_class
);
2978 BT_PUT(notit
->meta
.event_class
);
2979 BT_PUT(notit
->packet
);
2980 BT_PUT(notit
->cur_timestamp_end
);
2981 put_all_dscopes(notit
);
2983 BT_LOGD("Destroying CTF plugin notification iterator: addr=%p", notit
);
2986 BT_LOGD_STR("Destroying field stack.");
2987 stack_destroy(notit
->stack
);
2991 BT_LOGD("Destroying BTR: btr-addr=%p", notit
->btr
);
2992 bt_ctf_btr_destroy(notit
->btr
);
2995 if (notit
->clock_states
) {
2996 g_hash_table_destroy(notit
->clock_states
);
2999 if (notit
->sc_field_path_caches
) {
3000 g_hash_table_destroy(notit
->sc_field_path_caches
);
3003 if (notit
->field_overrides
) {
3004 g_hash_table_destroy(notit
->field_overrides
);
3010 enum bt_ctf_notif_iter_status
bt_ctf_notif_iter_get_next_notification(
3011 struct bt_ctf_notif_iter
*notit
,
3012 struct bt_clock_class_priority_map
*cc_prio_map
,
3013 struct bt_notification
**notification
)
3015 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
3018 assert(notification
);
3020 BT_LOGV("Getting next notification: notit-addr=%p, cc-prio-map-addr=%p",
3021 notit
, cc_prio_map
);
3024 status
= handle_state(notit
);
3025 if (status
== BT_CTF_NOTIF_ITER_STATUS_AGAIN
) {
3026 BT_LOGV_STR("Medium returned BT_CTF_NOTIF_ITER_STATUS_AGAIN.");
3029 if (status
!= BT_CTF_NOTIF_ITER_STATUS_OK
) {
3030 if (status
== BT_CTF_NOTIF_ITER_STATUS_EOF
) {
3031 BT_LOGV_STR("Medium returned BT_CTF_NOTIF_ITER_STATUS_EOF.");
3033 BT_LOGW("Cannot handle state: "
3034 "notit-addr=%p, state=%s",
3035 notit
, state_string(notit
->state
));
3040 switch (notit
->state
) {
3041 case STATE_EMIT_NOTIF_NEW_PACKET
:
3042 /* notify_new_packet() logs errors */
3043 notify_new_packet(notit
, notification
);
3044 if (!*notification
) {
3045 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
3048 case STATE_EMIT_NOTIF_EVENT
:
3049 /* notify_event() logs errors */
3050 notify_event(notit
, cc_prio_map
, notification
);
3051 if (!*notification
) {
3052 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
3055 case STATE_EMIT_NOTIF_END_OF_PACKET
:
3056 /* Update clock with timestamp_end field. */
3057 if (notit
->cur_timestamp_end
) {
3058 enum bt_ctf_btr_status btr_status
;
3059 struct bt_ctf_field_type
*field_type
=
3060 bt_ctf_field_get_type(
3061 notit
->cur_timestamp_end
);
3064 btr_status
= update_clock(notit
,
3065 notit
->cur_timestamp_end
);
3067 if (btr_status
!= BT_CTF_BTR_STATUS_OK
) {
3068 BT_LOGW("Cannot update stream's clock value: "
3069 "notit-addr=%p", notit
);
3070 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
3075 /* notify_end_of_packet() logs errors */
3076 notify_end_of_packet(notit
, notification
);
3077 if (!*notification
) {
3078 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
3082 /* Non-emitting state: continue */
3092 enum bt_ctf_notif_iter_status
bt_ctf_notif_iter_get_packet_header_context_fields(
3093 struct bt_ctf_notif_iter
*notit
,
3094 struct bt_ctf_field
**packet_header_field
,
3095 struct bt_ctf_field
**packet_context_field
)
3097 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
3101 if (notit
->state
== STATE_EMIT_NOTIF_NEW_PACKET
) {
3102 /* We're already there */
3107 status
= handle_state(notit
);
3108 if (status
== BT_CTF_NOTIF_ITER_STATUS_AGAIN
) {
3109 BT_LOGV_STR("Medium returned BT_CTF_NOTIF_ITER_STATUS_AGAIN.");
3112 if (status
!= BT_CTF_NOTIF_ITER_STATUS_OK
) {
3113 if (status
== BT_CTF_NOTIF_ITER_STATUS_EOF
) {
3114 BT_LOGV_STR("Medium returned BT_CTF_NOTIF_ITER_STATUS_EOF.");
3116 BT_LOGW("Cannot handle state: "
3117 "notit-addr=%p, state=%s",
3118 notit
, state_string(notit
->state
));
3123 switch (notit
->state
) {
3124 case STATE_EMIT_NOTIF_NEW_PACKET
:
3126 * Packet header and context fields are
3127 * potentially decoded (or they don't exist).
3131 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
:
3132 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
:
3133 case STATE_AFTER_TRACE_PACKET_HEADER
:
3134 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
:
3135 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
:
3136 case STATE_AFTER_STREAM_PACKET_CONTEXT
:
3137 /* Non-emitting state: continue */
3141 * We should never get past the
3142 * STATE_EMIT_NOTIF_NEW_PACKET state.
3144 BT_LOGF("Unexpected state: notit-addr=%p, state=%s",
3145 notit
, state_string(notit
->state
));
3151 if (packet_header_field
) {
3152 *packet_header_field
= bt_get(notit
->dscopes
.trace_packet_header
);
3155 if (packet_context_field
) {
3156 *packet_context_field
= bt_get(notit
->dscopes
.stream_packet_context
);