2 * Copyright 2018 - 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.
15 #define BT_LOG_TAG "PLUGIN-CTF-METADATA-META-TRANSLATE"
18 #include <babeltrace/babeltrace.h>
19 #include <babeltrace/babeltrace-internal.h>
20 #include <babeltrace/assert-internal.h>
26 #include "ctf-meta-visitors.h"
29 struct bt_field_class
*ctf_field_class_to_ir(struct ctf_field_class
*fc
,
30 struct ctf_trace_class
*tc
,
31 struct ctf_stream_class
*sc
,
32 struct ctf_event_class
*ec
);
35 void ctf_field_class_int_set_props(struct ctf_field_class_int
*fc
,
36 struct bt_field_class
*ir_fc
)
40 ret
= bt_field_class_integer_set_field_value_range(ir_fc
, fc
->base
.size
);
42 ret
= bt_field_class_integer_set_preferred_display_base(ir_fc
,
48 struct bt_field_class
*ctf_field_class_int_to_ir(struct ctf_field_class_int
*fc
)
50 struct bt_field_class
*ir_fc
;
53 ir_fc
= bt_field_class_signed_integer_create();
55 ir_fc
= bt_field_class_unsigned_integer_create();
59 ctf_field_class_int_set_props(fc
, ir_fc
);
64 struct bt_field_class
*ctf_field_class_enum_to_ir(struct ctf_field_class_enum
*fc
)
67 struct bt_field_class
*ir_fc
;
70 if (fc
->base
.is_signed
) {
71 ir_fc
= bt_field_class_signed_enumeration_create();
73 ir_fc
= bt_field_class_unsigned_enumeration_create();
77 ctf_field_class_int_set_props((void *) fc
, ir_fc
);
79 for (i
= 0; i
< fc
->mappings
->len
; i
++) {
80 struct ctf_field_class_enum_mapping
*mapping
=
81 ctf_field_class_enum_borrow_mapping_by_index(fc
, i
);
83 if (fc
->base
.is_signed
) {
84 ret
= bt_field_class_signed_enumeration_map_range(
85 ir_fc
, mapping
->label
->str
,
86 mapping
->range
.lower
.i
, mapping
->range
.upper
.i
);
88 ret
= bt_field_class_unsigned_enumeration_map_range(
89 ir_fc
, mapping
->label
->str
,
90 mapping
->range
.lower
.u
, mapping
->range
.upper
.u
);
100 struct bt_field_class
*ctf_field_class_float_to_ir(
101 struct ctf_field_class_float
*fc
)
103 struct bt_field_class
*ir_fc
;
106 ir_fc
= bt_field_class_real_create();
109 if (fc
->base
.size
== 32) {
110 ret
= bt_field_class_real_set_is_single_precision(ir_fc
,
119 struct bt_field_class
*ctf_field_class_string_to_ir(
120 struct ctf_field_class_string
*fc
)
122 struct bt_field_class
*ir_fc
= bt_field_class_string_create();
129 struct bt_field_class
*ctf_field_class_struct_to_ir(
130 struct ctf_field_class_struct
*fc
,
131 struct ctf_trace_class
*tc
,
132 struct ctf_stream_class
*sc
,
133 struct ctf_event_class
*ec
)
136 struct bt_field_class
*ir_fc
= bt_field_class_structure_create();
141 for (i
= 0; i
< fc
->members
->len
; i
++) {
142 struct ctf_named_field_class
*named_fc
=
143 ctf_field_class_struct_borrow_member_by_index(fc
, i
);
144 struct bt_field_class
*member_ir_fc
;
146 if (!named_fc
->fc
->in_ir
) {
150 member_ir_fc
= ctf_field_class_to_ir(named_fc
->fc
, tc
, sc
, ec
);
151 BT_ASSERT(member_ir_fc
);
152 ret
= bt_field_class_structure_append_member(ir_fc
,
153 named_fc
->name
->str
, member_ir_fc
);
155 bt_put(member_ir_fc
);
162 struct bt_field_class
*borrow_ir_ft_from_field_path(
163 struct ctf_field_path
*field_path
,
164 struct ctf_trace_class
*tc
,
165 struct ctf_stream_class
*sc
,
166 struct ctf_event_class
*ec
)
168 struct bt_field_class
*ir_fc
= NULL
;
169 struct ctf_field_class
*fc
= ctf_field_path_borrow_field_class(
170 field_path
, tc
, sc
, ec
);
182 struct bt_field_class
*ctf_field_class_variant_to_ir(
183 struct ctf_field_class_variant
*fc
,
184 struct ctf_trace_class
*tc
,
185 struct ctf_stream_class
*sc
,
186 struct ctf_event_class
*ec
)
189 struct bt_field_class
*ir_fc
= bt_field_class_variant_create();
193 ret
= bt_field_class_variant_set_selector_field_class(ir_fc
,
194 borrow_ir_ft_from_field_path(&fc
->tag_path
, tc
, sc
, ec
));
197 for (i
= 0; i
< fc
->options
->len
; i
++) {
198 struct ctf_named_field_class
*named_fc
=
199 ctf_field_class_variant_borrow_option_by_index(fc
, i
);
200 struct bt_field_class
*option_ir_fc
;
202 BT_ASSERT(named_fc
->fc
->in_ir
);
203 option_ir_fc
= ctf_field_class_to_ir(named_fc
->fc
, tc
, sc
, ec
);
204 BT_ASSERT(option_ir_fc
);
205 ret
= bt_field_class_variant_append_option(ir_fc
,
206 named_fc
->name
->str
, option_ir_fc
);
208 bt_put(option_ir_fc
);
215 struct bt_field_class
*ctf_field_class_array_to_ir(
216 struct ctf_field_class_array
*fc
,
217 struct ctf_trace_class
*tc
,
218 struct ctf_stream_class
*sc
,
219 struct ctf_event_class
*ec
)
221 struct bt_field_class
*ir_fc
;
222 struct bt_field_class
*elem_ir_fc
;
224 if (fc
->base
.is_text
) {
225 ir_fc
= bt_field_class_string_create();
230 elem_ir_fc
= ctf_field_class_to_ir(fc
->base
.elem_fc
, tc
, sc
, ec
);
231 BT_ASSERT(elem_ir_fc
);
232 ir_fc
= bt_field_class_static_array_create(elem_ir_fc
, fc
->length
);
241 struct bt_field_class
*ctf_field_class_sequence_to_ir(
242 struct ctf_field_class_sequence
*fc
,
243 struct ctf_trace_class
*tc
,
244 struct ctf_stream_class
*sc
,
245 struct ctf_event_class
*ec
)
248 struct bt_field_class
*ir_fc
;
249 struct bt_field_class
*elem_ir_fc
;
251 if (fc
->base
.is_text
) {
252 ir_fc
= bt_field_class_string_create();
257 elem_ir_fc
= ctf_field_class_to_ir(fc
->base
.elem_fc
, tc
, sc
, ec
);
258 BT_ASSERT(elem_ir_fc
);
259 ir_fc
= bt_field_class_dynamic_array_create(elem_ir_fc
);
263 ret
= bt_field_class_dynamic_array_set_length_field_class(ir_fc
,
264 borrow_ir_ft_from_field_path(&fc
->length_path
, tc
, sc
, ec
));
272 struct bt_field_class
*ctf_field_class_to_ir(struct ctf_field_class
*fc
,
273 struct ctf_trace_class
*tc
,
274 struct ctf_stream_class
*sc
,
275 struct ctf_event_class
*ec
)
277 struct bt_field_class
*ir_fc
= NULL
;
280 BT_ASSERT(fc
->in_ir
);
283 case CTF_FIELD_CLASS_ID_INT
:
284 ir_fc
= ctf_field_class_int_to_ir((void *) fc
);
286 case CTF_FIELD_CLASS_ID_ENUM
:
287 ir_fc
= ctf_field_class_enum_to_ir((void *) fc
);
289 case CTF_FIELD_CLASS_ID_FLOAT
:
290 ir_fc
= ctf_field_class_float_to_ir((void *) fc
);
292 case CTF_FIELD_CLASS_ID_STRING
:
293 ir_fc
= ctf_field_class_string_to_ir((void *) fc
);
295 case CTF_FIELD_CLASS_ID_STRUCT
:
296 ir_fc
= ctf_field_class_struct_to_ir((void *) fc
, tc
, sc
, ec
);
298 case CTF_FIELD_CLASS_ID_ARRAY
:
299 ir_fc
= ctf_field_class_array_to_ir((void *) fc
, tc
, sc
, ec
);
301 case CTF_FIELD_CLASS_ID_SEQUENCE
:
302 ir_fc
= ctf_field_class_sequence_to_ir((void *) fc
, tc
, sc
, ec
);
304 case CTF_FIELD_CLASS_ID_VARIANT
:
305 ir_fc
= ctf_field_class_variant_to_ir((void *) fc
, tc
, sc
, ec
);
316 bool ctf_field_class_struct_has_immediate_member_in_ir(
317 struct ctf_field_class_struct
*fc
)
320 bool has_immediate_member_in_ir
= false;
322 for (i
= 0; i
< fc
->members
->len
; i
++) {
323 struct ctf_named_field_class
*named_fc
=
324 ctf_field_class_struct_borrow_member_by_index(fc
, i
);
326 if (named_fc
->fc
->in_ir
) {
327 has_immediate_member_in_ir
= true;
333 return has_immediate_member_in_ir
;
337 struct bt_field_class
*scope_ctf_field_class_to_ir(struct ctf_field_class
*fc
,
338 struct ctf_trace_class
*tc
,
339 struct ctf_stream_class
*sc
,
340 struct ctf_event_class
*ec
)
342 struct bt_field_class
*ir_fc
= NULL
;
348 BT_ASSERT(fc
->id
== CTF_FIELD_CLASS_ID_STRUCT
);
350 if (!ctf_field_class_struct_has_immediate_member_in_ir((void *) fc
)) {
352 * Nothing for IR in this scope: typical for packet
353 * header, packet context, and event header.
358 ir_fc
= ctf_field_class_to_ir(fc
, tc
, sc
, ec
);
365 struct ctf_field_class_int
*borrow_named_int_field_class(
366 struct ctf_field_class_struct
*struct_fc
, const char *name
)
368 struct ctf_named_field_class
*named_fc
= NULL
;
369 struct ctf_field_class_int
*int_fc
= NULL
;
375 named_fc
= ctf_field_class_struct_borrow_member_by_name(struct_fc
, name
);
380 if (named_fc
->fc
->id
!= CTF_FIELD_CLASS_ID_INT
&&
381 named_fc
->fc
->id
!= CTF_FIELD_CLASS_ID_ENUM
) {
385 int_fc
= (void *) named_fc
->fc
;
392 struct bt_event_class
*ctf_event_class_to_ir(struct ctf_event_class
*ec
,
393 struct bt_stream_class
*ir_sc
, struct ctf_trace_class
*tc
,
394 struct ctf_stream_class
*sc
)
397 struct bt_event_class
*ir_ec
= NULL
;
399 if (ec
->is_translated
) {
400 ir_ec
= bt_stream_class_borrow_event_class_by_id(
406 ir_ec
= bt_event_class_create_with_id(ir_sc
, ec
->id
);
410 if (ec
->spec_context_fc
) {
411 struct bt_field_class
*ir_fc
= scope_ctf_field_class_to_ir(
412 ec
->spec_context_fc
, tc
, sc
, ec
);
415 ret
= bt_event_class_set_specific_context_field_class(
422 if (ec
->payload_fc
) {
423 struct bt_field_class
*ir_fc
= scope_ctf_field_class_to_ir(
424 ec
->payload_fc
, tc
, sc
, ec
);
427 ret
= bt_event_class_set_payload_field_class(ir_ec
,
434 if (ec
->name
->len
> 0) {
435 ret
= bt_event_class_set_name(ir_ec
, ec
->name
->str
);
439 if (ec
->emf_uri
->len
> 0) {
440 ret
= bt_event_class_set_emf_uri(ir_ec
, ec
->emf_uri
->str
);
444 if (ec
->log_level
!= -1) {
445 ret
= bt_event_class_set_log_level(ir_ec
, ec
->log_level
);
449 ec
->is_translated
= true;
458 struct bt_stream_class
*ctf_stream_class_to_ir(struct ctf_stream_class
*sc
,
459 struct bt_trace
*ir_trace
, struct ctf_trace_class
*tc
)
462 struct bt_stream_class
*ir_sc
= NULL
;
463 struct ctf_field_class_int
*int_fc
;
465 if (sc
->is_translated
) {
466 ir_sc
= bt_trace_borrow_stream_class_by_id(ir_trace
, sc
->id
);
471 ir_sc
= bt_stream_class_create_with_id(ir_trace
, sc
->id
);
475 if (sc
->packet_context_fc
) {
476 struct bt_field_class
*ir_fc
= scope_ctf_field_class_to_ir(
477 sc
->packet_context_fc
, tc
, sc
, NULL
);
480 ret
= bt_stream_class_set_packet_context_field_class(
487 if (sc
->event_header_fc
) {
488 struct bt_field_class
*ir_fc
= scope_ctf_field_class_to_ir(
489 sc
->event_header_fc
, tc
, sc
, NULL
);
492 ret
= bt_stream_class_set_event_header_field_class(ir_sc
,
499 if (sc
->event_common_context_fc
) {
500 struct bt_field_class
*ir_fc
= scope_ctf_field_class_to_ir(
501 sc
->event_common_context_fc
, tc
, sc
, NULL
);
504 ret
= bt_stream_class_set_event_common_context_field_class(
511 ret
= bt_stream_class_set_assigns_automatic_event_class_id(ir_sc
,
514 ret
= bt_stream_class_set_assigns_automatic_stream_id(ir_sc
, BT_FALSE
);
517 if (sc
->default_clock_class
) {
518 ret
= bt_stream_class_set_default_clock_class(ir_sc
,
519 sc
->default_clock_class
);
523 int_fc
= borrow_named_int_field_class((void *) sc
->packet_context_fc
,
526 if (int_fc
->meaning
== CTF_FIELD_CLASS_MEANING_DISC_EV_REC_COUNTER_SNAPSHOT
) {
527 ret
= bt_stream_class_set_packets_have_discarded_event_counter_snapshot(
533 int_fc
= borrow_named_int_field_class((void *) sc
->packet_context_fc
,
536 if (int_fc
->meaning
== CTF_FIELD_CLASS_MEANING_PACKET_COUNTER_SNAPSHOT
) {
537 ret
= bt_stream_class_set_packets_have_packet_counter_snapshot(
543 int_fc
= borrow_named_int_field_class((void *) sc
->packet_context_fc
,
546 if (int_fc
->meaning
== CTF_FIELD_CLASS_MEANING_PACKET_BEGINNING_TIME
) {
547 ret
= bt_stream_class_set_packets_have_default_beginning_clock_value(
553 int_fc
= borrow_named_int_field_class((void *) sc
->packet_context_fc
,
556 if (int_fc
->meaning
== CTF_FIELD_CLASS_MEANING_PACKET_END_TIME
) {
557 ret
= bt_stream_class_set_packets_have_default_end_clock_value(
563 sc
->is_translated
= true;
571 int ctf_trace_class_to_ir(struct bt_trace
*ir_trace
,
572 struct ctf_trace_class
*tc
)
577 if (tc
->is_translated
) {
581 if (tc
->packet_header_fc
) {
582 struct bt_field_class
*ir_fc
= scope_ctf_field_class_to_ir(
583 tc
->packet_header_fc
, tc
, NULL
, NULL
);
586 ret
= bt_trace_set_packet_header_field_class(ir_trace
,
593 if (tc
->name
->len
> 0) {
594 ret
= bt_trace_set_name(ir_trace
, tc
->name
->str
);
600 if (tc
->is_uuid_set
) {
601 ret
= bt_trace_set_uuid(ir_trace
, tc
->uuid
);
607 for (i
= 0; i
< tc
->env_entries
->len
; i
++) {
608 struct ctf_trace_class_env_entry
*env_entry
=
609 ctf_trace_class_borrow_env_entry_by_index(tc
, i
);
611 switch (env_entry
->type
) {
612 case CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
:
613 ret
= bt_trace_set_environment_entry_integer(
614 ir_trace
, env_entry
->name
->str
,
617 case CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR
:
618 ret
= bt_trace_set_environment_entry_string(
619 ir_trace
, env_entry
->name
->str
,
620 env_entry
->value
.str
->str
);
631 ret
= bt_trace_set_assigns_automatic_stream_class_id(ir_trace
,
637 tc
->is_translated
= true;
638 tc
->ir_tc
= ir_trace
;
645 int ctf_trace_class_translate(struct bt_trace
*ir_trace
,
646 struct ctf_trace_class
*tc
)
651 ret
= ctf_trace_class_to_ir(ir_trace
, tc
);
656 for (i
= 0; i
< tc
->stream_classes
->len
; i
++) {
658 struct ctf_stream_class
*sc
= tc
->stream_classes
->pdata
[i
];
659 struct bt_stream_class
*ir_sc
;
661 ir_sc
= ctf_stream_class_to_ir(sc
, ir_trace
, tc
);
667 for (j
= 0; j
< sc
->event_classes
->len
; j
++) {
668 struct ctf_event_class
*ec
= sc
->event_classes
->pdata
[j
];
669 struct bt_event_class
*ir_ec
;
671 ir_ec
= ctf_event_class_to_ir(ec
, ir_sc
, tc
, sc
);