4 * Babeltrace CTF IR - Trace Visitor
6 * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 #include <babeltrace/ctf-ir/event.h>
30 #include <babeltrace/ctf-ir/stream-class.h>
31 #include <babeltrace/ctf-ir/visitor-internal.h>
32 #include <babeltrace/ctf-ir/event-types-internal.h>
33 #include <babeltrace/ctf-ir/event-internal.h>
34 #include <babeltrace/babeltrace-internal.h>
36 /* TSDL dynamic scope prefixes defined in CTF Section 7.3.2 */
37 static const char * const absolute_path_prefixes
[] = {
38 [CTF_NODE_ENV
] = "env.",
39 [CTF_NODE_TRACE_PACKET_HEADER
] = "trace.packet.header.",
40 [CTF_NODE_STREAM_PACKET_CONTEXT
] = "stream.packet.context.",
41 [CTF_NODE_STREAM_EVENT_HEADER
] = "stream.event.header.",
42 [CTF_NODE_STREAM_EVENT_CONTEXT
] = "stream.event.context.",
43 [CTF_NODE_EVENT_CONTEXT
] = "event.context.",
44 [CTF_NODE_EVENT_FIELDS
] = "event.fields.",
47 const int absolute_path_prefix_token_counts
[] = {
49 [CTF_NODE_TRACE_PACKET_HEADER
] = 3,
50 [CTF_NODE_STREAM_PACKET_CONTEXT
] = 3,
51 [CTF_NODE_STREAM_EVENT_HEADER
] = 3,
52 [CTF_NODE_STREAM_EVENT_CONTEXT
] = 3,
53 [CTF_NODE_EVENT_CONTEXT
] = 2,
54 [CTF_NODE_EVENT_FIELDS
] = 2,
57 static const char * const type_names
[] = {
58 [CTF_TYPE_UNKNOWN
] = "unknown",
59 [CTF_TYPE_INTEGER
] = "integer",
60 [CTF_TYPE_FLOAT
] = "float",
61 [CTF_TYPE_ENUM
] = "enumeration",
62 [CTF_TYPE_STRING
] = "string",
63 [CTF_TYPE_STRUCT
] = "structure",
64 [CTF_TYPE_UNTAGGED_VARIANT
] = "untagged variant",
65 [CTF_TYPE_VARIANT
] = "variant",
66 [CTF_TYPE_ARRAY
] = "array",
67 [CTF_TYPE_SEQUENCE
] = "sequence",
71 int field_type_visit(struct bt_ctf_field_type
*type
,
72 struct ctf_type_visitor_context
*context
,
73 ctf_type_visitor_func func
);
76 int field_type_recursive_visit(struct bt_ctf_field_type
*type
,
77 struct ctf_type_visitor_context
*context
,
78 ctf_type_visitor_func func
);
81 int get_type_field_count(struct bt_ctf_field_type
*type
)
84 enum ctf_type_id type_id
= bt_ctf_field_type_get_type_id(type
);
86 if (type_id
== CTF_TYPE_STRUCT
) {
87 field_count
= bt_ctf_field_type_structure_get_field_count(type
);
88 } else if (type_id
== CTF_TYPE_VARIANT
) {
89 field_count
= bt_ctf_field_type_variant_get_field_count(type
);
95 struct bt_ctf_field_type
*get_type_field(struct bt_ctf_field_type
*type
, int i
)
97 struct bt_ctf_field_type
*field
= NULL
;
98 enum ctf_type_id type_id
= bt_ctf_field_type_get_type_id(type
);
100 if (type_id
== CTF_TYPE_STRUCT
) {
101 bt_ctf_field_type_structure_get_field(type
, NULL
,
103 } else if (type_id
== CTF_TYPE_VARIANT
) {
104 bt_ctf_field_type_variant_get_field(type
,
112 int set_type_field(struct bt_ctf_field_type
*type
,
113 struct bt_ctf_field_type
*field
, int i
)
116 enum ctf_type_id type_id
= bt_ctf_field_type_get_type_id(type
);
118 if (type_id
== CTF_TYPE_STRUCT
) {
119 ret
= bt_ctf_field_type_structure_set_field_index(
121 } else if (type_id
== CTF_TYPE_VARIANT
) {
122 ret
= bt_ctf_field_type_variant_set_field_index(
130 int get_type_field_index(struct bt_ctf_field_type
*type
, const char *name
)
132 int field_index
= -1;
133 enum ctf_type_id type_id
= bt_ctf_field_type_get_type_id(type
);
135 if (type_id
== CTF_TYPE_STRUCT
) {
136 field_index
= bt_ctf_field_type_structure_get_field_name_index(
138 } else if (type_id
== CTF_TYPE_VARIANT
) {
139 field_index
= bt_ctf_field_type_variant_get_field_name_index(
147 ctf_type_stack
*ctf_type_stack_create(void)
149 return g_ptr_array_new();
153 void ctf_type_stack_destroy(
154 ctf_type_stack
*stack
)
156 g_ptr_array_free(stack
, TRUE
);
160 int ctf_type_stack_push(ctf_type_stack
*stack
,
161 struct ctf_type_stack_frame
*entry
)
165 if (!stack
|| !entry
) {
170 g_ptr_array_add(stack
, entry
);
176 struct ctf_type_stack_frame
*ctf_type_stack_peek(ctf_type_stack
*stack
)
178 struct ctf_type_stack_frame
*entry
= NULL
;
180 if (!stack
|| stack
->len
== 0) {
184 entry
= g_ptr_array_index(stack
, stack
->len
- 1);
190 struct ctf_type_stack_frame
*ctf_type_stack_pop(ctf_type_stack
*stack
)
192 struct ctf_type_stack_frame
*entry
= NULL
;
194 entry
= ctf_type_stack_peek(stack
);
196 g_ptr_array_set_size(stack
, stack
->len
- 1);
202 int field_type_visit(struct bt_ctf_field_type
*type
,
203 struct ctf_type_visitor_context
*context
,
204 ctf_type_visitor_func func
)
207 enum ctf_type_id type_id
;
208 struct ctf_type_stack_frame
*frame
= NULL
;
210 ret
= func(type
, context
);
215 type_id
= bt_ctf_field_type_get_type_id(type
);
216 if (type_id
== CTF_TYPE_SEQUENCE
|| type_id
== CTF_TYPE_ARRAY
) {
217 struct bt_ctf_field_type
*element
=
218 type_id
== CTF_TYPE_SEQUENCE
?
219 bt_ctf_field_type_sequence_get_element_type(type
) :
220 bt_ctf_field_type_array_get_element_type(type
);
222 ret
= field_type_recursive_visit(element
, context
, func
);
223 bt_ctf_field_type_put(element
);
229 if (type_id
!= CTF_TYPE_STRUCT
&&
230 type_id
!= CTF_TYPE_VARIANT
) {
231 /* No need to create a new stack frame */
235 frame
= g_new0(struct ctf_type_stack_frame
, 1);
242 ret
= ctf_type_stack_push(context
->stack
, frame
);
252 int field_type_recursive_visit(struct bt_ctf_field_type
*type
,
253 struct ctf_type_visitor_context
*context
,
254 ctf_type_visitor_func func
)
257 struct ctf_type_stack_frame
*stack_marker
= NULL
;
259 ret
= field_type_visit(type
, context
, func
);
264 stack_marker
= ctf_type_stack_peek(context
->stack
);
265 if (!stack_marker
|| stack_marker
->type
!= type
) {
266 /* No need for a recursive visit */
271 struct bt_ctf_field_type
*field
;
272 struct ctf_type_stack_frame
*entry
=
273 ctf_type_stack_peek(context
->stack
);
274 int field_count
= get_type_field_count(entry
->type
);
276 if (field_count
<= 0) {
278 * Propagate error if one was given, else return
279 * -1 since empty structures or variants are invalid
282 ret
= field_count
< 0 ? field_count
: -1;
286 if (entry
->index
== field_count
) {
287 /* This level has been completely visited */
288 entry
= ctf_type_stack_pop(context
->stack
);
293 if (entry
== stack_marker
) {
294 /* Completed visit */
301 field
= get_type_field(entry
->type
, entry
->index
);
302 /* Will push a new stack frame if field is struct or variant */
303 ret
= field_type_visit(field
, context
, func
);
304 bt_ctf_field_type_put(field
);
316 int bt_ctf_event_class_visit(struct bt_ctf_event_class
*event_class
,
317 struct bt_ctf_trace
*trace
,
318 struct bt_ctf_stream_class
*stream_class
,
319 ctf_type_visitor_func func
)
322 struct bt_ctf_field_type
*type
;
323 struct ctf_type_visitor_context context
= { 0 };
325 if (!event_class
|| !func
) {
330 context
.trace
= trace
;
331 context
.stream_class
= stream_class
;
332 context
.event_class
= event_class
;
333 context
.stack
= ctf_type_stack_create();
334 if (!context
.stack
) {
339 /* Visit event context */
340 context
.root_node
= CTF_NODE_EVENT_CONTEXT
;
341 type
= bt_ctf_event_class_get_context_type(event_class
);
343 ret
= field_type_recursive_visit(type
, &context
, func
);
344 bt_ctf_field_type_put(type
);
351 /* Visit event payload */
352 context
.root_node
= CTF_NODE_EVENT_FIELDS
;
353 type
= bt_ctf_event_class_get_payload_type(event_class
);
355 ret
= field_type_recursive_visit(type
, &context
, func
);
356 bt_ctf_field_type_put(type
);
364 ctf_type_stack_destroy(context
.stack
);
370 int bt_ctf_stream_class_visit(struct bt_ctf_stream_class
*stream_class
,
371 struct bt_ctf_trace
*trace
,
372 ctf_type_visitor_func func
)
374 int i
, ret
= 0, event_count
;
375 struct bt_ctf_field_type
*type
;
376 struct ctf_type_visitor_context context
= { 0 };
378 if (!stream_class
|| !func
) {
383 context
.trace
= trace
;
384 context
.stream_class
= stream_class
;
385 context
.stack
= ctf_type_stack_create();
386 if (!context
.stack
) {
391 /* Visit stream packet context header */
392 context
.root_node
= CTF_NODE_STREAM_PACKET_CONTEXT
;
393 type
= bt_ctf_stream_class_get_packet_context_type(stream_class
);
395 ret
= field_type_recursive_visit(type
, &context
, func
);
396 bt_ctf_field_type_put(type
);
403 /* Visit stream event header */
404 context
.root_node
= CTF_NODE_STREAM_EVENT_HEADER
;
405 type
= bt_ctf_stream_class_get_event_header_type(stream_class
);
407 ret
= field_type_recursive_visit(type
, &context
, func
);
408 bt_ctf_field_type_put(type
);
415 /* Visit stream event context */
416 context
.root_node
= CTF_NODE_STREAM_EVENT_CONTEXT
;
417 type
= bt_ctf_stream_class_get_event_context_type(stream_class
);
419 ret
= field_type_recursive_visit(type
, &context
, func
);
420 bt_ctf_field_type_put(type
);
427 /* Visit event classes */
428 event_count
= bt_ctf_stream_class_get_event_class_count(stream_class
);
429 if (event_count
< 0) {
433 for (i
= 0; i
< event_count
; i
++) {
434 struct bt_ctf_event_class
*event_class
=
435 bt_ctf_stream_class_get_event_class(stream_class
, i
);
437 ret
= bt_ctf_event_class_visit(event_class
, trace
,
439 bt_ctf_event_class_put(event_class
);
446 ctf_type_stack_destroy(context
.stack
);
452 int set_field_path_relative(struct ctf_type_visitor_context
*context
,
453 struct bt_ctf_field_path
*field_path
,
454 GList
**path_tokens
, struct bt_ctf_field_type
**resolved_field
)
458 struct bt_ctf_field_type
*field
= NULL
;
459 struct ctf_type_stack_frame
*frame
=
460 ctf_type_stack_peek(context
->stack
);
461 size_t token_count
= g_list_length(*path_tokens
), i
;
469 bt_ctf_field_type_get(field
);
470 for (i
= 0; i
< token_count
; i
++) {
471 struct bt_ctf_field_type
*next_field
= NULL
;
472 int field_index
= get_type_field_index(field
,
473 (*path_tokens
)->data
);
475 if (field_index
< 0) {
476 /* Field name not found, abort */
477 printf_verbose("Could not resolve field \"%s\"\n",
478 (char *) (*path_tokens
)->data
);
483 if (field_index
>= frame
->index
) {
484 printf_verbose("Invalid relative path refers to a member after the current one\n");
489 next_field
= get_type_field(field
, field_index
);
495 bt_ctf_field_type_put(field
);
497 g_array_append_val(field_path
->path_indexes
, field_index
);
500 * Free token and remove from list. This function does not
501 * assume the ownership of path_tokens; it is therefore _not_
502 * a leak to leave elements in this list. The caller should
503 * clean-up what is left (in case of error).
505 free((*path_tokens
)->data
);
506 *path_tokens
= g_list_delete_link(*path_tokens
, *path_tokens
);
509 root_path
= g_array_sized_new(FALSE
, FALSE
,
510 sizeof(int), context
->stack
->len
- 1);
516 /* Set the current root node as the resolved type's root */
517 field_path
->root
= context
->root_node
;
519 * Prepend the current fields' path to the relative path that
520 * was found by walking the stack.
522 for (i
= 0; i
< context
->stack
->len
- 1; i
++) {
524 struct ctf_type_stack_frame
*frame
=
525 g_ptr_array_index(context
->stack
, i
);
527 /* Decrement "index" since it points to the next field */
528 index
= frame
->index
- 1;
529 g_array_append_val(root_path
, index
);
531 g_array_prepend_vals(field_path
->path_indexes
, root_path
->data
,
533 g_array_free(root_path
, TRUE
);
536 bt_ctf_field_type_put(field
);
537 *resolved_field
= field
;
544 int set_field_path_absolute(struct ctf_type_visitor_context
*context
,
545 struct bt_ctf_field_path
*field_path
,
546 GList
**path_tokens
, struct bt_ctf_field_type
**resolved_field
)
549 struct bt_ctf_field_type
*field
= NULL
;
550 size_t token_count
= g_list_length(*path_tokens
), i
;
552 if (field_path
->root
> context
->root_node
) {
554 * The target path's root is lower in the dynamic scope
555 * hierarchy than the current field being visited. This
556 * is invalid since it would not be possible to have read
557 * the target before the current field.
560 printf_verbose("The target path's root is lower in the dynamic scope than the current field.\n");
564 /* Set the appropriate root field */
565 switch (field_path
->root
) {
566 case CTF_NODE_TRACE_PACKET_HEADER
:
567 field
= bt_ctf_trace_get_packet_header_type(context
->trace
);
569 case CTF_NODE_STREAM_PACKET_CONTEXT
:
570 field
= bt_ctf_stream_class_get_packet_context_type(
571 context
->stream_class
);
573 case CTF_NODE_STREAM_EVENT_HEADER
:
574 field
= bt_ctf_stream_class_get_event_header_type(
575 context
->stream_class
);
577 case CTF_NODE_STREAM_EVENT_CONTEXT
:
578 field
= bt_ctf_stream_class_get_event_context_type(
579 context
->stream_class
);
581 case CTF_NODE_EVENT_CONTEXT
:
582 field
= bt_ctf_event_class_get_context_type(
583 context
->event_class
);
585 case CTF_NODE_EVENT_FIELDS
:
586 field
= bt_ctf_event_class_get_payload_type(
587 context
->event_class
);
599 for (i
= 0; i
< token_count
; i
++) {
600 int field_index
= get_type_field_index(field
,
601 (*path_tokens
)->data
);
602 struct bt_ctf_field_type
*next_field
= NULL
;
604 if (field_index
< 0) {
605 /* Field name not found, abort */
606 printf_verbose("Could not resolve field \"%s\"\n",
607 (char *) (*path_tokens
)->data
);
612 next_field
= get_type_field(field
, field_index
);
618 bt_ctf_field_type_put(field
);
620 g_array_append_val(field_path
->path_indexes
, field_index
);
623 * Free token and remove from list. This function does not
624 * assume the ownership of path_tokens; it is therefore _not_
625 * a leak to leave elements in this list. The caller should
626 * clean-up what is left (in case of error).
628 free((*path_tokens
)->data
);
629 *path_tokens
= g_list_delete_link(*path_tokens
, *path_tokens
);
633 bt_ctf_field_type_put(field
);
634 *resolved_field
= field
;
640 int get_field_path(struct ctf_type_visitor_context
*context
,
641 const char *path
, struct bt_ctf_field_path
**field_path
,
642 struct bt_ctf_field_type
**resolved_field
)
645 GList
*path_tokens
= NULL
;
646 char *name_copy
, *save_ptr
, *token
;
648 /* Tokenize path to a list of strings */
649 name_copy
= strdup(path
);
654 token
= strtok_r(name_copy
, ".", &save_ptr
);
656 char *token_string
= strdup(token
);
662 path_tokens
= g_list_append(path_tokens
, token_string
);
663 token
= strtok_r(NULL
, ".", &save_ptr
);
671 *field_path
= bt_ctf_field_path_create();
677 /* Check if the path is absolute */
678 for (i
= 0; i
< sizeof(absolute_path_prefixes
) / sizeof(char *); i
++) {
682 * Chech if "path" starts with a known absolute path prefix.
683 * Refer to CTF 7.3.2 STATIC AND DYNAMIC SCOPES.
685 if (strncmp(path
, absolute_path_prefixes
[i
],
686 strlen(absolute_path_prefixes
[i
]))) {
687 /* Wrong prefix, try the next one */
692 * Remove the first n tokens of this prefix.
693 * e.g. trace.packet.header: remove the first 3 tokens.
695 for (j
= 0; j
< absolute_path_prefix_token_counts
[i
]; j
++) {
696 free(path_tokens
->data
);
697 path_tokens
= g_list_delete_link(
698 path_tokens
, path_tokens
);
701 /* i maps to enum bt_ctf_node constants */
702 (*field_path
)->root
= (enum bt_ctf_node
) i
;
706 if ((*field_path
)->root
== CTF_NODE_UNKNOWN
) {
708 ret
= set_field_path_relative(context
,
709 *field_path
, &path_tokens
, resolved_field
);
715 ret
= set_field_path_absolute(context
,
716 *field_path
, &path_tokens
, resolved_field
);
726 g_list_free_full(path_tokens
, free
);
731 bt_ctf_field_path_destroy(*field_path
);
737 void print_path(const char *field_name
,
738 struct bt_ctf_field_type
*resolved_type
,
739 struct bt_ctf_field_path
*field_path
)
742 enum ctf_type_id type_id
= bt_ctf_field_type_get_type_id(
745 if (type_id
< CTF_TYPE_UNKNOWN
|| type_id
>= NR_CTF_TYPES
) {
746 type_id
= CTF_TYPE_UNKNOWN
;
749 printf_verbose("Resolved field \"%s\" as type \"%s\", ",
750 field_name
, type_names
[type_id
]);
751 printf_verbose("path: %s",
752 absolute_path_prefixes
[field_path
->root
]);
754 for (i
= 0; i
< field_path
->path_indexes
->len
; i
++) {
755 printf_verbose(" %d",
756 g_array_index(field_path
->path_indexes
, int, i
));
758 printf_verbose("\n");
762 int type_resolve_func(struct bt_ctf_field_type
*type
,
763 struct ctf_type_visitor_context
*context
)
766 enum ctf_type_id type_id
= bt_ctf_field_type_get_type_id(type
);
767 const char *field_name
= NULL
;
768 struct bt_ctf_field_path
*field_path
= NULL
;
769 struct bt_ctf_field_type
*resolved_type
= NULL
;
770 struct bt_ctf_field_type
*type_copy
= NULL
;
771 struct ctf_type_stack_frame
*frame
;
773 if (type_id
!= CTF_TYPE_SEQUENCE
&&
774 type_id
!= CTF_TYPE_VARIANT
) {
778 field_name
= type_id
== CTF_TYPE_SEQUENCE
?
779 bt_ctf_field_type_sequence_get_length_field_name(type
) :
780 bt_ctf_field_type_variant_get_tag_name(type
);
786 ret
= get_field_path(context
, field_name
,
787 &field_path
, &resolved_type
);
792 assert(field_path
&& resolved_type
);
794 /* Print path if in verbose mode */
795 print_path(field_name
, resolved_type
, field_path
);
798 * Set field type's path.
800 * The original field is copied since it may have been reused
801 * in multiple structures which would cause a conflict.
803 type_copy
= bt_ctf_field_type_copy(type
);
809 if (type_id
== CTF_TYPE_VARIANT
) {
810 if (bt_ctf_field_type_get_type_id(resolved_type
) !=
812 printf_verbose("Invalid variant tag \"%s\"; expected enum\n", field_name
);
816 ret
= bt_ctf_field_type_variant_set_tag(
817 type_copy
, resolved_type
);
822 ret
= bt_ctf_field_type_variant_set_tag_field_path(type_copy
,
829 if (bt_ctf_field_type_get_type_id(resolved_type
) !=
831 printf_verbose("Invalid sequence length field \"%s\"; expected integer\n", field_name
);
836 if (bt_ctf_field_type_integer_get_signed(resolved_type
) != 0) {
837 printf_verbose("Invalid sequence length field \"%s\"; integer should be unsigned\n", field_name
);
842 ret
= bt_ctf_field_type_sequence_set_length_field_path(
843 type_copy
, field_path
);
849 /* Replace the original field */
850 frame
= ctf_type_stack_peek(context
->stack
);
851 ret
= set_type_field(frame
->type
, type_copy
, frame
->index
);
852 bt_ctf_field_type_put(type_copy
);
858 int bt_ctf_trace_visit(struct bt_ctf_trace
*trace
,
859 ctf_type_visitor_func func
)
861 int i
, stream_count
, ret
= 0;
862 struct bt_ctf_field_type
*type
= NULL
;
863 struct ctf_type_visitor_context visitor_ctx
= { 0 };
865 if (!trace
|| !func
) {
870 visitor_ctx
.trace
= trace
;
871 visitor_ctx
.stack
= ctf_type_stack_create();
872 if (!visitor_ctx
.stack
) {
877 /* Visit trace packet header */
878 type
= bt_ctf_trace_get_packet_header_type(trace
);
880 visitor_ctx
.root_node
= CTF_NODE_TRACE_PACKET_HEADER
;
881 ret
= field_type_recursive_visit(type
, &visitor_ctx
, func
);
882 visitor_ctx
.root_node
= CTF_NODE_UNKNOWN
;
883 bt_ctf_field_type_put(type
);
890 stream_count
= bt_ctf_trace_get_stream_class_count(trace
);
891 for (i
= 0; i
< stream_count
; i
++) {
892 struct bt_ctf_stream_class
*stream_class
=
893 bt_ctf_trace_get_stream_class(trace
, i
);
896 ret
= bt_ctf_stream_class_visit(stream_class
, trace
,
898 bt_ctf_stream_class_put(stream_class
);
904 if (visitor_ctx
.stack
) {
905 ctf_type_stack_destroy(visitor_ctx
.stack
);
911 int bt_ctf_trace_resolve_types(struct bt_ctf_trace
*trace
)
913 return bt_ctf_trace_visit(trace
, type_resolve_func
);
917 int bt_ctf_stream_class_resolve_types(struct bt_ctf_stream_class
*stream_class
,
918 struct bt_ctf_trace
*trace
)
920 return bt_ctf_stream_class_visit(stream_class
, trace
,
925 int bt_ctf_event_class_resolve_types(struct bt_ctf_event_class
*event_class
,
926 struct bt_ctf_trace
*trace
,
927 struct bt_ctf_stream_class
*stream_class
)
929 return bt_ctf_event_class_visit(event_class
, trace
, stream_class
,