2 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #define BT_COMP_LOG_SELF_COMP (ctx->self_comp)
24 #define BT_LOG_OUTPUT_LEVEL (ctx->log_level)
25 #define BT_LOG_TAG "PLUGIN/SINK.CTF.FS/TRANSLATE-TRACE-IR-TO-CTF-IR"
26 #include "plugins/comp-logging.h"
28 #include <babeltrace2/babeltrace.h>
29 #include "common/macros.h"
30 #include "common/common.h"
31 #include "common/assert.h"
38 #include "fs-sink-ctf-meta.h"
40 struct field_path_elem
{
41 uint64_t index_in_parent
;
45 const bt_field_class
*ir_fc
;
48 struct fs_sink_ctf_field_class
*parent_fc
;
52 bt_logging_level log_level
;
53 bt_self_component
*self_comp
;
56 struct fs_sink_ctf_stream_class
*cur_sc
;
59 struct fs_sink_ctf_event_class
*cur_ec
;
64 * Array of `struct field_path_elem` */
69 struct field_path_elem
*cur_path_stack_at(struct ctx
*ctx
, uint64_t i
)
71 BT_ASSERT(i
< ctx
->cur_path
->len
);
72 return &g_array_index(ctx
->cur_path
, struct field_path_elem
, i
);
76 struct field_path_elem
*cur_path_stack_top(struct ctx
*ctx
)
78 BT_ASSERT(ctx
->cur_path
->len
> 0);
79 return cur_path_stack_at(ctx
, ctx
->cur_path
->len
- 1);
83 bool is_reserved_member_name(const char *name
, const char *reserved_name
)
85 bool is_reserved
= false;
87 if (strcmp(name
, reserved_name
) == 0) {
92 if (name
[0] == '_' && strcmp(&name
[1], reserved_name
) == 0) {
102 int cur_path_stack_push(struct ctx
*ctx
,
103 uint64_t index_in_parent
, const char *ir_name
,
104 const bt_field_class
*ir_fc
,
105 struct fs_sink_ctf_field_class
*parent_fc
)
108 struct field_path_elem
*field_path_elem
;
110 g_array_set_size(ctx
->cur_path
, ctx
->cur_path
->len
+ 1);
111 field_path_elem
= cur_path_stack_top(ctx
);
112 field_path_elem
->index_in_parent
= index_in_parent
;
113 field_path_elem
->name
= g_string_new(ir_name
);
116 if (ctx
->cur_scope
== BT_SCOPE_PACKET_CONTEXT
) {
117 if (is_reserved_member_name(ir_name
, "packet_size") ||
118 is_reserved_member_name(ir_name
, "content_size") ||
119 is_reserved_member_name(ir_name
, "timestamp_begin") ||
120 is_reserved_member_name(ir_name
, "timestamp_end") ||
121 is_reserved_member_name(ir_name
, "events_discarded") ||
122 is_reserved_member_name(ir_name
, "packet_seq_num")) {
123 BT_COMP_LOGE("Unsupported reserved TSDL structure field class member "
124 "or variant field class option name: name=\"%s\"",
131 ret
= fs_sink_ctf_protect_name(field_path_elem
->name
);
133 BT_COMP_LOGE("Unsupported non-TSDL structure field class member "
134 "or variant field class option name: name=\"%s\"",
140 field_path_elem
->ir_fc
= ir_fc
;
141 field_path_elem
->parent_fc
= parent_fc
;
148 void cur_path_stack_pop(struct ctx
*ctx
)
150 struct field_path_elem
*field_path_elem
;
152 BT_ASSERT(ctx
->cur_path
->len
> 0);
153 field_path_elem
= cur_path_stack_top(ctx
);
155 if (field_path_elem
->name
) {
156 g_string_free(field_path_elem
->name
, TRUE
);
157 field_path_elem
->name
= NULL
;
160 g_array_set_size(ctx
->cur_path
, ctx
->cur_path
->len
- 1);
164 * Creates a relative field ref (a single name) from IR field path
165 * `tgt_ir_field_path`.
167 * This function tries to locate the target field class recursively from
168 * the top to the bottom of the context's current path using only the
169 * target field class's own name. This is because many CTF reading tools
170 * do not support a relative field ref with more than one element, for
171 * example `prev_struct.len`.
173 * Returns a negative value if this resolving operation failed.
176 int create_relative_field_ref(struct ctx
*ctx
,
177 const bt_field_path
*tgt_ir_field_path
, GString
*tgt_field_ref
)
180 struct fs_sink_ctf_field_class
*tgt_fc
= NULL
;
183 const char *tgt_fc_name
= NULL
;
184 struct field_path_elem
*field_path_elem
;
186 /* Get target field class's name */
187 switch (bt_field_path_get_root_scope(tgt_ir_field_path
)) {
188 case BT_SCOPE_PACKET_CONTEXT
:
189 BT_ASSERT(ctx
->cur_sc
);
190 tgt_fc
= ctx
->cur_sc
->packet_context_fc
;
192 case BT_SCOPE_EVENT_COMMON_CONTEXT
:
193 BT_ASSERT(ctx
->cur_sc
);
194 tgt_fc
= ctx
->cur_sc
->event_common_context_fc
;
196 case BT_SCOPE_EVENT_SPECIFIC_CONTEXT
:
197 BT_ASSERT(ctx
->cur_ec
);
198 tgt_fc
= ctx
->cur_ec
->spec_context_fc
;
200 case BT_SCOPE_EVENT_PAYLOAD
:
201 BT_ASSERT(ctx
->cur_ec
);
202 tgt_fc
= ctx
->cur_ec
->payload_fc
;
210 while (i
< bt_field_path_get_item_count(tgt_ir_field_path
)) {
211 const bt_field_path_item
*fp_item
=
212 bt_field_path_borrow_item_by_index_const(
213 tgt_ir_field_path
, i
);
214 struct fs_sink_ctf_named_field_class
*named_fc
= NULL
;
219 switch (tgt_fc
->type
) {
220 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
221 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
222 BT_FIELD_PATH_ITEM_TYPE_INDEX
);
223 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
225 bt_field_path_item_index_get_index(fp_item
));
227 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
228 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
229 BT_FIELD_PATH_ITEM_TYPE_INDEX
);
230 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
232 bt_field_path_item_index_get_index(fp_item
));
234 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
235 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
237 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
240 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
241 BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT
);
242 tgt_fc
= array_base_fc
->elem_fc
;
250 tgt_fc
= named_fc
->fc
;
251 tgt_fc_name
= named_fc
->name
->str
;
257 BT_ASSERT(tgt_fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_INT
);
258 BT_ASSERT(tgt_fc_name
);
260 /* Find target field class having this name in current context */
261 for (si
= ctx
->cur_path
->len
- 1; si
>= 0; si
--) {
262 struct fs_sink_ctf_field_class
*fc
;
263 struct fs_sink_ctf_field_class_struct
*struct_fc
;
264 struct fs_sink_ctf_field_class_variant
*var_fc
;
265 struct fs_sink_ctf_named_field_class
*named_fc
;
268 field_path_elem
= cur_path_stack_at(ctx
, (uint64_t) si
);
269 fc
= field_path_elem
->parent_fc
;
271 /* Reached stack's bottom */
277 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
278 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
280 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
281 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
284 /* Not supported by TSDL 1.8 */
289 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
290 struct_fc
= (void *) fc
;
291 len
= struct_fc
->members
->len
;
293 var_fc
= (void *) fc
;
294 len
= var_fc
->options
->len
;
297 for (i
= 0; i
< len
; i
++) {
298 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
299 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
302 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
306 if (strcmp(named_fc
->name
->str
, tgt_fc_name
) == 0) {
307 if (named_fc
->fc
== tgt_fc
) {
308 g_string_assign(tgt_field_ref
,
312 * Using only the target field
313 * class's name, we're not
314 * reaching the target field
315 * class. This is not supported
331 * Creates an absolute field ref from IR field path `tgt_ir_field_path`.
333 * Returns a negative value if this resolving operation failed.
336 int create_absolute_field_ref(struct ctx
*ctx
,
337 const bt_field_path
*tgt_ir_field_path
, GString
*tgt_field_ref
)
340 struct fs_sink_ctf_field_class
*fc
= NULL
;
343 switch (bt_field_path_get_root_scope(tgt_ir_field_path
)) {
344 case BT_SCOPE_PACKET_CONTEXT
:
345 BT_ASSERT(ctx
->cur_sc
);
346 fc
= ctx
->cur_sc
->packet_context_fc
;
347 g_string_assign(tgt_field_ref
, "stream.packet.context");
349 case BT_SCOPE_EVENT_COMMON_CONTEXT
:
350 BT_ASSERT(ctx
->cur_sc
);
351 fc
= ctx
->cur_sc
->event_common_context_fc
;
352 g_string_assign(tgt_field_ref
, "stream.event.context");
354 case BT_SCOPE_EVENT_SPECIFIC_CONTEXT
:
355 BT_ASSERT(ctx
->cur_ec
);
356 fc
= ctx
->cur_ec
->spec_context_fc
;
357 g_string_assign(tgt_field_ref
, "event.context");
359 case BT_SCOPE_EVENT_PAYLOAD
:
360 BT_ASSERT(ctx
->cur_ec
);
361 fc
= ctx
->cur_ec
->payload_fc
;
362 g_string_assign(tgt_field_ref
, "event.fields");
370 for (i
= 0; i
< bt_field_path_get_item_count(tgt_ir_field_path
); i
++) {
371 const bt_field_path_item
*fp_item
=
372 bt_field_path_borrow_item_by_index_const(
373 tgt_ir_field_path
, i
);
374 struct fs_sink_ctf_named_field_class
*named_fc
= NULL
;
376 if (bt_field_path_item_get_type(fp_item
) !=
377 BT_FIELD_PATH_ITEM_TYPE_INDEX
) {
378 /* Not supported by TSDL 1.8 */
384 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
385 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
386 BT_FIELD_PATH_ITEM_TYPE_INDEX
);
387 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
389 bt_field_path_item_index_get_index(fp_item
));
391 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
392 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
393 BT_FIELD_PATH_ITEM_TYPE_INDEX
);
394 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
396 bt_field_path_item_index_get_index(fp_item
));
403 g_string_append_c(tgt_field_ref
, '.');
404 g_string_append(tgt_field_ref
, named_fc
->name
->str
);
413 * Resolves a target field class located at `tgt_ir_field_path`, writing
414 * the resolved field ref to `tgt_field_ref` and setting
415 * `*create_before` according to whether or not the target field must be
416 * created immediately before (in which case `tgt_field_ref` is
420 void resolve_field_class(struct ctx
*ctx
,
421 const bt_field_path
*tgt_ir_field_path
,
422 GString
*tgt_field_ref
, bool *create_before
)
427 *create_before
= false;
429 if (!tgt_ir_field_path
) {
430 *create_before
= true;
434 tgt_scope
= bt_field_path_get_root_scope(tgt_ir_field_path
);
436 if (tgt_scope
== ctx
->cur_scope
) {
438 * Try, in this order:
440 * 1. Use a relative path, using only the target field
441 * class's name. This is what is the most commonly
442 * supported by popular CTF reading tools.
444 * 2. Use an absolute path. This could fail if there's
445 * an array field class from the current root's field
446 * class to the target field class.
448 * 3. Create the target field class before the
449 * requesting field class (fallback).
451 ret
= create_relative_field_ref(ctx
, tgt_ir_field_path
,
454 ret
= create_absolute_field_ref(ctx
, tgt_ir_field_path
,
457 *create_before
= true;
463 ret
= create_absolute_field_ref(ctx
, tgt_ir_field_path
,
466 /* It must always work in previous scopes */
475 int translate_field_class(struct ctx
*ctx
);
478 void append_to_parent_field_class(struct ctx
*ctx
,
479 struct fs_sink_ctf_field_class
*fc
)
481 struct fs_sink_ctf_field_class
*parent_fc
=
482 cur_path_stack_top(ctx
)->parent_fc
;
484 switch (parent_fc
->type
) {
485 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
486 fs_sink_ctf_field_class_struct_append_member((void *) parent_fc
,
487 cur_path_stack_top(ctx
)->name
->str
, fc
);
489 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
490 fs_sink_ctf_field_class_variant_append_option((void *) parent_fc
,
491 cur_path_stack_top(ctx
)->name
->str
, fc
);
493 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
494 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
496 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
499 BT_ASSERT(!array_base_fc
->elem_fc
);
500 array_base_fc
->elem_fc
= fc
;
501 array_base_fc
->base
.alignment
= fc
->alignment
;
510 void update_parent_field_class_alignment(struct ctx
*ctx
,
511 unsigned int alignment
)
513 struct fs_sink_ctf_field_class
*parent_fc
=
514 cur_path_stack_top(ctx
)->parent_fc
;
516 switch (parent_fc
->type
) {
517 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
518 fs_sink_ctf_field_class_struct_align_at_least(
519 (void *) parent_fc
, alignment
);
521 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
522 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
524 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
527 array_base_fc
->base
.alignment
= alignment
;
536 int translate_structure_field_class_members(struct ctx
*ctx
,
537 struct fs_sink_ctf_field_class_struct
*struct_fc
,
538 const bt_field_class
*ir_fc
)
543 for (i
= 0; i
< bt_field_class_structure_get_member_count(ir_fc
); i
++) {
544 const bt_field_class_structure_member
*member
;
546 const bt_field_class
*memb_ir_fc
;
549 bt_field_class_structure_borrow_member_by_index_const(
551 name
= bt_field_class_structure_member_get_name(member
);
552 memb_ir_fc
= bt_field_class_structure_member_borrow_field_class_const(
554 ret
= cur_path_stack_push(ctx
, i
, name
, memb_ir_fc
,
557 BT_COMP_LOGE("Cannot translate structure field class member: "
558 "name=\"%s\"", name
);
562 ret
= translate_field_class(ctx
);
564 BT_COMP_LOGE("Cannot translate structure field class member: "
565 "name=\"%s\"", name
);
569 cur_path_stack_pop(ctx
);
577 int translate_structure_field_class(struct ctx
*ctx
)
580 struct fs_sink_ctf_field_class_struct
*fc
=
581 fs_sink_ctf_field_class_struct_create_empty(
582 cur_path_stack_top(ctx
)->ir_fc
,
583 cur_path_stack_top(ctx
)->index_in_parent
);
586 append_to_parent_field_class(ctx
, (void *) fc
);
587 ret
= translate_structure_field_class_members(ctx
, fc
, fc
->base
.ir_fc
);
592 update_parent_field_class_alignment(ctx
, fc
->base
.alignment
);
599 int translate_variant_field_class(struct ctx
*ctx
)
603 struct fs_sink_ctf_field_class_variant
*fc
=
604 fs_sink_ctf_field_class_variant_create_empty(
605 cur_path_stack_top(ctx
)->ir_fc
,
606 cur_path_stack_top(ctx
)->index_in_parent
);
610 /* Resolve tag field class before appending to parent */
611 resolve_field_class(ctx
,
612 bt_field_class_variant_borrow_selector_field_path_const(
613 fc
->base
.ir_fc
), fc
->tag_ref
, &fc
->tag_is_before
);
615 append_to_parent_field_class(ctx
, (void *) fc
);
617 for (i
= 0; i
< bt_field_class_variant_get_option_count(fc
->base
.ir_fc
);
619 const bt_field_class_variant_option
*opt
;
621 const bt_field_class
*opt_ir_fc
;
623 opt
= bt_field_class_variant_borrow_option_by_index_const(
625 name
= bt_field_class_variant_option_get_name(opt
);
626 opt_ir_fc
= bt_field_class_variant_option_borrow_field_class_const(
628 ret
= cur_path_stack_push(ctx
, i
, name
, opt_ir_fc
, (void *) fc
);
630 BT_COMP_LOGE("Cannot translate variant field class option: "
631 "name=\"%s\"", name
);
635 ret
= translate_field_class(ctx
);
637 BT_COMP_LOGE("Cannot translate variant field class option: "
638 "name=\"%s\"", name
);
642 cur_path_stack_pop(ctx
);
650 int translate_static_array_field_class(struct ctx
*ctx
)
652 struct fs_sink_ctf_field_class_array
*fc
=
653 fs_sink_ctf_field_class_array_create_empty(
654 cur_path_stack_top(ctx
)->ir_fc
,
655 cur_path_stack_top(ctx
)->index_in_parent
);
656 const bt_field_class
*elem_ir_fc
=
657 bt_field_class_array_borrow_element_field_class_const(
658 fc
->base
.base
.ir_fc
);
662 append_to_parent_field_class(ctx
, (void *) fc
);
663 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, elem_ir_fc
,
666 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
670 ret
= translate_field_class(ctx
);
672 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
676 cur_path_stack_pop(ctx
);
677 update_parent_field_class_alignment(ctx
, fc
->base
.base
.alignment
);
684 int translate_dynamic_array_field_class(struct ctx
*ctx
)
686 struct fs_sink_ctf_field_class_sequence
*fc
=
687 fs_sink_ctf_field_class_sequence_create_empty(
688 cur_path_stack_top(ctx
)->ir_fc
,
689 cur_path_stack_top(ctx
)->index_in_parent
);
690 const bt_field_class
*elem_ir_fc
=
691 bt_field_class_array_borrow_element_field_class_const(
692 fc
->base
.base
.ir_fc
);
697 /* Resolve length field class before appending to parent */
698 resolve_field_class(ctx
,
699 bt_field_class_dynamic_array_borrow_length_field_path_const(
700 fc
->base
.base
.ir_fc
),
701 fc
->length_ref
, &fc
->length_is_before
);
703 append_to_parent_field_class(ctx
, (void *) fc
);
704 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, elem_ir_fc
,
707 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
711 ret
= translate_field_class(ctx
);
713 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
717 cur_path_stack_pop(ctx
);
718 update_parent_field_class_alignment(ctx
, fc
->base
.base
.alignment
);
725 int translate_integer_field_class(struct ctx
*ctx
)
727 struct fs_sink_ctf_field_class_int
*fc
=
728 fs_sink_ctf_field_class_int_create(
729 cur_path_stack_top(ctx
)->ir_fc
,
730 cur_path_stack_top(ctx
)->index_in_parent
);
733 append_to_parent_field_class(ctx
, (void *) fc
);
738 int translate_real_field_class(struct ctx
*ctx
)
740 struct fs_sink_ctf_field_class_float
*fc
=
741 fs_sink_ctf_field_class_float_create(
742 cur_path_stack_top(ctx
)->ir_fc
,
743 cur_path_stack_top(ctx
)->index_in_parent
);
746 append_to_parent_field_class(ctx
, (void *) fc
);
751 int translate_string_field_class(struct ctx
*ctx
)
753 struct fs_sink_ctf_field_class_string
*fc
=
754 fs_sink_ctf_field_class_string_create(
755 cur_path_stack_top(ctx
)->ir_fc
,
756 cur_path_stack_top(ctx
)->index_in_parent
);
759 append_to_parent_field_class(ctx
, (void *) fc
);
764 * Translates a field class, recursively.
766 * The field class's IR field class, parent field class, and index
767 * within its parent are in the context's current path's top element
768 * (cur_path_stack_top()).
771 int translate_field_class(struct ctx
*ctx
)
775 switch (bt_field_class_get_type(cur_path_stack_top(ctx
)->ir_fc
)) {
776 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
777 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
778 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
779 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
780 ret
= translate_integer_field_class(ctx
);
782 case BT_FIELD_CLASS_TYPE_REAL
:
783 ret
= translate_real_field_class(ctx
);
785 case BT_FIELD_CLASS_TYPE_STRING
:
786 ret
= translate_string_field_class(ctx
);
788 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
789 ret
= translate_structure_field_class(ctx
);
791 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
792 ret
= translate_static_array_field_class(ctx
);
794 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
795 ret
= translate_dynamic_array_field_class(ctx
);
797 case BT_FIELD_CLASS_TYPE_VARIANT
:
798 ret
= translate_variant_field_class(ctx
);
808 int set_field_ref(struct fs_sink_ctf_field_class
*fc
, const char *fc_name
,
809 struct fs_sink_ctf_field_class
*parent_fc
)
812 GString
*field_ref
= NULL
;
814 const char *tgt_type
;
815 struct fs_sink_ctf_field_class_struct
*parent_struct_fc
=
818 unsigned int suffix
= 0;
820 if (!fc_name
|| !parent_fc
||
821 parent_fc
->type
!= FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
828 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
830 struct fs_sink_ctf_field_class_sequence
*seq_fc
= (void *) fc
;
832 field_ref
= seq_fc
->length_ref
;
833 is_before
= seq_fc
->length_is_before
;
837 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
839 struct fs_sink_ctf_field_class_variant
*var_fc
= (void *) fc
;
841 field_ref
= var_fc
->tag_ref
;
842 is_before
= var_fc
->tag_is_before
;
850 BT_ASSERT(field_ref
);
856 /* Initial field ref */
857 g_string_printf(field_ref
, "__%s_%s", fc_name
, tgt_type
);
860 * Make sure field ref does not clash with an existing field
861 * class name within the same parent structure field class.
866 for (i
= 0; i
< parent_struct_fc
->members
->len
; i
++) {
867 struct fs_sink_ctf_named_field_class
*named_fc
=
868 fs_sink_ctf_field_class_struct_borrow_member_by_index(
869 parent_struct_fc
, i
);
871 if (strcmp(field_ref
->str
, named_fc
->name
->str
) == 0) {
879 /* No clash: we're done */
883 /* Append suffix and try again */
884 g_string_printf(field_ref
, "__%s_%s_%u", fc_name
, tgt_type
,
894 * This function recursively sets field refs of sequence and variant
895 * field classes when they are immediately before, avoiding name clashes
896 * with existing field class names.
898 * It can fail at this point if, for example, a sequence field class of
899 * which to set the length's field ref has something else than a
900 * structure field class as its parent: in this case, there's no
901 * location to place the length field class immediately before the
902 * sequence field class.
905 int set_field_refs(struct fs_sink_ctf_field_class
* const fc
,
906 const char *fc_name
, struct fs_sink_ctf_field_class
*parent_fc
)
909 enum fs_sink_ctf_field_class_type fc_type
;
915 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
916 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
920 struct fs_sink_ctf_field_class_struct
*struct_fc
;
921 struct fs_sink_ctf_field_class_variant
*var_fc
= NULL
;
922 struct fs_sink_ctf_named_field_class
*named_fc
;
924 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
925 struct_fc
= (void *) fc
;
926 len
= struct_fc
->members
->len
;
928 var_fc
= (void *) fc
;
929 len
= var_fc
->options
->len
;
930 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
936 for (i
= 0; i
< len
; i
++) {
937 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
938 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
941 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
945 ret
= set_field_refs(named_fc
->fc
, named_fc
->name
->str
,
954 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
955 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
957 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
960 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
961 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
967 ret
= set_field_refs(array_base_fc
->elem_fc
, NULL
, fc
);
983 * This function translates a root scope trace IR field class to
984 * a CTF IR field class.
986 * The resulting CTF IR field class is written to `*fc` so that it
987 * exists as the parent object's (stream class or event class) true root
988 * field class during the recursive translation for resolving purposes.
989 * This is also why this function creates the empty structure field
990 * class and then calls translate_structure_field_class_members() to
994 int translate_scope_field_class(struct ctx
*ctx
, bt_scope scope
,
995 struct fs_sink_ctf_field_class
**fc
,
996 const bt_field_class
*ir_fc
)
1004 BT_ASSERT(bt_field_class_get_type(ir_fc
) ==
1005 BT_FIELD_CLASS_TYPE_STRUCTURE
);
1007 *fc
= (void *) fs_sink_ctf_field_class_struct_create_empty(
1008 ir_fc
, UINT64_C(-1));
1010 ctx
->cur_scope
= scope
;
1011 BT_ASSERT(ctx
->cur_path
->len
== 0);
1012 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, ir_fc
, NULL
);
1014 BT_COMP_LOGE("Cannot translate scope structure field class: "
1019 ret
= translate_structure_field_class_members(ctx
, (void *) *fc
, ir_fc
);
1021 BT_COMP_LOGE("Cannot translate scope structure field class: "
1026 cur_path_stack_pop(ctx
);
1028 /* Set field refs for preceding targets */
1029 ret
= set_field_refs(*fc
, NULL
, NULL
);
1036 void ctx_init(struct ctx
*ctx
, struct fs_sink_comp
*fs_sink
)
1038 memset(ctx
, 0, sizeof(struct ctx
));
1039 ctx
->cur_path
= g_array_new(FALSE
, TRUE
,
1040 sizeof(struct field_path_elem
));
1041 BT_ASSERT(ctx
->cur_path
);
1042 ctx
->log_level
= fs_sink
->log_level
;
1043 ctx
->self_comp
= fs_sink
->self_comp
;
1047 void ctx_fini(struct ctx
*ctx
)
1049 if (ctx
->cur_path
) {
1050 g_array_free(ctx
->cur_path
, TRUE
);
1051 ctx
->cur_path
= NULL
;
1056 int translate_event_class(struct fs_sink_comp
*fs_sink
,
1057 struct fs_sink_ctf_stream_class
*sc
,
1058 const bt_event_class
*ir_ec
,
1059 struct fs_sink_ctf_event_class
**out_ec
)
1063 struct fs_sink_ctf_event_class
*ec
;
1068 ctx_init(&ctx
, fs_sink
);
1069 ec
= fs_sink_ctf_event_class_create(sc
, ir_ec
);
1073 ret
= translate_scope_field_class(&ctx
, BT_SCOPE_EVENT_SPECIFIC_CONTEXT
,
1074 &ec
->spec_context_fc
,
1075 bt_event_class_borrow_specific_context_field_class_const(
1081 ret
= translate_scope_field_class(&ctx
, BT_SCOPE_EVENT_PAYLOAD
,
1083 bt_event_class_borrow_payload_field_class_const(ir_ec
));
1095 int try_translate_event_class_trace_ir_to_ctf_ir(
1096 struct fs_sink_comp
*fs_sink
,
1097 struct fs_sink_ctf_stream_class
*sc
,
1098 const bt_event_class
*ir_ec
,
1099 struct fs_sink_ctf_event_class
**out_ec
)
1106 /* Check in hash table first */
1107 *out_ec
= g_hash_table_lookup(sc
->event_classes_from_ir
, ir_ec
);
1108 if (G_LIKELY(*out_ec
)) {
1112 ret
= translate_event_class(fs_sink
, sc
, ir_ec
, out_ec
);
1118 bool default_clock_class_name_exists(struct fs_sink_ctf_trace
*trace
,
1121 bool exists
= false;
1124 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
1125 struct fs_sink_ctf_stream_class
*sc
=
1126 trace
->stream_classes
->pdata
[i
];
1128 if (sc
->default_clock_class_name
->len
== 0) {
1129 /* No default clock class */
1133 if (strcmp(sc
->default_clock_class_name
->str
, name
) == 0) {
1144 void make_unique_default_clock_class_name(struct fs_sink_ctf_stream_class
*sc
)
1146 unsigned int suffix
= 0;
1149 g_string_assign(sc
->default_clock_class_name
, "");
1150 sprintf(buf
, "default");
1152 while (default_clock_class_name_exists(sc
->trace
, buf
)) {
1153 sprintf(buf
, "default%u", suffix
);
1157 g_string_assign(sc
->default_clock_class_name
, buf
);
1161 int translate_stream_class(struct fs_sink_comp
*fs_sink
,
1162 struct fs_sink_ctf_trace
*trace
,
1163 const bt_stream_class
*ir_sc
,
1164 struct fs_sink_ctf_stream_class
**out_sc
)
1171 ctx_init(&ctx
, fs_sink
);
1172 *out_sc
= fs_sink_ctf_stream_class_create(trace
, ir_sc
);
1175 /* Set default clock class's protected name, if any */
1176 if ((*out_sc
)->default_clock_class
) {
1177 const char *name
= bt_clock_class_get_name(
1178 (*out_sc
)->default_clock_class
);
1181 /* Try original name, protected */
1182 g_string_assign((*out_sc
)->default_clock_class_name
,
1184 ret
= fs_sink_ctf_protect_name(
1185 (*out_sc
)->default_clock_class_name
);
1187 /* Invalid: create a new name */
1188 make_unique_default_clock_class_name(*out_sc
);
1192 /* No name: create a name */
1193 make_unique_default_clock_class_name(*out_sc
);
1197 ctx
.cur_sc
= *out_sc
;
1198 ret
= translate_scope_field_class(&ctx
, BT_SCOPE_PACKET_CONTEXT
,
1199 &(*out_sc
)->packet_context_fc
,
1200 bt_stream_class_borrow_packet_context_field_class_const(ir_sc
));
1205 if ((*out_sc
)->packet_context_fc
) {
1207 * Make sure the structure field class's alignment is
1208 * enough: 8 is what we use for our own special members
1209 * in the packet context.
1211 fs_sink_ctf_field_class_struct_align_at_least(
1212 (void *) (*out_sc
)->packet_context_fc
, 8);
1215 ret
= translate_scope_field_class(&ctx
, BT_SCOPE_EVENT_COMMON_CONTEXT
,
1216 &(*out_sc
)->event_common_context_fc
,
1217 bt_stream_class_borrow_event_common_context_field_class_const(
1226 fs_sink_ctf_stream_class_destroy(*out_sc
);
1235 int try_translate_stream_class_trace_ir_to_ctf_ir(
1236 struct fs_sink_comp
*fs_sink
,
1237 struct fs_sink_ctf_trace
*trace
,
1238 const bt_stream_class
*ir_sc
,
1239 struct fs_sink_ctf_stream_class
**out_sc
)
1247 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
1248 *out_sc
= trace
->stream_classes
->pdata
[i
];
1250 if ((*out_sc
)->ir_sc
== ir_sc
) {
1255 ret
= translate_stream_class(fs_sink
, trace
, ir_sc
, out_sc
);
1262 struct fs_sink_ctf_trace
*translate_trace_trace_ir_to_ctf_ir(
1263 struct fs_sink_comp
*fs_sink
, const bt_trace
*ir_trace
)
1267 struct fs_sink_ctf_trace
*trace
= NULL
;
1269 /* Check that trace's environment is TSDL-compatible */
1270 count
= bt_trace_get_environment_entry_count(ir_trace
);
1271 for (i
= 0; i
< count
; i
++) {
1273 const bt_value
*val
;
1275 bt_trace_borrow_environment_entry_by_index_const(
1276 ir_trace
, i
, &name
, &val
);
1278 if (!fs_sink_ctf_ist_valid_identifier(name
)) {
1279 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, fs_sink
->log_level
,
1281 "Unsupported trace class's environment entry name: "
1282 "name=\"%s\"", name
);
1286 switch (bt_value_get_type(val
)) {
1287 case BT_VALUE_TYPE_SIGNED_INTEGER
:
1288 case BT_VALUE_TYPE_STRING
:
1291 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, fs_sink
->log_level
,
1293 "Unsupported trace class's environment entry value type: "
1295 bt_common_value_type_string(
1296 bt_value_get_type(val
)));
1301 trace
= fs_sink_ctf_trace_create(ir_trace
);