lib: make trace IR API const-correct
[babeltrace.git] / plugins / ctf / common / metadata / ctf-meta-translate.c
1 /*
2 * Copyright 2018 - Philippe Proulx <pproulx@efficios.com>
3 *
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:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 */
14
15 #define BT_LOG_TAG "PLUGIN-CTF-METADATA-META-TRANSLATE"
16 #include "logging.h"
17
18 #include <babeltrace/babeltrace.h>
19 #include <babeltrace/babeltrace-internal.h>
20 #include <babeltrace/assert-internal.h>
21 #include <glib.h>
22 #include <stdint.h>
23 #include <string.h>
24 #include <inttypes.h>
25
26 #include "ctf-meta-visitors.h"
27
28 static inline
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);
33
34 static inline
35 void ctf_field_class_int_set_props(struct ctf_field_class_int *fc,
36 struct bt_field_class *ir_fc)
37 {
38 bt_field_class_integer_set_field_value_range(ir_fc,
39 fc->base.size);
40 bt_field_class_integer_set_preferred_display_base(ir_fc,
41 fc->disp_base);
42 }
43
44 static inline
45 struct bt_field_class *ctf_field_class_int_to_ir(
46 struct ctf_field_class_int *fc)
47 {
48 struct bt_field_class *ir_fc;
49
50 if (fc->is_signed) {
51 ir_fc = bt_field_class_signed_integer_create();
52 } else {
53 ir_fc = bt_field_class_unsigned_integer_create();
54 }
55
56 BT_ASSERT(ir_fc);
57 ctf_field_class_int_set_props(fc, ir_fc);
58 return ir_fc;
59 }
60
61 static inline
62 struct bt_field_class *ctf_field_class_enum_to_ir(
63 struct ctf_field_class_enum *fc)
64 {
65 int ret;
66 struct bt_field_class *ir_fc;
67 uint64_t i;
68
69 if (fc->base.is_signed) {
70 ir_fc = bt_field_class_signed_enumeration_create();
71 } else {
72 ir_fc = bt_field_class_unsigned_enumeration_create();
73 }
74
75 BT_ASSERT(ir_fc);
76 ctf_field_class_int_set_props((void *) fc, ir_fc);
77
78 for (i = 0; i < fc->mappings->len; i++) {
79 struct ctf_field_class_enum_mapping *mapping =
80 ctf_field_class_enum_borrow_mapping_by_index(fc, i);
81
82 if (fc->base.is_signed) {
83 ret = bt_field_class_signed_enumeration_map_range(
84 ir_fc, mapping->label->str,
85 mapping->range.lower.i, mapping->range.upper.i);
86 } else {
87 ret = bt_field_class_unsigned_enumeration_map_range(
88 ir_fc, mapping->label->str,
89 mapping->range.lower.u, mapping->range.upper.u);
90 }
91
92 BT_ASSERT(ret == 0);
93 }
94
95 return ir_fc;
96 }
97
98 static inline
99 struct bt_field_class *ctf_field_class_float_to_ir(
100 struct ctf_field_class_float *fc)
101 {
102 struct bt_field_class *ir_fc;
103
104 ir_fc = bt_field_class_real_create();
105 BT_ASSERT(ir_fc);
106
107 if (fc->base.size == 32) {
108 bt_field_class_real_set_is_single_precision(ir_fc,
109 BT_TRUE);
110 }
111
112 return ir_fc;
113 }
114
115 static inline
116 struct bt_field_class *ctf_field_class_string_to_ir(
117 struct ctf_field_class_string *fc)
118 {
119 struct bt_field_class *ir_fc =
120 bt_field_class_string_create();
121
122 BT_ASSERT(ir_fc);
123 return ir_fc;
124 }
125
126 static inline
127 struct bt_field_class *ctf_field_class_struct_to_ir(
128 struct ctf_field_class_struct *fc,
129 struct ctf_trace_class *tc,
130 struct ctf_stream_class *sc,
131 struct ctf_event_class *ec)
132 {
133 int ret;
134 struct bt_field_class *ir_fc =
135 bt_field_class_structure_create();
136 uint64_t i;
137
138 BT_ASSERT(ir_fc);
139
140 for (i = 0; i < fc->members->len; i++) {
141 struct ctf_named_field_class *named_fc =
142 ctf_field_class_struct_borrow_member_by_index(fc, i);
143 struct bt_field_class *member_ir_fc;
144
145 if (!named_fc->fc->in_ir) {
146 continue;
147 }
148
149 member_ir_fc = ctf_field_class_to_ir(named_fc->fc, tc, sc, ec);
150 BT_ASSERT(member_ir_fc);
151 ret = bt_field_class_structure_append_member(
152 ir_fc, named_fc->name->str, member_ir_fc);
153 BT_ASSERT(ret == 0);
154 bt_object_put_ref(member_ir_fc);
155 }
156
157 return ir_fc;
158 }
159
160 static inline
161 struct bt_field_class *borrow_ir_ft_from_field_path(
162 struct ctf_field_path *field_path,
163 struct ctf_trace_class *tc,
164 struct ctf_stream_class *sc,
165 struct ctf_event_class *ec)
166 {
167 struct bt_field_class *ir_fc = NULL;
168 struct ctf_field_class *fc = ctf_field_path_borrow_field_class(
169 field_path, tc, sc, ec);
170
171 BT_ASSERT(fc);
172
173 if (fc->in_ir) {
174 ir_fc = fc->ir_fc;
175 }
176
177 return ir_fc;
178 }
179
180 static inline
181 struct bt_field_class *ctf_field_class_variant_to_ir(
182 struct ctf_field_class_variant *fc,
183 struct ctf_trace_class *tc,
184 struct ctf_stream_class *sc,
185 struct ctf_event_class *ec)
186 {
187 int ret;
188 struct bt_field_class *ir_fc =
189 bt_field_class_variant_create();
190 uint64_t i;
191
192 BT_ASSERT(ir_fc);
193 ret = bt_field_class_variant_set_selector_field_class(
194 ir_fc, borrow_ir_ft_from_field_path(&fc->tag_path, tc, sc, ec));
195 BT_ASSERT(ret == 0);
196
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;
201
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(
206 ir_fc, named_fc->name->str, option_ir_fc);
207 BT_ASSERT(ret == 0);
208 bt_object_put_ref(option_ir_fc);
209 }
210
211 return ir_fc;
212 }
213
214 static inline
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)
220 {
221 struct bt_field_class *ir_fc;
222 struct bt_field_class *elem_ir_fc;
223
224 if (fc->base.is_text) {
225 ir_fc = bt_field_class_string_create();
226 BT_ASSERT(ir_fc);
227 goto end;
228 }
229
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,
233 fc->length);
234 BT_ASSERT(ir_fc);
235 bt_object_put_ref(elem_ir_fc);
236
237 end:
238 return ir_fc;
239 }
240
241 static inline
242 struct bt_field_class *ctf_field_class_sequence_to_ir(
243 struct ctf_field_class_sequence *fc,
244 struct ctf_trace_class *tc,
245 struct ctf_stream_class *sc,
246 struct ctf_event_class *ec)
247 {
248 int ret;
249 struct bt_field_class *ir_fc;
250 struct bt_field_class *elem_ir_fc;
251
252 if (fc->base.is_text) {
253 ir_fc = bt_field_class_string_create();
254 BT_ASSERT(ir_fc);
255 goto end;
256 }
257
258 elem_ir_fc = ctf_field_class_to_ir(fc->base.elem_fc, tc, sc, ec);
259 BT_ASSERT(elem_ir_fc);
260 ir_fc = bt_field_class_dynamic_array_create(elem_ir_fc);
261 BT_ASSERT(ir_fc);
262 bt_object_put_ref(elem_ir_fc);
263 BT_ASSERT(ir_fc);
264 ret = bt_field_class_dynamic_array_set_length_field_class(
265 ir_fc,
266 borrow_ir_ft_from_field_path(&fc->length_path, tc, sc, ec));
267 BT_ASSERT(ret == 0);
268
269 end:
270 return ir_fc;
271 }
272
273 static inline
274 struct bt_field_class *ctf_field_class_to_ir(struct ctf_field_class *fc,
275 struct ctf_trace_class *tc,
276 struct ctf_stream_class *sc,
277 struct ctf_event_class *ec)
278 {
279 struct bt_field_class *ir_fc = NULL;
280
281 BT_ASSERT(fc);
282 BT_ASSERT(fc->in_ir);
283
284 switch (fc->type) {
285 case CTF_FIELD_CLASS_TYPE_INT:
286 ir_fc = ctf_field_class_int_to_ir((void *) fc);
287 break;
288 case CTF_FIELD_CLASS_TYPE_ENUM:
289 ir_fc = ctf_field_class_enum_to_ir((void *) fc);
290 break;
291 case CTF_FIELD_CLASS_TYPE_FLOAT:
292 ir_fc = ctf_field_class_float_to_ir((void *) fc);
293 break;
294 case CTF_FIELD_CLASS_TYPE_STRING:
295 ir_fc = ctf_field_class_string_to_ir((void *) fc);
296 break;
297 case CTF_FIELD_CLASS_TYPE_STRUCT:
298 ir_fc = ctf_field_class_struct_to_ir((void *) fc, tc, sc, ec);
299 break;
300 case CTF_FIELD_CLASS_TYPE_ARRAY:
301 ir_fc = ctf_field_class_array_to_ir((void *) fc, tc, sc, ec);
302 break;
303 case CTF_FIELD_CLASS_TYPE_SEQUENCE:
304 ir_fc = ctf_field_class_sequence_to_ir((void *) fc, tc, sc, ec);
305 break;
306 case CTF_FIELD_CLASS_TYPE_VARIANT:
307 ir_fc = ctf_field_class_variant_to_ir((void *) fc, tc, sc, ec);
308 break;
309 default:
310 abort();
311 }
312
313 fc->ir_fc = ir_fc;
314 return ir_fc;
315 }
316
317 static inline
318 bool ctf_field_class_struct_has_immediate_member_in_ir(
319 struct ctf_field_class_struct *fc)
320 {
321 uint64_t i;
322 bool has_immediate_member_in_ir = false;
323
324 for (i = 0; i < fc->members->len; i++) {
325 struct ctf_named_field_class *named_fc =
326 ctf_field_class_struct_borrow_member_by_index(fc, i);
327
328 if (named_fc->fc->in_ir) {
329 has_immediate_member_in_ir = true;
330 goto end;
331 }
332 }
333
334 end:
335 return has_immediate_member_in_ir;
336 }
337
338 static inline
339 struct bt_field_class *scope_ctf_field_class_to_ir(struct ctf_field_class *fc,
340 struct ctf_trace_class *tc,
341 struct ctf_stream_class *sc,
342 struct ctf_event_class *ec)
343 {
344 struct bt_field_class *ir_fc = NULL;
345
346 if (!fc) {
347 goto end;
348 }
349
350 BT_ASSERT(fc->type == CTF_FIELD_CLASS_TYPE_STRUCT);
351
352 if (!ctf_field_class_struct_has_immediate_member_in_ir((void *) fc)) {
353 /*
354 * Nothing for IR in this scope: typical for packet
355 * header, packet context, and event header.
356 */
357 goto end;
358 }
359
360 ir_fc = ctf_field_class_to_ir(fc, tc, sc, ec);
361
362 end:
363 return ir_fc;
364 }
365
366 static inline
367 struct ctf_field_class_int *borrow_named_int_field_class(
368 struct ctf_field_class_struct *struct_fc, const char *name)
369 {
370 struct ctf_named_field_class *named_fc = NULL;
371 struct ctf_field_class_int *int_fc = NULL;
372
373 if (!struct_fc) {
374 goto end;
375 }
376
377 named_fc = ctf_field_class_struct_borrow_member_by_name(struct_fc, name);
378 if (!named_fc) {
379 goto end;
380 }
381
382 if (named_fc->fc->type != CTF_FIELD_CLASS_TYPE_INT &&
383 named_fc->fc->type != CTF_FIELD_CLASS_TYPE_ENUM) {
384 goto end;
385 }
386
387 int_fc = (void *) named_fc->fc;
388
389 end:
390 return int_fc;
391 }
392
393 static inline
394 struct bt_event_class *ctf_event_class_to_ir(struct ctf_event_class *ec,
395 struct bt_stream_class *ir_sc, struct ctf_trace_class *tc,
396 struct ctf_stream_class *sc)
397 {
398 int ret;
399 struct bt_event_class *ir_ec = NULL;
400
401 if (ec->is_translated) {
402 ir_ec = bt_stream_class_borrow_event_class_by_id(
403 ir_sc, ec->id);
404 BT_ASSERT(ir_ec);
405 goto end;
406 }
407
408 ir_ec = bt_event_class_create_with_id(ir_sc, ec->id);
409 BT_ASSERT(ir_ec);
410 bt_object_put_ref(ir_ec);
411
412 if (ec->spec_context_fc) {
413 struct bt_field_class *ir_fc = scope_ctf_field_class_to_ir(
414 ec->spec_context_fc, tc, sc, ec);
415
416 if (ir_fc) {
417 ret = bt_event_class_set_specific_context_field_class(
418 ir_ec, ir_fc);
419 BT_ASSERT(ret == 0);
420 bt_object_put_ref(ir_fc);
421 }
422 }
423
424 if (ec->payload_fc) {
425 struct bt_field_class *ir_fc = scope_ctf_field_class_to_ir(
426 ec->payload_fc, tc, sc, ec);
427
428 if (ir_fc) {
429 ret = bt_event_class_set_payload_field_class(ir_ec,
430 ir_fc);
431 BT_ASSERT(ret == 0);
432 bt_object_put_ref(ir_fc);
433 }
434 }
435
436 if (ec->name->len > 0) {
437 ret = bt_event_class_set_name(ir_ec, ec->name->str);
438 BT_ASSERT(ret == 0);
439 }
440
441 if (ec->emf_uri->len > 0) {
442 ret = bt_event_class_set_emf_uri(ir_ec, ec->emf_uri->str);
443 BT_ASSERT(ret == 0);
444 }
445
446 if (ec->log_level != -1) {
447 bt_event_class_set_log_level(ir_ec, ec->log_level);
448 }
449
450 ec->is_translated = true;
451 ec->ir_ec = ir_ec;
452
453 end:
454 return ir_ec;
455 }
456
457
458 static inline
459 struct bt_stream_class *ctf_stream_class_to_ir(struct ctf_stream_class *sc,
460 struct bt_trace *ir_trace, struct ctf_trace_class *tc)
461 {
462 int ret;
463 struct bt_stream_class *ir_sc = NULL;
464 struct ctf_field_class_int *int_fc;
465
466 if (sc->is_translated) {
467 ir_sc = bt_trace_borrow_stream_class_by_id(
468 ir_trace, sc->id);
469 BT_ASSERT(ir_sc);
470 goto end;
471 }
472
473 ir_sc = bt_stream_class_create_with_id(ir_trace, sc->id);
474 BT_ASSERT(ir_sc);
475 bt_object_put_ref(ir_sc);
476
477 if (sc->packet_context_fc) {
478 struct bt_field_class *ir_fc = scope_ctf_field_class_to_ir(
479 sc->packet_context_fc, tc, sc, NULL);
480
481 if (ir_fc) {
482 ret = bt_stream_class_set_packet_context_field_class(
483 ir_sc, ir_fc);
484 BT_ASSERT(ret == 0);
485 bt_object_put_ref(ir_fc);
486 }
487 }
488
489 if (sc->event_header_fc) {
490 struct bt_field_class *ir_fc = scope_ctf_field_class_to_ir(
491 sc->event_header_fc, tc, sc, NULL);
492
493 if (ir_fc) {
494 ret = bt_stream_class_set_event_header_field_class(
495 ir_sc, ir_fc);
496 BT_ASSERT(ret == 0);
497 bt_object_put_ref(ir_fc);
498 }
499 }
500
501 if (sc->event_common_context_fc) {
502 struct bt_field_class *ir_fc = scope_ctf_field_class_to_ir(
503 sc->event_common_context_fc, tc, sc, NULL);
504
505 if (ir_fc) {
506 ret = bt_stream_class_set_event_common_context_field_class(
507 ir_sc, ir_fc);
508 BT_ASSERT(ret == 0);
509 bt_object_put_ref(ir_fc);
510 }
511 }
512
513 bt_stream_class_set_assigns_automatic_event_class_id(ir_sc,
514 BT_FALSE);
515 bt_stream_class_set_assigns_automatic_stream_id(ir_sc, BT_FALSE);
516
517 if (sc->default_clock_class) {
518 ret = bt_stream_class_set_default_clock_class(ir_sc,
519 sc->default_clock_class);
520 BT_ASSERT(ret == 0);
521 }
522
523 int_fc = borrow_named_int_field_class((void *) sc->packet_context_fc,
524 "events_discarded");
525 if (int_fc) {
526 if (int_fc->meaning == CTF_FIELD_CLASS_MEANING_DISC_EV_REC_COUNTER_SNAPSHOT) {
527 bt_stream_class_set_packets_have_discarded_event_counter_snapshot(
528 ir_sc, BT_TRUE);
529 }
530 }
531
532 int_fc = borrow_named_int_field_class((void *) sc->packet_context_fc,
533 "packet_seq_num");
534 if (int_fc) {
535 if (int_fc->meaning == CTF_FIELD_CLASS_MEANING_PACKET_COUNTER_SNAPSHOT) {
536 bt_stream_class_set_packets_have_packet_counter_snapshot(
537 ir_sc, BT_TRUE);
538 }
539 }
540
541 int_fc = borrow_named_int_field_class((void *) sc->packet_context_fc,
542 "timestamp_begin");
543 if (int_fc) {
544 if (int_fc->meaning == CTF_FIELD_CLASS_MEANING_PACKET_BEGINNING_TIME) {
545 bt_stream_class_set_packets_have_default_beginning_clock_value(
546 ir_sc, BT_TRUE);
547 }
548 }
549
550 int_fc = borrow_named_int_field_class((void *) sc->packet_context_fc,
551 "timestamp_end");
552 if (int_fc) {
553 if (int_fc->meaning == CTF_FIELD_CLASS_MEANING_PACKET_END_TIME) {
554 bt_stream_class_set_packets_have_default_end_clock_value(
555 ir_sc, BT_TRUE);
556 }
557 }
558
559 sc->is_translated = true;
560 sc->ir_sc = ir_sc;
561
562 end:
563 return ir_sc;
564 }
565
566 static inline
567 int ctf_trace_class_to_ir(struct bt_trace *ir_trace,
568 struct ctf_trace_class *tc)
569 {
570 int ret = 0;
571 uint64_t i;
572
573 if (tc->is_translated) {
574 goto end;
575 }
576
577 if (tc->packet_header_fc) {
578 struct bt_field_class *ir_fc = scope_ctf_field_class_to_ir(
579 tc->packet_header_fc, tc, NULL, NULL);
580
581 if (ir_fc) {
582 ret = bt_trace_set_packet_header_field_class(
583 ir_trace, ir_fc);
584 BT_ASSERT(ret == 0);
585 bt_object_put_ref(ir_fc);
586 }
587 }
588
589 if (tc->name->len > 0) {
590 ret = bt_trace_set_name(ir_trace, tc->name->str);
591 if (ret) {
592 goto end;
593 }
594 }
595
596 if (tc->is_uuid_set) {
597 bt_trace_set_uuid(ir_trace, tc->uuid);
598 }
599
600 for (i = 0; i < tc->env_entries->len; i++) {
601 struct ctf_trace_class_env_entry *env_entry =
602 ctf_trace_class_borrow_env_entry_by_index(tc, i);
603
604 switch (env_entry->type) {
605 case CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT:
606 ret = bt_trace_set_environment_entry_integer(
607 ir_trace, env_entry->name->str,
608 env_entry->value.i);
609 break;
610 case CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR:
611 ret = bt_trace_set_environment_entry_string(
612 ir_trace, env_entry->name->str,
613 env_entry->value.str->str);
614 break;
615 default:
616 abort();
617 }
618
619 if (ret) {
620 goto end;
621 }
622 }
623
624 bt_trace_set_assigns_automatic_stream_class_id(ir_trace,
625 BT_FALSE);
626 tc->is_translated = true;
627 tc->ir_tc = ir_trace;
628
629 end:
630 return ret;
631 }
632
633 BT_HIDDEN
634 int ctf_trace_class_translate(struct bt_trace *ir_trace,
635 struct ctf_trace_class *tc)
636 {
637 int ret = 0;
638 uint64_t i;
639
640 ret = ctf_trace_class_to_ir(ir_trace, tc);
641 if (ret) {
642 goto end;
643 }
644
645 for (i = 0; i < tc->stream_classes->len; i++) {
646 uint64_t j;
647 struct ctf_stream_class *sc = tc->stream_classes->pdata[i];
648 struct bt_stream_class *ir_sc;
649
650 ir_sc = ctf_stream_class_to_ir(sc, ir_trace, tc);
651 if (!ir_sc) {
652 ret = -1;
653 goto end;
654 }
655
656 for (j = 0; j < sc->event_classes->len; j++) {
657 struct ctf_event_class *ec = sc->event_classes->pdata[j];
658 struct bt_event_class *ir_ec;
659
660 ir_ec = ctf_event_class_to_ir(ec, ir_sc, tc, sc);
661 if (!ir_ec) {
662 ret = -1;
663 goto end;
664 }
665 }
666 }
667
668 end:
669 return ret;
670 }
This page took 0.043491 seconds and 4 git commands to generate.