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 bt_trace_class
*ir_tc
;
30 bt_stream_class
*ir_sc
;
31 struct ctf_trace_class
*tc
;
32 struct ctf_stream_class
*sc
;
33 struct ctf_event_class
*ec
;
38 bt_field_class
*ctf_field_class_to_ir(struct ctx
*ctx
,
39 struct ctf_field_class
*fc
);
42 void ctf_field_class_int_set_props(struct ctf_field_class_int
*fc
,
43 bt_field_class
*ir_fc
)
45 bt_field_class_integer_set_field_value_range(ir_fc
,
47 bt_field_class_integer_set_preferred_display_base(ir_fc
,
52 bt_field_class
*ctf_field_class_int_to_ir(struct ctx
*ctx
,
53 struct ctf_field_class_int
*fc
)
55 bt_field_class
*ir_fc
;
58 ir_fc
= bt_field_class_signed_integer_create(ctx
->ir_tc
);
60 ir_fc
= bt_field_class_unsigned_integer_create(ctx
->ir_tc
);
64 ctf_field_class_int_set_props(fc
, ir_fc
);
69 bt_field_class
*ctf_field_class_enum_to_ir(struct ctx
*ctx
,
70 struct ctf_field_class_enum
*fc
)
73 bt_field_class
*ir_fc
;
76 if (fc
->base
.is_signed
) {
77 ir_fc
= bt_field_class_signed_enumeration_create(ctx
->ir_tc
);
79 ir_fc
= bt_field_class_unsigned_enumeration_create(ctx
->ir_tc
);
83 ctf_field_class_int_set_props((void *) fc
, ir_fc
);
85 for (i
= 0; i
< fc
->mappings
->len
; i
++) {
86 struct ctf_field_class_enum_mapping
*mapping
=
87 ctf_field_class_enum_borrow_mapping_by_index(fc
, i
);
89 if (fc
->base
.is_signed
) {
90 ret
= bt_field_class_signed_enumeration_map_range(
91 ir_fc
, mapping
->label
->str
,
92 mapping
->range
.lower
.i
, mapping
->range
.upper
.i
);
94 ret
= bt_field_class_unsigned_enumeration_map_range(
95 ir_fc
, mapping
->label
->str
,
96 mapping
->range
.lower
.u
, mapping
->range
.upper
.u
);
106 bt_field_class
*ctf_field_class_float_to_ir(struct ctx
*ctx
,
107 struct ctf_field_class_float
*fc
)
109 bt_field_class
*ir_fc
;
111 ir_fc
= bt_field_class_real_create(ctx
->ir_tc
);
114 if (fc
->base
.size
== 32) {
115 bt_field_class_real_set_is_single_precision(ir_fc
,
123 bt_field_class
*ctf_field_class_string_to_ir(struct ctx
*ctx
,
124 struct ctf_field_class_string
*fc
)
126 bt_field_class
*ir_fc
= bt_field_class_string_create(ctx
->ir_tc
);
133 void translate_struct_field_class_members(struct ctx
*ctx
,
134 struct ctf_field_class_struct
*fc
, bt_field_class
*ir_fc
,
135 bool with_header_prefix
,
136 struct ctf_field_class_struct
*context_fc
)
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 bt_field_class
*member_ir_fc
;
145 const char *name
= named_fc
->name
->str
;
147 if (!named_fc
->fc
->in_ir
) {
151 member_ir_fc
= ctf_field_class_to_ir(ctx
, named_fc
->fc
);
152 BT_ASSERT(member_ir_fc
);
153 ret
= bt_field_class_structure_append_member(ir_fc
, name
,
156 bt_field_class_put_ref(member_ir_fc
);
161 bt_field_class
*ctf_field_class_struct_to_ir(struct ctx
*ctx
,
162 struct ctf_field_class_struct
*fc
)
164 bt_field_class
*ir_fc
= bt_field_class_structure_create(ctx
->ir_tc
);
167 translate_struct_field_class_members(ctx
, fc
, ir_fc
, false, NULL
);
172 bt_field_class
*borrow_ir_fc_from_field_path(struct ctx
*ctx
,
173 struct ctf_field_path
*field_path
)
175 bt_field_class
*ir_fc
= NULL
;
176 struct ctf_field_class
*fc
= ctf_field_path_borrow_field_class(
177 field_path
, ctx
->tc
, ctx
->sc
, ctx
->ec
);
189 bt_field_class
*ctf_field_class_variant_to_ir(struct ctx
*ctx
,
190 struct ctf_field_class_variant
*fc
)
193 bt_field_class
*ir_fc
= bt_field_class_variant_create(ctx
->ir_tc
);
198 if (fc
->tag_path
.root
!= CTF_SCOPE_PACKET_HEADER
&&
199 fc
->tag_path
.root
!= CTF_SCOPE_EVENT_HEADER
) {
200 ret
= bt_field_class_variant_set_selector_field_class(
201 ir_fc
, borrow_ir_fc_from_field_path(ctx
,
206 for (i
= 0; i
< fc
->options
->len
; i
++) {
207 struct ctf_named_field_class
*named_fc
=
208 ctf_field_class_variant_borrow_option_by_index(fc
, i
);
209 bt_field_class
*option_ir_fc
;
211 BT_ASSERT(named_fc
->fc
->in_ir
);
212 option_ir_fc
= ctf_field_class_to_ir(ctx
, named_fc
->fc
);
213 BT_ASSERT(option_ir_fc
);
214 ret
= bt_field_class_variant_append_option(
215 ir_fc
, named_fc
->name
->str
, option_ir_fc
);
217 bt_field_class_put_ref(option_ir_fc
);
224 bt_field_class
*ctf_field_class_array_to_ir(struct ctx
*ctx
,
225 struct ctf_field_class_array
*fc
)
227 bt_field_class
*ir_fc
;
228 bt_field_class
*elem_ir_fc
;
230 if (fc
->base
.is_text
) {
231 ir_fc
= bt_field_class_string_create(ctx
->ir_tc
);
236 elem_ir_fc
= ctf_field_class_to_ir(ctx
, fc
->base
.elem_fc
);
237 BT_ASSERT(elem_ir_fc
);
238 ir_fc
= bt_field_class_static_array_create(ctx
->ir_tc
, elem_ir_fc
,
241 bt_field_class_put_ref(elem_ir_fc
);
248 bt_field_class
*ctf_field_class_sequence_to_ir(struct ctx
*ctx
,
249 struct ctf_field_class_sequence
*fc
)
252 bt_field_class
*ir_fc
;
253 bt_field_class
*elem_ir_fc
;
255 if (fc
->base
.is_text
) {
256 ir_fc
= bt_field_class_string_create(ctx
->ir_tc
);
261 elem_ir_fc
= ctf_field_class_to_ir(ctx
, fc
->base
.elem_fc
);
262 BT_ASSERT(elem_ir_fc
);
263 ir_fc
= bt_field_class_dynamic_array_create(ctx
->ir_tc
, elem_ir_fc
);
265 bt_field_class_put_ref(elem_ir_fc
);
268 if (fc
->length_path
.root
!= CTF_SCOPE_PACKET_HEADER
&&
269 fc
->length_path
.root
!= CTF_SCOPE_EVENT_HEADER
) {
270 ret
= bt_field_class_dynamic_array_set_length_field_class(
271 ir_fc
, borrow_ir_fc_from_field_path(ctx
, &fc
->length_path
));
280 bt_field_class
*ctf_field_class_to_ir(struct ctx
*ctx
,
281 struct ctf_field_class
*fc
)
283 bt_field_class
*ir_fc
= NULL
;
286 BT_ASSERT(fc
->in_ir
);
289 case CTF_FIELD_CLASS_TYPE_INT
:
290 ir_fc
= ctf_field_class_int_to_ir(ctx
, (void *) fc
);
292 case CTF_FIELD_CLASS_TYPE_ENUM
:
293 ir_fc
= ctf_field_class_enum_to_ir(ctx
, (void *) fc
);
295 case CTF_FIELD_CLASS_TYPE_FLOAT
:
296 ir_fc
= ctf_field_class_float_to_ir(ctx
, (void *) fc
);
298 case CTF_FIELD_CLASS_TYPE_STRING
:
299 ir_fc
= ctf_field_class_string_to_ir(ctx
, (void *) fc
);
301 case CTF_FIELD_CLASS_TYPE_STRUCT
:
302 ir_fc
= ctf_field_class_struct_to_ir(ctx
, (void *) fc
);
304 case CTF_FIELD_CLASS_TYPE_ARRAY
:
305 ir_fc
= ctf_field_class_array_to_ir(ctx
, (void *) fc
);
307 case CTF_FIELD_CLASS_TYPE_SEQUENCE
:
308 ir_fc
= ctf_field_class_sequence_to_ir(ctx
, (void *) fc
);
310 case CTF_FIELD_CLASS_TYPE_VARIANT
:
311 ir_fc
= ctf_field_class_variant_to_ir(ctx
, (void *) fc
);
322 bool ctf_field_class_struct_has_immediate_member_in_ir(
323 struct ctf_field_class_struct
*fc
)
326 bool has_immediate_member_in_ir
= false;
328 for (i
= 0; i
< fc
->members
->len
; i
++) {
329 struct ctf_named_field_class
*named_fc
=
330 ctf_field_class_struct_borrow_member_by_index(fc
, i
);
332 if (named_fc
->fc
->in_ir
) {
333 has_immediate_member_in_ir
= true;
339 return has_immediate_member_in_ir
;
343 bt_field_class
*scope_ctf_field_class_to_ir(struct ctx
*ctx
)
345 bt_field_class
*ir_fc
= NULL
;
346 struct ctf_field_class
*fc
= NULL
;
348 switch (ctx
->scope
) {
349 case CTF_SCOPE_PACKET_CONTEXT
:
350 fc
= ctx
->sc
->packet_context_fc
;
352 case CTF_SCOPE_EVENT_COMMON_CONTEXT
:
353 fc
= ctx
->sc
->event_common_context_fc
;
355 case CTF_SCOPE_EVENT_SPECIFIC_CONTEXT
:
356 fc
= ctx
->ec
->spec_context_fc
;
358 case CTF_SCOPE_EVENT_PAYLOAD
:
359 fc
= ctx
->ec
->payload_fc
;
365 if (fc
&& ctf_field_class_struct_has_immediate_member_in_ir(
367 ir_fc
= ctf_field_class_to_ir(ctx
, fc
);
374 struct ctf_field_class_int
*borrow_named_int_field_class(
375 struct ctf_field_class_struct
*struct_fc
, const char *name
)
377 struct ctf_named_field_class
*named_fc
= NULL
;
378 struct ctf_field_class_int
*int_fc
= NULL
;
384 named_fc
= ctf_field_class_struct_borrow_member_by_name(struct_fc
, name
);
389 if (named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&&
390 named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
394 int_fc
= (void *) named_fc
->fc
;
401 void ctf_event_class_to_ir(struct ctx
*ctx
)
404 bt_event_class
*ir_ec
= NULL
;
405 bt_field_class
*ir_fc
;
409 if (ctx
->ec
->is_translated
) {
410 ir_ec
= bt_stream_class_borrow_event_class_by_id(
411 ctx
->ir_sc
, ctx
->ec
->id
);
416 ir_ec
= bt_event_class_create_with_id(ctx
->ir_sc
, ctx
->ec
->id
);
418 bt_event_class_put_ref(ir_ec
);
419 ctx
->scope
= CTF_SCOPE_EVENT_SPECIFIC_CONTEXT
;
420 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
422 ret
= bt_event_class_set_specific_context_field_class(
425 bt_field_class_put_ref(ir_fc
);
428 ctx
->scope
= CTF_SCOPE_EVENT_PAYLOAD
;
429 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
431 ret
= bt_event_class_set_payload_field_class(ir_ec
,
434 bt_field_class_put_ref(ir_fc
);
437 if (ctx
->ec
->name
->len
> 0) {
438 ret
= bt_event_class_set_name(ir_ec
, ctx
->ec
->name
->str
);
442 if (ctx
->ec
->emf_uri
->len
> 0) {
443 ret
= bt_event_class_set_emf_uri(ir_ec
, ctx
->ec
->emf_uri
->str
);
447 if (ctx
->ec
->log_level
!= -1) {
448 bt_event_class_set_log_level(ir_ec
, ctx
->ec
->log_level
);
451 ctx
->ec
->is_translated
= true;
452 ctx
->ec
->ir_ec
= ir_ec
;
460 void ctf_stream_class_to_ir(struct ctx
*ctx
)
463 struct ctf_field_class_int
*int_fc
;
464 bt_field_class
*ir_fc
;
468 if (ctx
->sc
->is_translated
) {
469 ctx
->ir_sc
= bt_trace_class_borrow_stream_class_by_id(
470 ctx
->ir_tc
, ctx
->sc
->id
);
471 BT_ASSERT(ctx
->ir_sc
);
475 ctx
->ir_sc
= bt_stream_class_create_with_id(ctx
->ir_tc
, ctx
->sc
->id
);
476 BT_ASSERT(ctx
->ir_sc
);
477 bt_stream_class_put_ref(ctx
->ir_sc
);
478 ctx
->scope
= CTF_SCOPE_PACKET_CONTEXT
;
479 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
481 ret
= bt_stream_class_set_packet_context_field_class(
484 bt_field_class_put_ref(ir_fc
);
487 ctx
->scope
= CTF_SCOPE_EVENT_COMMON_CONTEXT
;
488 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
490 ret
= bt_stream_class_set_event_common_context_field_class(
493 bt_field_class_put_ref(ir_fc
);
496 bt_stream_class_set_assigns_automatic_event_class_id(ctx
->ir_sc
,
498 bt_stream_class_set_assigns_automatic_stream_id(ctx
->ir_sc
, BT_FALSE
);
500 if (ctx
->sc
->default_clock_class
) {
501 BT_ASSERT(ctx
->sc
->default_clock_class
->ir_cc
);
502 ret
= bt_stream_class_set_default_clock_class(ctx
->ir_sc
,
503 ctx
->sc
->default_clock_class
->ir_cc
);
507 int_fc
= borrow_named_int_field_class((void *) ctx
->sc
->packet_context_fc
,
510 if (int_fc
->meaning
== CTF_FIELD_CLASS_MEANING_DISC_EV_REC_COUNTER_SNAPSHOT
) {
511 bt_stream_class_set_packets_have_discarded_event_counter_snapshot(
512 ctx
->ir_sc
, BT_TRUE
);
516 int_fc
= borrow_named_int_field_class((void *) ctx
->sc
->packet_context_fc
,
519 if (int_fc
->meaning
== CTF_FIELD_CLASS_MEANING_PACKET_COUNTER_SNAPSHOT
) {
520 bt_stream_class_set_packets_have_packet_counter_snapshot(
521 ctx
->ir_sc
, BT_TRUE
);
525 int_fc
= borrow_named_int_field_class((void *) ctx
->sc
->packet_context_fc
,
528 if (int_fc
->meaning
== CTF_FIELD_CLASS_MEANING_PACKET_BEGINNING_TIME
) {
529 bt_stream_class_set_packets_have_default_beginning_clock_snapshot(
530 ctx
->ir_sc
, BT_TRUE
);
534 int_fc
= borrow_named_int_field_class((void *) ctx
->sc
->packet_context_fc
,
537 if (int_fc
->meaning
== CTF_FIELD_CLASS_MEANING_PACKET_END_TIME
) {
538 bt_stream_class_set_packets_have_default_end_clock_snapshot(
539 ctx
->ir_sc
, BT_TRUE
);
543 ctx
->sc
->is_translated
= true;
544 ctx
->sc
->ir_sc
= ctx
->ir_sc
;
551 void ctf_clock_class_to_ir(bt_clock_class
*ir_cc
, struct ctf_clock_class
*cc
)
555 if (strlen(cc
->name
->str
) > 0) {
556 ret
= bt_clock_class_set_name(ir_cc
, cc
->name
->str
);
560 if (strlen(cc
->description
->str
) > 0) {
561 ret
= bt_clock_class_set_description(ir_cc
, cc
->description
->str
);
565 bt_clock_class_set_frequency(ir_cc
, cc
->frequency
);
566 bt_clock_class_set_precision(ir_cc
, cc
->precision
);
567 bt_clock_class_set_offset(ir_cc
, cc
->offset_seconds
, cc
->offset_cycles
);
570 bt_clock_class_set_uuid(ir_cc
, cc
->uuid
);
573 bt_clock_class_set_is_absolute(ir_cc
, cc
->is_absolute
);
577 int ctf_trace_class_to_ir(struct ctx
*ctx
)
583 BT_ASSERT(ctx
->ir_tc
);
585 if (ctx
->tc
->is_translated
) {
589 if (ctx
->tc
->is_uuid_set
) {
590 bt_trace_class_set_uuid(ctx
->ir_tc
, ctx
->tc
->uuid
);
593 for (i
= 0; i
< ctx
->tc
->env_entries
->len
; i
++) {
594 struct ctf_trace_class_env_entry
*env_entry
=
595 ctf_trace_class_borrow_env_entry_by_index(ctx
->tc
, i
);
597 switch (env_entry
->type
) {
598 case CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
:
599 ret
= bt_trace_class_set_environment_entry_integer(
600 ctx
->ir_tc
, env_entry
->name
->str
,
603 case CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR
:
604 ret
= bt_trace_class_set_environment_entry_string(
605 ctx
->ir_tc
, env_entry
->name
->str
,
606 env_entry
->value
.str
->str
);
617 for (i
= 0; i
< ctx
->tc
->clock_classes
->len
; i
++) {
618 struct ctf_clock_class
*cc
= ctx
->tc
->clock_classes
->pdata
[i
];
620 cc
->ir_cc
= bt_clock_class_create(ctx
->ir_tc
);
621 ctf_clock_class_to_ir(cc
->ir_cc
, cc
);
624 bt_trace_class_set_assigns_automatic_stream_class_id(ctx
->ir_tc
,
626 ctx
->tc
->is_translated
= true;
627 ctx
->tc
->ir_tc
= ctx
->ir_tc
;
634 int ctf_trace_class_translate(bt_trace_class
*ir_tc
,
635 struct ctf_trace_class
*tc
)
639 struct ctx ctx
= { 0 };
643 ret
= ctf_trace_class_to_ir(&ctx
);
648 for (i
= 0; i
< tc
->stream_classes
->len
; i
++) {
650 ctx
.sc
= tc
->stream_classes
->pdata
[i
];
652 ctf_stream_class_to_ir(&ctx
);
654 for (j
= 0; j
< ctx
.sc
->event_classes
->len
; j
++) {
655 ctx
.ec
= ctx
.sc
->event_classes
->pdata
[j
];
657 ctf_event_class_to_ir(&ctx
);