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
33 #include <babeltrace/ctf-ir/field-types.h>
34 #include <babeltrace/ctf-ir/field-path.h>
35 #include <babeltrace/ctf-ir/fields.h>
36 #include <babeltrace/ctf-ir/stream-class.h>
37 #include <babeltrace/ctf-ir/packet.h>
38 #include <babeltrace/ctf-ir/stream.h>
39 #include <babeltrace/ctf-ir/clock-class.h>
40 #include <babeltrace/ctf-ir/event-class.h>
41 #include <babeltrace/graph/notification-packet.h>
42 #include <babeltrace/graph/notification-event.h>
43 #include <babeltrace/graph/notification-stream.h>
44 #include <babeltrace/graph/clock-class-priority-map.h>
45 #include <babeltrace/ref.h>
49 #define PRINT_ERR_STREAM notit->err_stream
50 #define PRINT_PREFIX "ctf-notif-iter"
53 #include "notif-iter.h"
54 #include "../btr/btr.h"
56 #define BYTES_TO_BITS(x) ((x) * 8)
58 struct bt_ctf_notif_iter
;
60 /* A visit stack entry */
63 * Current base field, one of:
71 * Field is owned by this.
73 struct bt_ctf_field
*base
;
75 /* index of next field to set */
81 /* Entries (struct stack_entry *) (top is last element) */
88 STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
,
89 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
,
90 STATE_AFTER_TRACE_PACKET_HEADER
,
91 STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
,
92 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
,
93 STATE_AFTER_STREAM_PACKET_CONTEXT
,
94 STATE_EMIT_NOTIF_NEW_PACKET
,
95 STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN
,
96 STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE
,
97 STATE_AFTER_STREAM_EVENT_HEADER
,
98 STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN
,
99 STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE
,
100 STATE_DSCOPE_EVENT_CONTEXT_BEGIN
,
101 STATE_DSCOPE_EVENT_CONTEXT_CONTINUE
,
102 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
,
103 STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
,
104 STATE_EMIT_NOTIF_EVENT
,
105 STATE_EMIT_NOTIF_END_OF_PACKET
,
106 STATE_SKIP_PACKET_PADDING
,
109 struct trace_field_path_cache
{
111 * Indexes of the stream_id and stream_instance_id field in the packet
112 * header structure, -1 if unset.
115 int stream_instance_id
;
118 struct stream_class_field_path_cache
{
120 * Indexes of the v and id fields in the stream event header structure,
127 * index of the timestamp_end, packet_size and content_size fields in
128 * the stream packet context structure. Set to -1 if the fields were
136 struct field_cb_override
{
137 enum bt_ctf_btr_status (* func
)(void *value
,
138 struct bt_ctf_field_type
*type
, void *data
);
142 /* CTF notification iterator */
143 struct bt_ctf_notif_iter
{
147 /* Error stream (may be NULL) */
151 * Current dynamic scope field pointer.
153 * This is set when a dynamic scope field is first created by
154 * btr_compound_begin_cb(). It points to one of the fields in
157 struct bt_ctf_field
**cur_dscope_field
;
159 /* Trace and classes (owned by this) */
161 struct bt_ctf_trace
*trace
;
162 struct bt_ctf_stream_class
*stream_class
;
163 struct bt_ctf_event_class
*event_class
;
166 /* Current packet (NULL if not created yet) */
167 struct bt_ctf_packet
*packet
;
170 * Current timestamp_end field (to consider before switching packets).
172 struct bt_ctf_field
*cur_timestamp_end
;
174 /* Database of current dynamic scopes (owned by this) */
176 struct bt_ctf_field
*trace_packet_header
;
177 struct bt_ctf_field
*stream_packet_context
;
178 struct bt_ctf_field
*stream_event_header
;
179 struct bt_ctf_field
*stream_event_context
;
180 struct bt_ctf_field
*event_context
;
181 struct bt_ctf_field
*event_payload
;
185 * Special field overrides.
187 * Overrides are used to implement the behaviours of special fields such
188 * as "timestamp_end" (which must be ignored until the end of the
189 * packet), "id" (event id) which can be present multiple times and must
190 * be updated multiple time.
192 * This should be used to implement the behaviour of integer fields
193 * mapped to clocks and other "tagged" fields (in CTF 2).
195 * bt_ctf_field_type to struct field_cb_override
197 GHashTable
*field_overrides
;
202 /* Current medium buffer data */
204 /* Last address provided by medium */
207 /* Buffer size provided by medium (bytes) */
210 /* Offset within whole packet of addr (bits) */
211 size_t packet_offset
;
213 /* Current position from addr (bits) */
217 /* Binary type reader */
218 struct bt_ctf_btr
*btr
;
220 /* Current medium data */
222 struct bt_ctf_notif_iter_medium_ops medops
;
223 size_t max_request_sz
;
227 /* Current packet size (bits) (-1 if unknown) */
228 int64_t cur_packet_size
;
230 /* Current content size (bits) (-1 if unknown) */
231 int64_t cur_content_size
;
233 /* bt_ctf_clock_class to uint64_t. */
234 GHashTable
*clock_states
;
237 * Cache of the trace-constant field paths (event header type)
238 * associated to the current trace.
240 struct trace_field_path_cache trace_field_path_cache
;
243 * Field path cache associated with the current stream class.
244 * Ownership of this structure belongs to the field_path_caches HT.
246 struct stream_class_field_path_cache
*cur_sc_field_path_cache
;
248 /* bt_ctf_stream_class to struct stream_class_field_path_cache. */
249 GHashTable
*sc_field_path_caches
;
253 int bt_ctf_notif_iter_switch_packet(struct bt_ctf_notif_iter
*notit
);
256 enum bt_ctf_btr_status
btr_timestamp_end_cb(void *value
,
257 struct bt_ctf_field_type
*type
, void *data
);
260 void stack_entry_free_func(gpointer data
)
262 struct stack_entry
*entry
= data
;
269 struct stack
*stack_new(struct bt_ctf_notif_iter
*notit
)
271 struct stack
*stack
= NULL
;
273 stack
= g_new0(struct stack
, 1);
278 stack
->entries
= g_ptr_array_new_with_free_func(stack_entry_free_func
);
279 if (!stack
->entries
) {
290 void stack_destroy(struct stack
*stack
)
293 g_ptr_array_free(stack
->entries
, TRUE
);
298 int stack_push(struct stack
*stack
, struct bt_ctf_field
*base
)
301 struct stack_entry
*entry
;
305 entry
= g_new0(struct stack_entry
, 1);
311 entry
->base
= bt_get(base
);
312 g_ptr_array_add(stack
->entries
, entry
);
319 unsigned int stack_size(struct stack
*stack
)
323 return stack
->entries
->len
;
327 void stack_pop(struct stack
*stack
)
330 assert(stack_size(stack
));
331 g_ptr_array_remove_index(stack
->entries
, stack
->entries
->len
- 1);
335 struct stack_entry
*stack_top(struct stack
*stack
)
338 assert(stack_size(stack
));
340 return g_ptr_array_index(stack
->entries
, stack
->entries
->len
- 1);
344 bool stack_empty(struct stack
*stack
)
346 return stack_size(stack
) == 0;
350 void stack_clear(struct stack
*stack
)
354 if (!stack_empty(stack
)) {
355 g_ptr_array_remove_range(stack
->entries
, 0, stack_size(stack
));
358 assert(stack_empty(stack
));
362 enum bt_ctf_notif_iter_status
notif_iter_status_from_m_status(
363 enum bt_ctf_notif_iter_medium_status m_status
)
365 return (int) m_status
;
369 size_t buf_size_bits(struct bt_ctf_notif_iter
*notit
)
371 return BYTES_TO_BITS(notit
->buf
.sz
);
375 size_t buf_available_bits(struct bt_ctf_notif_iter
*notit
)
377 return buf_size_bits(notit
) - notit
->buf
.at
;
381 size_t packet_at(struct bt_ctf_notif_iter
*notit
)
383 return notit
->buf
.packet_offset
+ notit
->buf
.at
;
387 void buf_consume_bits(struct bt_ctf_notif_iter
*notit
, size_t incr
)
389 notit
->buf
.at
+= incr
;
393 enum bt_ctf_notif_iter_status
request_medium_bytes(
394 struct bt_ctf_notif_iter
*notit
)
396 uint8_t *buffer_addr
;
398 enum bt_ctf_notif_iter_medium_status m_status
;
400 m_status
= notit
->medium
.medops
.request_bytes(
401 notit
->medium
.max_request_sz
, &buffer_addr
,
402 &buffer_sz
, notit
->medium
.data
);
403 if (m_status
== BT_CTF_NOTIF_ITER_MEDIUM_STATUS_OK
) {
404 assert(buffer_sz
!= 0);
406 /* New packet offset is old one + old size (in bits) */
407 notit
->buf
.packet_offset
+= buf_size_bits(notit
);
409 /* Restart at the beginning of the new medium buffer */
412 /* New medium buffer size */
413 notit
->buf
.sz
= buffer_sz
;
415 /* New medium buffer address */
416 notit
->buf
.addr
= buffer_addr
;
419 return notif_iter_status_from_m_status(m_status
);
423 enum bt_ctf_notif_iter_status
buf_ensure_available_bits(
424 struct bt_ctf_notif_iter
*notit
)
426 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
428 if (buf_available_bits(notit
) == 0) {
430 * This _cannot_ return BT_CTF_NOTIF_ITER_STATUS_OK
433 status
= request_medium_bytes(notit
);
440 enum bt_ctf_notif_iter_status
read_dscope_begin_state(
441 struct bt_ctf_notif_iter
*notit
,
442 struct bt_ctf_field_type
*dscope_field_type
,
443 enum state done_state
, enum state continue_state
,
444 struct bt_ctf_field
**dscope_field
)
446 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
447 enum bt_ctf_btr_status btr_status
;
448 size_t consumed_bits
;
450 status
= buf_ensure_available_bits(notit
);
451 if (status
!= BT_CTF_NOTIF_ITER_STATUS_OK
) {
455 bt_put(*dscope_field
);
456 notit
->cur_dscope_field
= dscope_field
;
457 consumed_bits
= bt_ctf_btr_start(notit
->btr
, dscope_field_type
,
458 notit
->buf
.addr
, notit
->buf
.at
, packet_at(notit
),
459 notit
->buf
.sz
, &btr_status
);
461 switch (btr_status
) {
462 case BT_CTF_BTR_STATUS_OK
:
463 /* type was read completely */
464 notit
->state
= done_state
;
466 case BT_CTF_BTR_STATUS_EOF
:
467 notit
->state
= continue_state
;
470 PERR("Binary type reader failed to start\n");
471 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
475 /* Consume bits now since we know we're not in an error state */
476 buf_consume_bits(notit
, consumed_bits
);
483 enum bt_ctf_notif_iter_status
read_dscope_continue_state(
484 struct bt_ctf_notif_iter
*notit
, enum state done_state
)
486 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
487 enum bt_ctf_btr_status btr_status
;
488 size_t consumed_bits
;
490 status
= buf_ensure_available_bits(notit
);
491 if (status
!= BT_CTF_NOTIF_ITER_STATUS_OK
) {
495 consumed_bits
= bt_ctf_btr_continue(notit
->btr
, notit
->buf
.addr
,
496 notit
->buf
.sz
, &btr_status
);
498 switch (btr_status
) {
499 case BT_CTF_BTR_STATUS_OK
:
500 /* Type was read completely. */
501 notit
->state
= done_state
;
503 case BT_CTF_BTR_STATUS_EOF
:
504 /* Stay in this continue state. */
507 PERR("Binary type reader failed to continue\n");
508 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
512 /* Consume bits now since we know we're not in an error state. */
513 buf_consume_bits(notit
, consumed_bits
);
519 void put_event_dscopes(struct bt_ctf_notif_iter
*notit
)
521 BT_PUT(notit
->dscopes
.stream_event_header
);
522 BT_PUT(notit
->dscopes
.stream_event_context
);
523 BT_PUT(notit
->dscopes
.event_context
);
524 BT_PUT(notit
->dscopes
.event_payload
);
528 void put_all_dscopes(struct bt_ctf_notif_iter
*notit
)
530 BT_PUT(notit
->dscopes
.trace_packet_header
);
531 BT_PUT(notit
->dscopes
.stream_packet_context
);
532 put_event_dscopes(notit
);
536 enum bt_ctf_notif_iter_status
read_packet_header_begin_state(
537 struct bt_ctf_notif_iter
*notit
)
539 struct bt_ctf_field_type
*packet_header_type
= NULL
;
540 enum bt_ctf_notif_iter_status ret
= BT_CTF_NOTIF_ITER_STATUS_OK
;
542 if (bt_ctf_notif_iter_switch_packet(notit
)) {
543 ret
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
547 /* Packet header type is common to the whole trace. */
548 packet_header_type
= bt_ctf_trace_get_packet_header_type(
550 if (!packet_header_type
) {
551 notit
->state
= STATE_AFTER_TRACE_PACKET_HEADER
;
555 ret
= read_dscope_begin_state(notit
, packet_header_type
,
556 STATE_AFTER_TRACE_PACKET_HEADER
,
557 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
,
558 ¬it
->dscopes
.trace_packet_header
);
560 BT_PUT(packet_header_type
);
565 enum bt_ctf_notif_iter_status
read_packet_header_continue_state(
566 struct bt_ctf_notif_iter
*notit
)
568 return read_dscope_continue_state(notit
,
569 STATE_AFTER_TRACE_PACKET_HEADER
);
573 bool is_struct_type(struct bt_ctf_field_type
*field_type
)
575 return bt_ctf_field_type_get_type_id(field_type
) ==
576 BT_CTF_FIELD_TYPE_ID_STRUCT
;
580 bool is_variant_type(struct bt_ctf_field_type
*field_type
)
582 return bt_ctf_field_type_get_type_id(field_type
) ==
583 BT_CTF_FIELD_TYPE_ID_VARIANT
;
587 struct stream_class_field_path_cache
*
588 create_stream_class_field_path_cache_entry(
589 struct bt_ctf_notif_iter
*notit
,
590 struct bt_ctf_stream_class
*stream_class
)
594 int timestamp_end
= -1;
595 int packet_size
= -1;
596 int content_size
= -1;
597 struct stream_class_field_path_cache
*cache_entry
= g_new0(
598 struct stream_class_field_path_cache
, 1);
599 struct bt_ctf_field_type
*event_header
= NULL
, *packet_context
= NULL
;
605 event_header
= bt_ctf_stream_class_get_event_header_type(stream_class
);
606 if (event_header
&& bt_ctf_field_type_is_structure(event_header
)) {
609 count
= bt_ctf_field_type_structure_get_field_count(
614 for (i
= 0; i
< count
; i
++) {
618 ret
= bt_ctf_field_type_structure_get_field(
619 event_header
, &name
, NULL
, i
);
624 if (v
!= -1 && id
!= -1) {
627 if (v
== -1 && !strcmp(name
, "v")) {
629 } else if (id
== -1 && !strcmp(name
, "id")) {
635 packet_context
= bt_ctf_stream_class_get_packet_context_type(
637 if (packet_context
&& bt_ctf_field_type_is_structure(packet_context
)) {
640 count
= bt_ctf_field_type_structure_get_field_count(
645 for (i
= 0; i
< count
; i
++) {
648 struct bt_ctf_field_type
*field_type
;
650 if (timestamp_end
!= -1 && packet_size
!= -1 &&
651 content_size
!= -1) {
655 ret
= bt_ctf_field_type_structure_get_field(
656 packet_context
, &name
, &field_type
, i
);
661 if (timestamp_end
== -1 &&
662 !strcmp(name
, "timestamp_end")) {
663 struct field_cb_override
*override
= g_new0(
664 struct field_cb_override
, 1);
671 override
->func
= btr_timestamp_end_cb
;
672 override
->data
= notit
;
674 g_hash_table_insert(notit
->field_overrides
,
675 bt_get(field_type
), override
);
678 } else if (packet_size
== -1 &&
679 !strcmp(name
, "packet_size")) {
681 } else if (content_size
== -1 &&
682 !strcmp(name
, "content_size")) {
690 cache_entry
->id
= id
;
691 cache_entry
->timestamp_end
= timestamp_end
;
692 cache_entry
->packet_size
= packet_size
;
693 cache_entry
->content_size
= content_size
;
695 BT_PUT(event_header
);
696 BT_PUT(packet_context
);
705 struct stream_class_field_path_cache
*get_stream_class_field_path_cache(
706 struct bt_ctf_notif_iter
*notit
,
707 struct bt_ctf_stream_class
*stream_class
)
709 bool cache_entry_found
;
710 struct stream_class_field_path_cache
*cache_entry
;
712 cache_entry_found
= g_hash_table_lookup_extended(
713 notit
->sc_field_path_caches
,
714 stream_class
, NULL
, (gpointer
) &cache_entry
);
715 if (unlikely(!cache_entry_found
)) {
716 cache_entry
= create_stream_class_field_path_cache_entry(notit
,
718 g_hash_table_insert(notit
->sc_field_path_caches
,
719 bt_get(stream_class
), (gpointer
) cache_entry
);
726 enum bt_ctf_notif_iter_status
set_current_stream_class(
727 struct bt_ctf_notif_iter
*notit
)
729 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
730 struct bt_ctf_field_type
*packet_header_type
= NULL
;
731 struct bt_ctf_field_type
*stream_id_field_type
= NULL
;
734 /* Clear the current stream class field path cache. */
735 notit
->cur_sc_field_path_cache
= NULL
;
737 /* Is there any "stream_id" field in the packet header? */
738 packet_header_type
= bt_ctf_trace_get_packet_header_type(
740 if (!packet_header_type
) {
741 PERR("Failed to retrieve trace's packet header type\n");
742 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
746 assert(is_struct_type(packet_header_type
));
749 stream_id_field_type
=
750 bt_ctf_field_type_structure_get_field_type_by_name(
751 packet_header_type
, "stream_id");
752 if (stream_id_field_type
) {
753 /* Find appropriate stream class using current stream ID */
755 struct bt_ctf_field
*stream_id_field
= NULL
;
757 assert(notit
->dscopes
.trace_packet_header
);
760 stream_id_field
= bt_ctf_field_structure_get_field(
761 notit
->dscopes
.trace_packet_header
, "stream_id");
762 assert(stream_id_field
);
763 ret
= bt_ctf_field_unsigned_integer_get_value(
764 stream_id_field
, &stream_id
);
766 BT_PUT(stream_id_field
);
768 /* Only one stream: pick the first stream class */
769 assert(bt_ctf_trace_get_stream_class_count(
770 notit
->meta
.trace
) == 1);
774 BT_PUT(notit
->meta
.stream_class
);
775 notit
->meta
.stream_class
= bt_ctf_trace_get_stream_class_by_id(
776 notit
->meta
.trace
, stream_id
);
777 if (!notit
->meta
.stream_class
) {
778 PERR("Cannot find stream class with ID %" PRIu64
"\n",
780 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
785 * Retrieve (or lazily create) the current stream class field path
788 notit
->cur_sc_field_path_cache
= get_stream_class_field_path_cache(
789 notit
, notit
->meta
.stream_class
);
790 if (!notit
->cur_sc_field_path_cache
) {
791 PERR("Failed to retrieve stream class field path cache\n");
792 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
796 BT_PUT(packet_header_type
);
797 BT_PUT(stream_id_field_type
);
803 enum bt_ctf_notif_iter_status
after_packet_header_state(
804 struct bt_ctf_notif_iter
*notit
)
806 enum bt_ctf_notif_iter_status status
;
808 status
= set_current_stream_class(notit
);
809 if (status
== BT_CTF_NOTIF_ITER_STATUS_OK
) {
810 notit
->state
= STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
;
817 enum bt_ctf_notif_iter_status
read_packet_context_begin_state(
818 struct bt_ctf_notif_iter
*notit
)
820 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
821 struct bt_ctf_field_type
*packet_context_type
;
823 assert(notit
->meta
.stream_class
);
824 packet_context_type
= bt_ctf_stream_class_get_packet_context_type(
825 notit
->meta
.stream_class
);
826 if (!packet_context_type
) {
827 notit
->state
= STATE_AFTER_STREAM_PACKET_CONTEXT
;
831 status
= read_dscope_begin_state(notit
, packet_context_type
,
832 STATE_AFTER_STREAM_PACKET_CONTEXT
,
833 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
,
834 ¬it
->dscopes
.stream_packet_context
);
837 BT_PUT(packet_context_type
);
842 enum bt_ctf_notif_iter_status
read_packet_context_continue_state(
843 struct bt_ctf_notif_iter
*notit
)
845 return read_dscope_continue_state(notit
,
846 STATE_AFTER_STREAM_PACKET_CONTEXT
);
850 enum bt_ctf_notif_iter_status
set_current_packet_content_sizes(
851 struct bt_ctf_notif_iter
*notit
)
853 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
854 struct bt_ctf_field
*packet_size_field
= NULL
;
855 struct bt_ctf_field
*content_size_field
= NULL
;
856 uint64_t content_size
= -1, packet_size
= -1;
858 assert(notit
->dscopes
.stream_packet_context
);
860 packet_size_field
= bt_ctf_field_structure_get_field(
861 notit
->dscopes
.stream_packet_context
, "packet_size");
862 content_size_field
= bt_ctf_field_structure_get_field(
863 notit
->dscopes
.stream_packet_context
, "content_size");
864 if (packet_size_field
) {
865 int ret
= bt_ctf_field_unsigned_integer_get_value(
866 packet_size_field
, &packet_size
);
869 if (packet_size
== 0) {
870 PERR("Decoded packet size is 0\n");
871 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
873 } else if ((packet_size
% 8) != 0) {
874 PERR("Decoded packet size is not a multiple of 8\n");
875 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
880 if (content_size_field
) {
881 int ret
= bt_ctf_field_unsigned_integer_get_value(
882 content_size_field
, &content_size
);
886 content_size
= packet_size
;
889 notit
->cur_packet_size
= packet_size
;
890 notit
->cur_content_size
= content_size
;
892 BT_PUT(packet_size_field
);
893 BT_PUT(content_size_field
);
898 enum bt_ctf_notif_iter_status
after_packet_context_state(
899 struct bt_ctf_notif_iter
*notit
)
901 enum bt_ctf_notif_iter_status status
;
903 status
= set_current_packet_content_sizes(notit
);
904 if (status
== BT_CTF_NOTIF_ITER_STATUS_OK
) {
905 notit
->state
= STATE_EMIT_NOTIF_NEW_PACKET
;
912 enum bt_ctf_notif_iter_status
read_event_header_begin_state(
913 struct bt_ctf_notif_iter
*notit
)
915 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
916 struct bt_ctf_field_type
*event_header_type
= NULL
;
918 /* Check if we have some content left */
919 if (notit
->cur_content_size
>= 0) {
920 if (packet_at(notit
) == notit
->cur_content_size
) {
921 /* No more events! */
922 notit
->state
= STATE_EMIT_NOTIF_END_OF_PACKET
;
924 } else if (packet_at(notit
) > notit
->cur_content_size
) {
925 /* That's not supposed to happen */
926 PERR("Cursor passed packet's content size:\n");
927 PERR("\tDecoded content size: %zu\n",
928 notit
->cur_content_size
);
929 PERR("\tCursor position: %zu\n", packet_at(notit
));
930 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
935 event_header_type
= bt_ctf_stream_class_get_event_header_type(
936 notit
->meta
.stream_class
);
937 if (!event_header_type
) {
938 notit
->state
= STATE_AFTER_STREAM_EVENT_HEADER
;
942 put_event_dscopes(notit
);
943 status
= read_dscope_begin_state(notit
, event_header_type
,
944 STATE_AFTER_STREAM_EVENT_HEADER
,
945 STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE
,
946 ¬it
->dscopes
.stream_event_header
);
948 BT_PUT(event_header_type
);
954 enum bt_ctf_notif_iter_status
read_event_header_continue_state(
955 struct bt_ctf_notif_iter
*notit
)
957 return read_dscope_continue_state(notit
,
958 STATE_AFTER_STREAM_EVENT_HEADER
);
962 enum bt_ctf_notif_iter_status
set_current_event_class(struct bt_ctf_notif_iter
*notit
)
965 * The assert() calls in this function are okay because it is
966 * assumed here that all the metadata objects have been
967 * validated for CTF correctness before decoding actual streams.
970 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
971 struct bt_ctf_field_type
*event_header_type
;
972 struct bt_ctf_field_type
*id_field_type
= NULL
;
973 struct bt_ctf_field_type
*v_field_type
= NULL
;
974 uint64_t event_id
= -1ULL;
977 event_header_type
= bt_ctf_stream_class_get_event_header_type(
978 notit
->meta
.stream_class
);
979 if (!event_header_type
) {
980 PERR("Failed to retrieve stream class's event header type\n");
981 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
985 /* Is there any "id"/"v" field in the event header? */
986 assert(is_struct_type(event_header_type
));
987 id_field_type
= bt_ctf_field_type_structure_get_field_type_by_name(
988 event_header_type
, "id");
989 v_field_type
= bt_ctf_field_type_structure_get_field_type_by_name(
990 event_header_type
, "v");
991 assert(notit
->dscopes
.stream_event_header
);
995 * | | |_ _|_ _| __ __ _
996 * | | | | | || '_ \ / _` |
997 * | |___| | | || | | | (_| | S P E C I A L
998 * |_____|_| |_||_| |_|\__, | C A S E â„¢
1001 struct bt_ctf_field
*v_field
= NULL
;
1002 struct bt_ctf_field
*v_struct_field
= NULL
;
1003 struct bt_ctf_field
*v_struct_id_field
= NULL
;
1005 // TODO: optimalize!
1006 v_field
= bt_ctf_field_structure_get_field(
1007 notit
->dscopes
.stream_event_header
, "v");
1011 bt_ctf_field_variant_get_current_field(v_field
);
1012 if (!v_struct_field
) {
1013 goto end_v_field_type
;
1016 // TODO: optimalize!
1018 bt_ctf_field_structure_get_field(v_struct_field
, "id");
1019 if (!v_struct_id_field
) {
1020 goto end_v_field_type
;
1023 ret
= bt_ctf_field_unsigned_integer_get_value(
1024 v_struct_id_field
, &event_id
);
1031 BT_PUT(v_struct_field
);
1032 BT_PUT(v_struct_id_field
);
1035 if (id_field_type
&& event_id
== -1ULL) {
1036 /* Check "id" field */
1037 struct bt_ctf_field
*id_field
= NULL
;
1040 // TODO: optimalize!
1041 id_field
= bt_ctf_field_structure_get_field(
1042 notit
->dscopes
.stream_event_header
, "id");
1044 assert(bt_ctf_field_is_integer(id_field
) ||
1045 bt_ctf_field_is_enumeration(id_field
));
1047 if (bt_ctf_field_is_integer(id_field
)) {
1048 ret
= bt_ctf_field_unsigned_integer_get_value(
1049 id_field
, &event_id
);
1051 struct bt_ctf_field
*container
;
1053 container
= bt_ctf_field_enumeration_get_container(
1056 ret
= bt_ctf_field_unsigned_integer_get_value(
1057 container
, &event_id
);
1064 if (event_id
== -1ULL) {
1065 /* Event ID not found: single event? */
1066 assert(bt_ctf_stream_class_get_event_class_count(
1067 notit
->meta
.stream_class
) == 1);
1071 BT_PUT(notit
->meta
.event_class
);
1072 notit
->meta
.event_class
= bt_ctf_stream_class_get_event_class_by_id(
1073 notit
->meta
.stream_class
, event_id
);
1074 if (!notit
->meta
.event_class
) {
1075 PERR("Cannot find event class with ID %" PRIu64
"\n", event_id
);
1076 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
1081 BT_PUT(event_header_type
);
1082 BT_PUT(id_field_type
);
1083 BT_PUT(v_field_type
);
1089 enum bt_ctf_notif_iter_status
after_event_header_state(
1090 struct bt_ctf_notif_iter
*notit
)
1092 enum bt_ctf_notif_iter_status status
;
1094 status
= set_current_event_class(notit
);
1095 if (status
!= BT_CTF_NOTIF_ITER_STATUS_OK
) {
1096 PERR("Failed to set current event class\n");
1100 notit
->state
= STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN
;
1107 enum bt_ctf_notif_iter_status
read_stream_event_context_begin_state(
1108 struct bt_ctf_notif_iter
*notit
)
1110 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
1111 struct bt_ctf_field_type
*stream_event_context_type
;
1113 stream_event_context_type
= bt_ctf_stream_class_get_event_context_type(
1114 notit
->meta
.stream_class
);
1115 if (!stream_event_context_type
) {
1116 notit
->state
= STATE_DSCOPE_EVENT_CONTEXT_BEGIN
;
1120 status
= read_dscope_begin_state(notit
, stream_event_context_type
,
1121 STATE_DSCOPE_EVENT_CONTEXT_BEGIN
,
1122 STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE
,
1123 ¬it
->dscopes
.stream_event_context
);
1126 BT_PUT(stream_event_context_type
);
1132 enum bt_ctf_notif_iter_status
read_stream_event_context_continue_state(
1133 struct bt_ctf_notif_iter
*notit
)
1135 return read_dscope_continue_state(notit
,
1136 STATE_DSCOPE_EVENT_CONTEXT_BEGIN
);
1140 enum bt_ctf_notif_iter_status
read_event_context_begin_state(
1141 struct bt_ctf_notif_iter
*notit
)
1143 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
1144 struct bt_ctf_field_type
*event_context_type
;
1146 event_context_type
= bt_ctf_event_class_get_context_type(
1147 notit
->meta
.event_class
);
1148 if (!event_context_type
) {
1149 notit
->state
= STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
;
1152 status
= read_dscope_begin_state(notit
, event_context_type
,
1153 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
,
1154 STATE_DSCOPE_EVENT_CONTEXT_CONTINUE
,
1155 ¬it
->dscopes
.event_context
);
1158 BT_PUT(event_context_type
);
1164 enum bt_ctf_notif_iter_status
read_event_context_continue_state(
1165 struct bt_ctf_notif_iter
*notit
)
1167 return read_dscope_continue_state(notit
,
1168 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
);
1172 enum bt_ctf_notif_iter_status
read_event_payload_begin_state(
1173 struct bt_ctf_notif_iter
*notit
)
1175 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
1176 struct bt_ctf_field_type
*event_payload_type
;
1178 event_payload_type
= bt_ctf_event_class_get_payload_type(
1179 notit
->meta
.event_class
);
1180 if (!event_payload_type
) {
1181 notit
->state
= STATE_EMIT_NOTIF_EVENT
;
1185 status
= read_dscope_begin_state(notit
, event_payload_type
,
1186 STATE_EMIT_NOTIF_EVENT
,
1187 STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
,
1188 ¬it
->dscopes
.event_payload
);
1191 BT_PUT(event_payload_type
);
1197 enum bt_ctf_notif_iter_status
read_event_payload_continue_state(
1198 struct bt_ctf_notif_iter
*notit
)
1200 return read_dscope_continue_state(notit
, STATE_EMIT_NOTIF_EVENT
);
1204 enum bt_ctf_notif_iter_status
skip_packet_padding_state(
1205 struct bt_ctf_notif_iter
*notit
)
1207 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
1208 size_t bits_to_skip
;
1210 assert(notit
->cur_packet_size
> 0);
1211 bits_to_skip
= notit
->cur_packet_size
- packet_at(notit
);
1212 if (bits_to_skip
== 0) {
1213 notit
->state
= STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
;
1216 size_t bits_to_consume
;
1217 status
= buf_ensure_available_bits(notit
);
1218 if (status
!= BT_CTF_NOTIF_ITER_STATUS_OK
) {
1222 bits_to_consume
= MIN(buf_available_bits(notit
), bits_to_skip
);
1223 buf_consume_bits(notit
, bits_to_consume
);
1224 bits_to_skip
= notit
->cur_packet_size
- packet_at(notit
);
1225 if (bits_to_skip
== 0) {
1226 notit
->state
= STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
;
1236 enum bt_ctf_notif_iter_status
handle_state(struct bt_ctf_notif_iter
*notit
)
1238 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
1240 PDBG("Handling state %d\n", notit
->state
);
1242 // TODO: optimalize!
1243 switch (notit
->state
) {
1245 notit
->state
= STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
;
1247 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
:
1248 status
= read_packet_header_begin_state(notit
);
1250 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
:
1251 status
= read_packet_header_continue_state(notit
);
1253 case STATE_AFTER_TRACE_PACKET_HEADER
:
1254 status
= after_packet_header_state(notit
);
1256 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
:
1257 status
= read_packet_context_begin_state(notit
);
1259 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
:
1260 status
= read_packet_context_continue_state(notit
);
1262 case STATE_AFTER_STREAM_PACKET_CONTEXT
:
1263 status
= after_packet_context_state(notit
);
1265 case STATE_EMIT_NOTIF_NEW_PACKET
:
1266 notit
->state
= STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN
;
1268 case STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN
:
1269 status
= read_event_header_begin_state(notit
);
1271 case STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE
:
1272 status
= read_event_header_continue_state(notit
);
1274 case STATE_AFTER_STREAM_EVENT_HEADER
:
1275 status
= after_event_header_state(notit
);
1277 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN
:
1278 status
= read_stream_event_context_begin_state(notit
);
1280 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE
:
1281 status
= read_stream_event_context_continue_state(notit
);
1283 case STATE_DSCOPE_EVENT_CONTEXT_BEGIN
:
1284 status
= read_event_context_begin_state(notit
);
1286 case STATE_DSCOPE_EVENT_CONTEXT_CONTINUE
:
1287 status
= read_event_context_continue_state(notit
);
1289 case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN
:
1290 status
= read_event_payload_begin_state(notit
);
1292 case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE
:
1293 status
= read_event_payload_continue_state(notit
);
1295 case STATE_EMIT_NOTIF_EVENT
:
1296 notit
->state
= STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN
;
1298 case STATE_SKIP_PACKET_PADDING
:
1299 status
= skip_packet_padding_state(notit
);
1301 case STATE_EMIT_NOTIF_END_OF_PACKET
:
1302 notit
->state
= STATE_SKIP_PACKET_PADDING
;
1310 * Resets the internal state of a CTF notification iterator.
1313 void bt_ctf_notif_iter_reset(struct bt_ctf_notif_iter
*notit
)
1316 stack_clear(notit
->stack
);
1317 BT_PUT(notit
->meta
.stream_class
);
1318 BT_PUT(notit
->meta
.event_class
);
1319 BT_PUT(notit
->packet
);
1320 put_all_dscopes(notit
);
1321 notit
->buf
.addr
= NULL
;
1324 notit
->buf
.packet_offset
= 0;
1325 notit
->state
= STATE_INIT
;
1326 notit
->cur_content_size
= -1;
1327 notit
->cur_packet_size
= -1;
1331 int bt_ctf_notif_iter_switch_packet(struct bt_ctf_notif_iter
*notit
)
1336 stack_clear(notit
->stack
);
1337 BT_PUT(notit
->meta
.stream_class
);
1338 BT_PUT(notit
->meta
.event_class
);
1339 BT_PUT(notit
->packet
);
1340 BT_PUT(notit
->cur_timestamp_end
);
1341 put_all_dscopes(notit
);
1344 * Adjust current buffer so that addr points to the beginning of the new
1347 if (notit
->buf
.addr
) {
1348 size_t consumed_bytes
= (size_t) (notit
->buf
.at
/ CHAR_BIT
);
1350 /* Packets are assumed to start on a byte frontier. */
1351 if (notit
->buf
.at
% CHAR_BIT
) {
1356 notit
->buf
.addr
+= consumed_bytes
;
1357 notit
->buf
.sz
-= consumed_bytes
;
1359 notit
->buf
.packet_offset
= 0;
1362 notit
->cur_content_size
= -1;
1363 notit
->cur_packet_size
= -1;
1364 notit
->cur_sc_field_path_cache
= NULL
;
1370 struct bt_ctf_field
*get_next_field(struct bt_ctf_notif_iter
*notit
)
1372 struct bt_ctf_field
*next_field
= NULL
;
1373 struct bt_ctf_field
*base_field
;
1374 struct bt_ctf_field_type
*base_type
;
1377 assert(!stack_empty(notit
->stack
));
1378 index
= stack_top(notit
->stack
)->index
;
1379 base_field
= stack_top(notit
->stack
)->base
;
1380 base_type
= bt_ctf_field_get_type(base_field
);
1382 PERR("Failed to get base field's type\n");
1386 switch (bt_ctf_field_type_get_type_id(base_type
)) {
1387 case BT_CTF_FIELD_TYPE_ID_STRUCT
:
1388 next_field
= bt_ctf_field_structure_get_field_by_index(
1391 case BT_CTF_FIELD_TYPE_ID_ARRAY
:
1392 next_field
= bt_ctf_field_array_get_field(base_field
, index
);
1394 case BT_CTF_FIELD_TYPE_ID_SEQUENCE
:
1395 next_field
= bt_ctf_field_sequence_get_field(base_field
, index
);
1397 case BT_CTF_FIELD_TYPE_ID_VARIANT
:
1398 next_field
= bt_ctf_field_variant_get_current_field(base_field
);
1411 void update_clock_state(uint64_t *state
,
1412 struct bt_ctf_field
*value_field
)
1414 struct bt_ctf_field_type
*value_type
= NULL
;
1415 uint64_t requested_new_value
;
1416 uint64_t requested_new_value_mask
;
1417 uint64_t cur_value_masked
;
1418 int requested_new_value_size
;
1421 value_type
= bt_ctf_field_get_type(value_field
);
1424 requested_new_value_size
=
1425 bt_ctf_field_type_integer_get_size(value_type
);
1426 assert(requested_new_value_size
> 0);
1428 ret
= bt_ctf_field_unsigned_integer_get_value(value_field
,
1429 &requested_new_value
);
1433 * Special case for a 64-bit new value, which is the limit
1434 * of a clock value as of this version: overwrite the
1435 * current value directly.
1437 if (requested_new_value_size
== 64) {
1438 *state
= requested_new_value
;
1442 requested_new_value_mask
= (1ULL << requested_new_value_size
) - 1;
1443 cur_value_masked
= *state
& requested_new_value_mask
;
1445 if (requested_new_value
< cur_value_masked
) {
1447 * It looks like a wrap happened on the number of bits
1448 * of the requested new value. Assume that the clock
1449 * value wrapped only one time.
1451 *state
+= requested_new_value_mask
+ 1;
1454 /* Clear the low bits of the current clock value. */
1455 *state
&= ~requested_new_value_mask
;
1457 /* Set the low bits of the current clock value. */
1458 *state
|= requested_new_value
;
1464 enum bt_ctf_btr_status
update_clock(struct bt_ctf_notif_iter
*notit
,
1465 struct bt_ctf_field
*int_field
)
1467 gboolean clock_class_found
;
1468 uint64_t *clock_state
;
1469 struct bt_ctf_field_type
*int_field_type
= NULL
;
1470 enum bt_ctf_btr_status ret
= BT_CTF_BTR_STATUS_OK
;
1471 struct bt_ctf_clock_class
*clock_class
= NULL
;
1473 int_field_type
= bt_ctf_field_get_type(int_field
);
1474 if (unlikely(!int_field_type
)) {
1478 clock_class
= bt_ctf_field_type_integer_get_mapped_clock_class(
1480 if (likely(!clock_class
)) {
1484 clock_class_found
= g_hash_table_lookup_extended(notit
->clock_states
,
1485 clock_class
, NULL
, (gpointer
) &clock_state
);
1486 if (unlikely(!clock_class_found
)) {
1487 const char *clock_class_name
=
1488 bt_ctf_clock_class_get_name(clock_class
);
1490 PERR("Unknown clock class %s mapped to integer encountered in stream\n",
1491 clock_class_name
? : "NULL");
1492 ret
= BT_CTF_BTR_STATUS_ERROR
;
1496 if (unlikely(!clock_state
)) {
1497 clock_state
= g_new0(uint64_t, 1);
1499 ret
= BT_CTF_BTR_STATUS_ENOMEM
;
1502 g_hash_table_insert(notit
->clock_states
, bt_get(clock_class
),
1506 /* Update the clock's state. */
1507 update_clock_state(clock_state
, int_field
);
1509 bt_put(int_field_type
);
1510 bt_put(clock_class
);
1515 enum bt_ctf_btr_status
btr_unsigned_int_common(uint64_t value
,
1516 struct bt_ctf_field_type
*type
, void *data
,
1517 struct bt_ctf_field
**out_int_field
)
1519 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1520 struct bt_ctf_field
*field
= NULL
;
1521 struct bt_ctf_field
*int_field
= NULL
;
1522 struct bt_ctf_notif_iter
*notit
= data
;
1525 /* Create next field */
1526 field
= get_next_field(notit
);
1528 PERR("Failed to get next field (unsigned int)\n");
1529 status
= BT_CTF_BTR_STATUS_ERROR
;
1533 switch(bt_ctf_field_type_get_type_id(type
)) {
1534 case BT_CTF_FIELD_TYPE_ID_INTEGER
:
1535 /* Integer field is created field */
1536 BT_MOVE(int_field
, field
);
1539 case BT_CTF_FIELD_TYPE_ID_ENUM
:
1540 int_field
= bt_ctf_field_enumeration_get_container(field
);
1541 type
= bt_ctf_field_get_type(int_field
);
1548 PERR("Failed to get integer field\n");
1549 status
= BT_CTF_BTR_STATUS_ERROR
;
1553 ret
= bt_ctf_field_unsigned_integer_set_value(int_field
, value
);
1555 stack_top(notit
->stack
)->index
++;
1556 *out_int_field
= int_field
;
1566 enum bt_ctf_btr_status
btr_timestamp_end_cb(void *value
,
1567 struct bt_ctf_field_type
*type
, void *data
)
1569 enum bt_ctf_btr_status status
;
1570 struct bt_ctf_field
*field
= NULL
;
1571 struct bt_ctf_notif_iter
*notit
= data
;
1573 status
= btr_unsigned_int_common(*((uint64_t *) value
), type
, data
,
1576 /* Set as the current packet's timestamp_end field. */
1577 BT_MOVE(notit
->cur_timestamp_end
, field
);
1582 enum bt_ctf_btr_status
btr_unsigned_int_cb(uint64_t value
,
1583 struct bt_ctf_field_type
*type
, void *data
)
1585 struct bt_ctf_notif_iter
*notit
= data
;
1586 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1587 struct bt_ctf_field
*field
= NULL
;
1588 struct field_cb_override
*override
;
1590 override
= g_hash_table_lookup(notit
->field_overrides
,
1592 if (unlikely(override
)) {
1593 status
= override
->func(&value
, type
, override
->data
);
1597 status
= btr_unsigned_int_common(value
, type
, data
, &field
);
1598 if (status
!= BT_CTF_BTR_STATUS_OK
) {
1602 status
= update_clock(notit
, field
);
1609 enum bt_ctf_btr_status
btr_signed_int_cb(int64_t value
,
1610 struct bt_ctf_field_type
*type
, void *data
)
1612 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1613 struct bt_ctf_field
*field
= NULL
;
1614 struct bt_ctf_field
*int_field
= NULL
;
1615 struct bt_ctf_notif_iter
*notit
= data
;
1618 /* create next field */
1619 field
= get_next_field(notit
);
1621 PERR("Failed to get next field (signed int)\n");
1622 status
= BT_CTF_BTR_STATUS_ERROR
;
1626 switch(bt_ctf_field_type_get_type_id(type
)) {
1627 case BT_CTF_FIELD_TYPE_ID_INTEGER
:
1628 /* Integer field is created field */
1629 BT_MOVE(int_field
, field
);
1632 case BT_CTF_FIELD_TYPE_ID_ENUM
:
1633 int_field
= bt_ctf_field_enumeration_get_container(field
);
1634 type
= bt_ctf_field_get_type(int_field
);
1641 PERR("Failed to get integer field\n");
1642 status
= BT_CTF_BTR_STATUS_ERROR
;
1646 ret
= bt_ctf_field_signed_integer_set_value(int_field
, value
);
1648 stack_top(notit
->stack
)->index
++;
1649 status
= update_clock(notit
, int_field
);
1659 enum bt_ctf_btr_status
btr_floating_point_cb(double value
,
1660 struct bt_ctf_field_type
*type
, void *data
)
1662 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1663 struct bt_ctf_field
*field
= NULL
;
1664 struct bt_ctf_notif_iter
*notit
= data
;
1667 /* Create next field */
1668 field
= get_next_field(notit
);
1670 PERR("Failed to get next field (floating point number)\n");
1671 status
= BT_CTF_BTR_STATUS_ERROR
;
1675 ret
= bt_ctf_field_floating_point_set_value(field
, value
);
1677 stack_top(notit
->stack
)->index
++;
1686 enum bt_ctf_btr_status
btr_string_begin_cb(
1687 struct bt_ctf_field_type
*type
, void *data
)
1689 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1690 struct bt_ctf_field
*field
= NULL
;
1691 struct bt_ctf_notif_iter
*notit
= data
;
1694 /* Create next field */
1695 field
= get_next_field(notit
);
1697 PERR("Failed to get next field (string)\n");
1698 status
= BT_CTF_BTR_STATUS_ERROR
;
1703 * Push on stack. Not a compound type per se, but we know that only
1704 * btr_string_cb() may be called between this call and a subsequent
1705 * call to btr_string_end_cb().
1707 ret
= stack_push(notit
->stack
, field
);
1709 PERR("Failed to push string field onto the stack\n");
1710 status
= BT_CTF_BTR_STATUS_ERROR
;
1715 * Initialize string field payload to an empty string since in the
1716 * case of a length 0 string the btr_string_cb won't be called and
1717 * we will end up with an unset string payload.
1719 ret
= bt_ctf_field_string_set_value(field
, "");
1721 PERR("Failed to initialize string field\n");
1722 status
= BT_CTF_BTR_STATUS_ERROR
;
1733 enum bt_ctf_btr_status
btr_string_cb(const char *value
,
1734 size_t len
, struct bt_ctf_field_type
*type
, void *data
)
1736 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1737 struct bt_ctf_field
*field
= NULL
;
1738 struct bt_ctf_notif_iter
*notit
= data
;
1741 /* Get string field */
1742 field
= stack_top(notit
->stack
)->base
;
1745 /* Append current string */
1746 ret
= bt_ctf_field_string_append_len(field
, value
, len
);
1748 PERR("Failed to append a string to a string field\n");
1749 status
= BT_CTF_BTR_STATUS_ERROR
;
1758 enum bt_ctf_btr_status
btr_string_end_cb(
1759 struct bt_ctf_field_type
*type
, void *data
)
1761 struct bt_ctf_notif_iter
*notit
= data
;
1763 /* Pop string field */
1764 stack_pop(notit
->stack
);
1766 /* Go to next field */
1767 stack_top(notit
->stack
)->index
++;
1769 return BT_CTF_BTR_STATUS_OK
;
1772 enum bt_ctf_btr_status
btr_compound_begin_cb(
1773 struct bt_ctf_field_type
*type
, void *data
)
1775 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1776 struct bt_ctf_notif_iter
*notit
= data
;
1777 struct bt_ctf_field
*field
;
1781 if (stack_empty(notit
->stack
)) {
1782 /* Root: create dynamic scope field */
1783 *notit
->cur_dscope_field
= bt_ctf_field_create(type
);
1784 field
= *notit
->cur_dscope_field
;
1787 * Field will be put at the end of this function
1788 * (stack_push() will take one reference, but this
1789 * reference is lost upon the equivalent stack_pop()
1790 * later), so also get it for our context to own it.
1792 bt_get(*notit
->cur_dscope_field
);
1794 field
= get_next_field(notit
);
1798 PERR("Failed to get next field or create dynamic scope field\n");
1799 status
= BT_CTF_BTR_STATUS_ERROR
;
1804 ret
= stack_push(notit
->stack
, field
);
1806 PERR("Failed to push compound field onto the stack\n");
1807 status
= BT_CTF_BTR_STATUS_ERROR
;
1817 enum bt_ctf_btr_status
btr_compound_end_cb(
1818 struct bt_ctf_field_type
*type
, void *data
)
1820 struct bt_ctf_notif_iter
*notit
= data
;
1822 assert(!stack_empty(notit
->stack
));
1825 stack_pop(notit
->stack
);
1827 /* If the stack is not empty, increment the base's index */
1828 if (!stack_empty(notit
->stack
)) {
1829 stack_top(notit
->stack
)->index
++;
1832 return BT_CTF_BTR_STATUS_OK
;
1836 struct bt_ctf_field
*resolve_field(struct bt_ctf_notif_iter
*notit
,
1837 struct bt_ctf_field_path
*path
)
1839 struct bt_ctf_field
*field
= NULL
;
1842 switch (bt_ctf_field_path_get_root_scope(path
)) {
1843 case BT_CTF_SCOPE_TRACE_PACKET_HEADER
:
1844 field
= notit
->dscopes
.trace_packet_header
;
1846 case BT_CTF_SCOPE_STREAM_PACKET_CONTEXT
:
1847 field
= notit
->dscopes
.stream_packet_context
;
1849 case BT_CTF_SCOPE_STREAM_EVENT_HEADER
:
1850 field
= notit
->dscopes
.stream_event_header
;
1852 case BT_CTF_SCOPE_STREAM_EVENT_CONTEXT
:
1853 field
= notit
->dscopes
.stream_event_context
;
1855 case BT_CTF_SCOPE_EVENT_CONTEXT
:
1856 field
= notit
->dscopes
.event_context
;
1858 case BT_CTF_SCOPE_EVENT_FIELDS
:
1859 field
= notit
->dscopes
.event_payload
;
1871 for (i
= 0; i
< bt_ctf_field_path_get_index_count(path
); ++i
) {
1872 struct bt_ctf_field
*next_field
= NULL
;
1873 struct bt_ctf_field_type
*field_type
;
1874 int index
= bt_ctf_field_path_get_index(path
, i
);
1876 field_type
= bt_ctf_field_get_type(field
);
1882 if (is_struct_type(field_type
)) {
1883 next_field
= bt_ctf_field_structure_get_field_by_index(
1885 } else if (is_variant_type(field_type
)) {
1887 bt_ctf_field_variant_get_current_field(field
);
1897 /* Move next field -> field */
1898 BT_MOVE(field
, next_field
);
1906 int64_t btr_get_sequence_length_cb(struct bt_ctf_field_type
*type
, void *data
)
1910 struct bt_ctf_field_path
*field_path
;
1911 struct bt_ctf_notif_iter
*notit
= data
;
1912 struct bt_ctf_field
*length_field
= NULL
;
1915 field_path
= bt_ctf_field_type_sequence_get_length_field_path(type
);
1920 length_field
= resolve_field(notit
, field_path
);
1921 if (!length_field
) {
1925 iret
= bt_ctf_field_unsigned_integer_get_value(length_field
, &length
);
1930 iret
= bt_ctf_field_sequence_set_length(stack_top(notit
->stack
)->base
,
1935 ret
= (int64_t) length
;
1938 BT_PUT(length_field
);
1945 struct bt_ctf_field_type
*btr_get_variant_type_cb(
1946 struct bt_ctf_field_type
*type
, void *data
)
1948 struct bt_ctf_field_path
*path
;
1949 struct bt_ctf_notif_iter
*notit
= data
;
1950 struct bt_ctf_field
*tag_field
= NULL
;
1951 struct bt_ctf_field
*selected_field
= NULL
;
1952 struct bt_ctf_field_type
*selected_field_type
= NULL
;
1954 path
= bt_ctf_field_type_variant_get_tag_field_path(type
);
1959 tag_field
= resolve_field(notit
, path
);
1965 * We found the enumeration tag field instance which should be
1966 * able to select a current field for this variant. This
1967 * callback function we're in is called _after_
1968 * compound_begin(), so the current stack top's base field is
1969 * the variant field in question. We get the selected field here
1970 * thanks to this tag field (thus creating the selected field),
1971 * which will also provide us with its type. Then, this field
1972 * will remain the current selected one until the next callback
1973 * function call which is used to fill the current selected
1976 selected_field
= bt_ctf_field_variant_get_field(
1977 stack_top(notit
->stack
)->base
, tag_field
);
1978 if (!selected_field
) {
1982 selected_field_type
= bt_ctf_field_get_type(selected_field
);
1986 BT_PUT(selected_field
);
1989 return selected_field_type
;
1993 int set_event_clocks(struct bt_ctf_event
*event
,
1994 struct bt_ctf_notif_iter
*notit
)
1997 GHashTableIter iter
;
1998 struct bt_ctf_clock_class
*clock_class
;
1999 uint64_t *clock_state
;
2001 g_hash_table_iter_init(&iter
, notit
->clock_states
);
2003 while (g_hash_table_iter_next(&iter
, (gpointer
) &clock_class
,
2004 (gpointer
) &clock_state
)) {
2005 struct bt_ctf_clock_value
*clock_value
;
2007 clock_value
= bt_ctf_clock_value_create(clock_class
,
2013 ret
= bt_ctf_event_set_clock_value(event
, clock_value
);
2014 bt_put(clock_value
);
2025 struct bt_ctf_event
*create_event(struct bt_ctf_notif_iter
*notit
)
2028 struct bt_ctf_event
*event
;
2030 /* Create event object. */
2031 event
= bt_ctf_event_create(notit
->meta
.event_class
);
2036 /* Set header, stream event context, context, and payload fields. */
2037 ret
= bt_ctf_event_set_header(event
,
2038 notit
->dscopes
.stream_event_header
);
2043 ret
= bt_ctf_event_set_stream_event_context(event
,
2044 notit
->dscopes
.stream_event_context
);
2049 ret
= bt_ctf_event_set_event_context(event
,
2050 notit
->dscopes
.event_context
);
2055 ret
= bt_ctf_event_set_event_payload(event
,
2056 notit
->dscopes
.event_payload
);
2061 ret
= set_event_clocks(event
, notit
);
2066 /* Associate with current packet. */
2067 assert(notit
->packet
);
2068 ret
= bt_ctf_event_set_packet(event
, notit
->packet
);
2081 void create_packet(struct bt_ctf_notif_iter
*notit
)
2084 struct bt_ctf_stream
*stream
= NULL
;
2085 struct bt_ctf_packet
*packet
= NULL
;
2087 /* Ask the user for the stream */
2088 stream
= notit
->medium
.medops
.get_stream(notit
->meta
.stream_class
,
2089 notit
->medium
.data
);
2095 packet
= bt_ctf_packet_create(stream
);
2100 /* Set packet's context and header fields */
2101 if (notit
->dscopes
.trace_packet_header
) {
2102 ret
= bt_ctf_packet_set_header(packet
,
2103 notit
->dscopes
.trace_packet_header
);
2109 if (notit
->dscopes
.stream_packet_context
) {
2110 ret
= bt_ctf_packet_set_context(packet
,
2111 notit
->dscopes
.stream_packet_context
);
2121 BT_MOVE(notit
->packet
, packet
);
2125 void notify_new_packet(struct bt_ctf_notif_iter
*notit
,
2126 struct bt_notification
**notification
)
2128 struct bt_notification
*ret
;
2130 /* Initialize the iterator's current packet */
2131 create_packet(notit
);
2132 if (!notit
->packet
) {
2136 ret
= bt_notification_packet_begin_create(notit
->packet
);
2140 *notification
= ret
;
2144 void notify_end_of_packet(struct bt_ctf_notif_iter
*notit
,
2145 struct bt_notification
**notification
)
2147 struct bt_notification
*ret
;
2149 if (!notit
->packet
) {
2153 ret
= bt_notification_packet_end_create(notit
->packet
);
2157 BT_PUT(notit
->packet
);
2158 *notification
= ret
;
2162 void notify_event(struct bt_ctf_notif_iter
*notit
,
2163 struct bt_clock_class_priority_map
*cc_prio_map
,
2164 struct bt_notification
**notification
)
2166 struct bt_ctf_event
*event
;
2167 struct bt_notification
*ret
= NULL
;
2170 event
= create_event(notit
);
2175 ret
= bt_notification_event_create(event
, cc_prio_map
);
2179 *notification
= ret
;
2185 int init_clock_states(GHashTable
*clock_states
, struct bt_ctf_trace
*trace
)
2187 int clock_class_count
, i
, ret
= 0;
2189 clock_class_count
= bt_ctf_trace_get_clock_class_count(trace
);
2190 if (clock_class_count
<= 0) {
2195 for (i
= 0; i
< clock_class_count
; i
++) {
2196 struct bt_ctf_clock_class
*clock_class
;
2198 clock_class
= bt_ctf_trace_get_clock_class_by_index(trace
, i
);
2204 g_hash_table_insert(clock_states
, bt_get(clock_class
), NULL
);
2205 bt_put(clock_class
);
2212 void init_trace_field_path_cache(struct bt_ctf_trace
*trace
,
2213 struct trace_field_path_cache
*trace_field_path_cache
)
2216 int stream_instance_id
= -1;
2218 struct bt_ctf_field_type
*packet_header
= NULL
;
2220 packet_header
= bt_ctf_trace_get_packet_header_type(trace
);
2221 if (!packet_header
) {
2225 if (!bt_ctf_field_type_is_structure(packet_header
)) {
2229 count
= bt_ctf_field_type_structure_get_field_count(packet_header
);
2234 for (i
= 0; (i
< count
&& (stream_id
== -1 || stream_instance_id
== -1)); i
++) {
2236 const char *field_name
;
2238 ret
= bt_ctf_field_type_structure_get_field(packet_header
,
2239 &field_name
, NULL
, i
);
2244 if (stream_id
== -1 && !strcmp(field_name
, "stream_id")) {
2246 } else if (stream_instance_id
== -1 &&
2247 !strcmp(field_name
, "stream_instance_id")) {
2248 stream_instance_id
= i
;
2252 trace_field_path_cache
->stream_id
= stream_id
;
2253 trace_field_path_cache
->stream_instance_id
= stream_instance_id
;
2254 BT_PUT(packet_header
);
2258 struct bt_ctf_notif_iter
*bt_ctf_notif_iter_create(struct bt_ctf_trace
*trace
,
2259 size_t max_request_sz
,
2260 struct bt_ctf_notif_iter_medium_ops medops
,
2261 void *data
, FILE *err_stream
)
2264 struct bt_ctf_notif_iter
*notit
= NULL
;
2265 struct bt_ctf_btr_cbs cbs
= {
2267 .signed_int
= btr_signed_int_cb
,
2268 .unsigned_int
= btr_unsigned_int_cb
,
2269 .floating_point
= btr_floating_point_cb
,
2270 .string_begin
= btr_string_begin_cb
,
2271 .string
= btr_string_cb
,
2272 .string_end
= btr_string_end_cb
,
2273 .compound_begin
= btr_compound_begin_cb
,
2274 .compound_end
= btr_compound_end_cb
,
2277 .get_sequence_length
= btr_get_sequence_length_cb
,
2278 .get_variant_type
= btr_get_variant_type_cb
,
2283 assert(medops
.request_bytes
);
2284 assert(medops
.get_stream
);
2285 notit
= g_new0(struct bt_ctf_notif_iter
, 1);
2287 PERR("Failed to allocate memory for CTF notification iterator\n");
2290 notit
->clock_states
= g_hash_table_new_full(g_direct_hash
,
2291 g_direct_equal
, bt_put
, g_free
);
2292 if (!notit
->clock_states
) {
2293 PERR("Failed to create hash table\n");
2296 ret
= init_clock_states(notit
->clock_states
, trace
);
2298 PERR("Failed to initialize stream clock states\n");
2301 notit
->meta
.trace
= bt_get(trace
);
2302 notit
->medium
.medops
= medops
;
2303 notit
->medium
.max_request_sz
= max_request_sz
;
2304 notit
->medium
.data
= data
;
2305 notit
->err_stream
= err_stream
;
2306 notit
->stack
= stack_new(notit
);
2307 if (!notit
->stack
) {
2308 PERR("Failed to create stack\n");
2312 notit
->btr
= bt_ctf_btr_create(cbs
, notit
, err_stream
);
2314 PERR("Failed to create binary type reader\n");
2318 bt_ctf_notif_iter_reset(notit
);
2320 init_trace_field_path_cache(trace
, ¬it
->trace_field_path_cache
);
2321 notit
->sc_field_path_caches
= g_hash_table_new_full(g_direct_hash
,
2322 g_direct_equal
, bt_put
, g_free
);
2323 if (!notit
->sc_field_path_caches
) {
2324 PERR("Failed to create stream class field path caches\n");
2328 notit
->field_overrides
= g_hash_table_new_full(g_direct_hash
,
2329 g_direct_equal
, bt_put
, g_free
);
2330 if (!notit
->field_overrides
) {
2337 bt_ctf_notif_iter_destroy(notit
);
2342 void bt_ctf_notif_iter_destroy(struct bt_ctf_notif_iter
*notit
)
2344 BT_PUT(notit
->meta
.trace
);
2345 BT_PUT(notit
->meta
.stream_class
);
2346 BT_PUT(notit
->meta
.event_class
);
2347 BT_PUT(notit
->packet
);
2348 BT_PUT(notit
->cur_timestamp_end
);
2349 put_all_dscopes(notit
);
2352 stack_destroy(notit
->stack
);
2356 bt_ctf_btr_destroy(notit
->btr
);
2359 if (notit
->clock_states
) {
2360 g_hash_table_destroy(notit
->clock_states
);
2363 if (notit
->sc_field_path_caches
) {
2364 g_hash_table_destroy(notit
->sc_field_path_caches
);
2367 if (notit
->field_overrides
) {
2368 g_hash_table_destroy(notit
->field_overrides
);
2373 enum bt_ctf_notif_iter_status
bt_ctf_notif_iter_get_next_notification(
2374 struct bt_ctf_notif_iter
*notit
,
2375 struct bt_clock_class_priority_map
*cc_prio_map
,
2376 struct bt_notification
**notification
)
2378 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
2381 assert(notification
);
2384 status
= handle_state(notit
);
2385 if (status
== BT_CTF_NOTIF_ITER_STATUS_AGAIN
) {
2386 PDBG("Medium operation reported \"try again later\"");
2389 if (status
!= BT_CTF_NOTIF_ITER_STATUS_OK
) {
2390 if (status
== BT_CTF_NOTIF_ITER_STATUS_EOF
) {
2391 PDBG("Medium operation reported end of stream\n");
2393 PERR("Failed to handle state:\n");
2394 PERR("\tState: %d\n", notit
->state
);
2399 switch (notit
->state
) {
2400 case STATE_EMIT_NOTIF_NEW_PACKET
:
2401 PDBG("Emitting new packet notification\n");
2402 notify_new_packet(notit
, notification
);
2403 if (!*notification
) {
2404 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
2407 case STATE_EMIT_NOTIF_EVENT
:
2408 PDBG("Emitting event notification\n");
2409 notify_event(notit
, cc_prio_map
, notification
);
2410 if (!*notification
) {
2411 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
2414 case STATE_EMIT_NOTIF_END_OF_PACKET
:
2415 /* Update clock with timestamp_end field. */
2416 if (notit
->cur_timestamp_end
) {
2417 enum bt_ctf_btr_status btr_status
;
2418 struct bt_ctf_field_type
*field_type
=
2419 bt_ctf_field_get_type(
2420 notit
->cur_timestamp_end
);
2422 btr_status
= update_clock(notit
,
2423 notit
->cur_timestamp_end
);
2425 if (btr_status
!= BT_CTF_BTR_STATUS_OK
) {
2426 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
2431 PDBG("Emitting end of packet notification\n");
2432 notify_end_of_packet(notit
, notification
);
2433 if (!*notification
) {
2434 status
= BT_CTF_NOTIF_ITER_STATUS_ERROR
;
2438 /* Non-emitting state: continue */
2448 enum bt_ctf_notif_iter_status
bt_ctf_notif_iter_get_packet_header_context_fields(
2449 struct bt_ctf_notif_iter
*notit
,
2450 struct bt_ctf_field
**packet_header_field
,
2451 struct bt_ctf_field
**packet_context_field
)
2453 enum bt_ctf_notif_iter_status status
= BT_CTF_NOTIF_ITER_STATUS_OK
;
2457 if (notit
->state
== STATE_EMIT_NOTIF_NEW_PACKET
) {
2458 /* We're already there */
2463 status
= handle_state(notit
);
2464 if (status
== BT_CTF_NOTIF_ITER_STATUS_AGAIN
) {
2465 PDBG("Medium operation reported \"try again later\"");
2468 if (status
!= BT_CTF_NOTIF_ITER_STATUS_OK
) {
2469 if (status
== BT_CTF_NOTIF_ITER_STATUS_EOF
) {
2470 PDBG("Medium operation reported end of stream\n");
2472 PERR("Failed to handle state:\n");
2473 PERR("\tState: %d\n", notit
->state
);
2478 switch (notit
->state
) {
2479 case STATE_EMIT_NOTIF_NEW_PACKET
:
2481 * Packet header and context fields are
2482 * potentially decoded (or they don't exist).
2486 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN
:
2487 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE
:
2488 case STATE_AFTER_TRACE_PACKET_HEADER
:
2489 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN
:
2490 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE
:
2491 case STATE_AFTER_STREAM_PACKET_CONTEXT
:
2492 /* Non-emitting state: continue */
2496 * We should never get past the
2497 * STATE_EMIT_NOTIF_NEW_PACKET state.
2504 if (packet_header_field
) {
2505 *packet_header_field
= bt_get(notit
->dscopes
.trace_packet_header
);
2508 if (packet_context_field
) {
2509 *packet_context_field
= bt_get(notit
->dscopes
.stream_packet_context
);