608db66fd95fd82493b6da8dd38bc0a9c7212b75
[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 struct ctx {
29 bt_self_component_source *self_comp;
30 bt_trace_class *ir_tc;
31 bt_stream_class *ir_sc;
32 struct ctf_trace_class *tc;
33 struct ctf_stream_class *sc;
34 struct ctf_event_class *ec;
35 enum ctf_scope scope;
36 };
37
38 static inline
39 bt_field_class *ctf_field_class_to_ir(struct ctx *ctx,
40 struct ctf_field_class *fc);
41
42 static inline
43 void ctf_field_class_int_set_props(struct ctf_field_class_int *fc,
44 bt_field_class *ir_fc)
45 {
46 bt_field_class_integer_set_field_value_range(ir_fc,
47 fc->base.size);
48 bt_field_class_integer_set_preferred_display_base(ir_fc,
49 fc->disp_base);
50 }
51
52 static inline
53 bt_field_class *ctf_field_class_int_to_ir(struct ctx *ctx,
54 struct ctf_field_class_int *fc)
55 {
56 bt_field_class *ir_fc;
57
58 if (fc->is_signed) {
59 ir_fc = bt_field_class_signed_integer_create(ctx->ir_tc);
60 } else {
61 ir_fc = bt_field_class_unsigned_integer_create(ctx->ir_tc);
62 }
63
64 BT_ASSERT(ir_fc);
65 ctf_field_class_int_set_props(fc, ir_fc);
66 return ir_fc;
67 }
68
69 static inline
70 bt_field_class *ctf_field_class_enum_to_ir(struct ctx *ctx,
71 struct ctf_field_class_enum *fc)
72 {
73 int ret;
74 bt_field_class *ir_fc;
75 uint64_t i;
76
77 if (fc->base.is_signed) {
78 ir_fc = bt_field_class_signed_enumeration_create(ctx->ir_tc);
79 } else {
80 ir_fc = bt_field_class_unsigned_enumeration_create(ctx->ir_tc);
81 }
82
83 BT_ASSERT(ir_fc);
84 ctf_field_class_int_set_props((void *) fc, ir_fc);
85
86 for (i = 0; i < fc->mappings->len; i++) {
87 struct ctf_field_class_enum_mapping *mapping =
88 ctf_field_class_enum_borrow_mapping_by_index(fc, i);
89
90 if (fc->base.is_signed) {
91 ret = bt_field_class_signed_enumeration_map_range(
92 ir_fc, mapping->label->str,
93 mapping->range.lower.i, mapping->range.upper.i);
94 } else {
95 ret = bt_field_class_unsigned_enumeration_map_range(
96 ir_fc, mapping->label->str,
97 mapping->range.lower.u, mapping->range.upper.u);
98 }
99
100 BT_ASSERT(ret == 0);
101 }
102
103 return ir_fc;
104 }
105
106 static inline
107 bt_field_class *ctf_field_class_float_to_ir(struct ctx *ctx,
108 struct ctf_field_class_float *fc)
109 {
110 bt_field_class *ir_fc;
111
112 ir_fc = bt_field_class_real_create(ctx->ir_tc);
113 BT_ASSERT(ir_fc);
114
115 if (fc->base.size == 32) {
116 bt_field_class_real_set_is_single_precision(ir_fc,
117 BT_TRUE);
118 }
119
120 return ir_fc;
121 }
122
123 static inline
124 bt_field_class *ctf_field_class_string_to_ir(struct ctx *ctx,
125 struct ctf_field_class_string *fc)
126 {
127 bt_field_class *ir_fc = bt_field_class_string_create(ctx->ir_tc);
128
129 BT_ASSERT(ir_fc);
130 return ir_fc;
131 }
132
133 static inline
134 void translate_struct_field_class_members(struct ctx *ctx,
135 struct ctf_field_class_struct *fc, bt_field_class *ir_fc,
136 bool with_header_prefix,
137 struct ctf_field_class_struct *context_fc)
138 {
139 uint64_t i;
140 int ret;
141
142 for (i = 0; i < fc->members->len; i++) {
143 struct ctf_named_field_class *named_fc =
144 ctf_field_class_struct_borrow_member_by_index(fc, i);
145 bt_field_class *member_ir_fc;
146 const char *name = named_fc->name->str;
147
148 if (!named_fc->fc->in_ir) {
149 continue;
150 }
151
152 member_ir_fc = ctf_field_class_to_ir(ctx, named_fc->fc);
153 BT_ASSERT(member_ir_fc);
154 ret = bt_field_class_structure_append_member(ir_fc, name,
155 member_ir_fc);
156 BT_ASSERT(ret == 0);
157 bt_field_class_put_ref(member_ir_fc);
158 }
159 }
160
161 static inline
162 bt_field_class *ctf_field_class_struct_to_ir(struct ctx *ctx,
163 struct ctf_field_class_struct *fc)
164 {
165 bt_field_class *ir_fc = bt_field_class_structure_create(ctx->ir_tc);
166
167 BT_ASSERT(ir_fc);
168 translate_struct_field_class_members(ctx, fc, ir_fc, false, NULL);
169 return ir_fc;
170 }
171
172 static inline
173 bt_field_class *borrow_ir_fc_from_field_path(struct ctx *ctx,
174 struct ctf_field_path *field_path)
175 {
176 bt_field_class *ir_fc = NULL;
177 struct ctf_field_class *fc = ctf_field_path_borrow_field_class(
178 field_path, ctx->tc, ctx->sc, ctx->ec);
179
180 BT_ASSERT(fc);
181
182 if (fc->in_ir) {
183 ir_fc = fc->ir_fc;
184 }
185
186 return ir_fc;
187 }
188
189 static inline
190 bt_field_class *ctf_field_class_variant_to_ir(struct ctx *ctx,
191 struct ctf_field_class_variant *fc)
192 {
193 int ret;
194 bt_field_class *ir_fc = bt_field_class_variant_create(ctx->ir_tc);
195 uint64_t i;
196
197 BT_ASSERT(ir_fc);
198
199 if (fc->tag_path.root != CTF_SCOPE_PACKET_HEADER &&
200 fc->tag_path.root != CTF_SCOPE_EVENT_HEADER) {
201 ret = bt_field_class_variant_set_selector_field_class(
202 ir_fc, borrow_ir_fc_from_field_path(ctx,
203 &fc->tag_path));
204 BT_ASSERT(ret == 0);
205 }
206
207 for (i = 0; i < fc->options->len; i++) {
208 struct ctf_named_field_class *named_fc =
209 ctf_field_class_variant_borrow_option_by_index(fc, i);
210 bt_field_class *option_ir_fc;
211
212 BT_ASSERT(named_fc->fc->in_ir);
213 option_ir_fc = ctf_field_class_to_ir(ctx, named_fc->fc);
214 BT_ASSERT(option_ir_fc);
215 ret = bt_field_class_variant_append_option(
216 ir_fc, named_fc->name->str, option_ir_fc);
217 BT_ASSERT(ret == 0);
218 bt_field_class_put_ref(option_ir_fc);
219 }
220
221 return ir_fc;
222 }
223
224 static inline
225 bt_field_class *ctf_field_class_array_to_ir(struct ctx *ctx,
226 struct ctf_field_class_array *fc)
227 {
228 bt_field_class *ir_fc;
229 bt_field_class *elem_ir_fc;
230
231 if (fc->base.is_text) {
232 ir_fc = bt_field_class_string_create(ctx->ir_tc);
233 BT_ASSERT(ir_fc);
234 goto end;
235 }
236
237 elem_ir_fc = ctf_field_class_to_ir(ctx, fc->base.elem_fc);
238 BT_ASSERT(elem_ir_fc);
239 ir_fc = bt_field_class_static_array_create(ctx->ir_tc, elem_ir_fc,
240 fc->length);
241 BT_ASSERT(ir_fc);
242 bt_field_class_put_ref(elem_ir_fc);
243
244 end:
245 return ir_fc;
246 }
247
248 static inline
249 bt_field_class *ctf_field_class_sequence_to_ir(struct ctx *ctx,
250 struct ctf_field_class_sequence *fc)
251 {
252 int ret;
253 bt_field_class *ir_fc;
254 bt_field_class *elem_ir_fc;
255
256 if (fc->base.is_text) {
257 ir_fc = bt_field_class_string_create(ctx->ir_tc);
258 BT_ASSERT(ir_fc);
259 goto end;
260 }
261
262 elem_ir_fc = ctf_field_class_to_ir(ctx, fc->base.elem_fc);
263 BT_ASSERT(elem_ir_fc);
264 ir_fc = bt_field_class_dynamic_array_create(ctx->ir_tc, elem_ir_fc);
265 BT_ASSERT(ir_fc);
266 bt_field_class_put_ref(elem_ir_fc);
267 BT_ASSERT(ir_fc);
268
269 if (fc->length_path.root != CTF_SCOPE_PACKET_HEADER &&
270 fc->length_path.root != CTF_SCOPE_EVENT_HEADER) {
271 ret = bt_field_class_dynamic_array_set_length_field_class(
272 ir_fc, borrow_ir_fc_from_field_path(ctx, &fc->length_path));
273 BT_ASSERT(ret == 0);
274 }
275
276 end:
277 return ir_fc;
278 }
279
280 static inline
281 bt_field_class *ctf_field_class_to_ir(struct ctx *ctx,
282 struct ctf_field_class *fc)
283 {
284 bt_field_class *ir_fc = NULL;
285
286 BT_ASSERT(fc);
287 BT_ASSERT(fc->in_ir);
288
289 switch (fc->type) {
290 case CTF_FIELD_CLASS_TYPE_INT:
291 ir_fc = ctf_field_class_int_to_ir(ctx, (void *) fc);
292 break;
293 case CTF_FIELD_CLASS_TYPE_ENUM:
294 ir_fc = ctf_field_class_enum_to_ir(ctx, (void *) fc);
295 break;
296 case CTF_FIELD_CLASS_TYPE_FLOAT:
297 ir_fc = ctf_field_class_float_to_ir(ctx, (void *) fc);
298 break;
299 case CTF_FIELD_CLASS_TYPE_STRING:
300 ir_fc = ctf_field_class_string_to_ir(ctx, (void *) fc);
301 break;
302 case CTF_FIELD_CLASS_TYPE_STRUCT:
303 ir_fc = ctf_field_class_struct_to_ir(ctx, (void *) fc);
304 break;
305 case CTF_FIELD_CLASS_TYPE_ARRAY:
306 ir_fc = ctf_field_class_array_to_ir(ctx, (void *) fc);
307 break;
308 case CTF_FIELD_CLASS_TYPE_SEQUENCE:
309 ir_fc = ctf_field_class_sequence_to_ir(ctx, (void *) fc);
310 break;
311 case CTF_FIELD_CLASS_TYPE_VARIANT:
312 ir_fc = ctf_field_class_variant_to_ir(ctx, (void *) fc);
313 break;
314 default:
315 abort();
316 }
317
318 fc->ir_fc = ir_fc;
319 return ir_fc;
320 }
321
322 static inline
323 bool ctf_field_class_struct_has_immediate_member_in_ir(
324 struct ctf_field_class_struct *fc)
325 {
326 uint64_t i;
327 bool has_immediate_member_in_ir = false;
328
329 for (i = 0; i < fc->members->len; i++) {
330 struct ctf_named_field_class *named_fc =
331 ctf_field_class_struct_borrow_member_by_index(fc, i);
332
333 if (named_fc->fc->in_ir) {
334 has_immediate_member_in_ir = true;
335 goto end;
336 }
337 }
338
339 end:
340 return has_immediate_member_in_ir;
341 }
342
343 static inline
344 bt_field_class *scope_ctf_field_class_to_ir(struct ctx *ctx)
345 {
346 bt_field_class *ir_fc = NULL;
347 struct ctf_field_class *fc = NULL;
348
349 switch (ctx->scope) {
350 case CTF_SCOPE_PACKET_CONTEXT:
351 fc = ctx->sc->packet_context_fc;
352 break;
353 case CTF_SCOPE_EVENT_COMMON_CONTEXT:
354 fc = ctx->sc->event_common_context_fc;
355 break;
356 case CTF_SCOPE_EVENT_SPECIFIC_CONTEXT:
357 fc = ctx->ec->spec_context_fc;
358 break;
359 case CTF_SCOPE_EVENT_PAYLOAD:
360 fc = ctx->ec->payload_fc;
361 break;
362 default:
363 abort();
364 }
365
366 if (fc && ctf_field_class_struct_has_immediate_member_in_ir(
367 (void *) fc)) {
368 ir_fc = ctf_field_class_to_ir(ctx, fc);
369 }
370
371 return ir_fc;
372 }
373
374 static inline
375 void ctf_event_class_to_ir(struct ctx *ctx)
376 {
377 int ret;
378 bt_event_class *ir_ec = NULL;
379 bt_field_class *ir_fc;
380
381 BT_ASSERT(ctx->ec);
382
383 if (ctx->ec->is_translated) {
384 ir_ec = bt_stream_class_borrow_event_class_by_id(
385 ctx->ir_sc, ctx->ec->id);
386 BT_ASSERT(ir_ec);
387 goto end;
388 }
389
390 ir_ec = bt_event_class_create_with_id(ctx->ir_sc, ctx->ec->id);
391 BT_ASSERT(ir_ec);
392 bt_event_class_put_ref(ir_ec);
393 ctx->scope = CTF_SCOPE_EVENT_SPECIFIC_CONTEXT;
394 ir_fc = scope_ctf_field_class_to_ir(ctx);
395 if (ir_fc) {
396 ret = bt_event_class_set_specific_context_field_class(
397 ir_ec, ir_fc);
398 BT_ASSERT(ret == 0);
399 bt_field_class_put_ref(ir_fc);
400 }
401
402 ctx->scope = CTF_SCOPE_EVENT_PAYLOAD;
403 ir_fc = scope_ctf_field_class_to_ir(ctx);
404 if (ir_fc) {
405 ret = bt_event_class_set_payload_field_class(ir_ec,
406 ir_fc);
407 BT_ASSERT(ret == 0);
408 bt_field_class_put_ref(ir_fc);
409 }
410
411 if (ctx->ec->name->len > 0) {
412 ret = bt_event_class_set_name(ir_ec, ctx->ec->name->str);
413 BT_ASSERT(ret == 0);
414 }
415
416 if (ctx->ec->emf_uri->len > 0) {
417 ret = bt_event_class_set_emf_uri(ir_ec, ctx->ec->emf_uri->str);
418 BT_ASSERT(ret == 0);
419 }
420
421 if (ctx->ec->log_level != -1) {
422 bt_event_class_set_log_level(ir_ec, ctx->ec->log_level);
423 }
424
425 ctx->ec->is_translated = true;
426 ctx->ec->ir_ec = ir_ec;
427
428 end:
429 return;
430 }
431
432
433 static inline
434 void ctf_stream_class_to_ir(struct ctx *ctx)
435 {
436 int ret;
437 bt_field_class *ir_fc;
438
439 BT_ASSERT(ctx->sc);
440
441 if (ctx->sc->is_translated) {
442 ctx->ir_sc = bt_trace_class_borrow_stream_class_by_id(
443 ctx->ir_tc, ctx->sc->id);
444 BT_ASSERT(ctx->ir_sc);
445 goto end;
446 }
447
448 ctx->ir_sc = bt_stream_class_create_with_id(ctx->ir_tc, ctx->sc->id);
449 BT_ASSERT(ctx->ir_sc);
450 bt_stream_class_put_ref(ctx->ir_sc);
451 ctx->scope = CTF_SCOPE_PACKET_CONTEXT;
452 ir_fc = scope_ctf_field_class_to_ir(ctx);
453 if (ir_fc) {
454 ret = bt_stream_class_set_packet_context_field_class(
455 ctx->ir_sc, ir_fc);
456 BT_ASSERT(ret == 0);
457 bt_field_class_put_ref(ir_fc);
458 }
459
460 ctx->scope = CTF_SCOPE_EVENT_COMMON_CONTEXT;
461 ir_fc = scope_ctf_field_class_to_ir(ctx);
462 if (ir_fc) {
463 ret = bt_stream_class_set_event_common_context_field_class(
464 ctx->ir_sc, ir_fc);
465 BT_ASSERT(ret == 0);
466 bt_field_class_put_ref(ir_fc);
467 }
468
469 bt_stream_class_set_assigns_automatic_event_class_id(ctx->ir_sc,
470 BT_FALSE);
471 bt_stream_class_set_assigns_automatic_stream_id(ctx->ir_sc, BT_FALSE);
472
473 if (ctx->sc->default_clock_class) {
474 BT_ASSERT(ctx->sc->default_clock_class->ir_cc);
475 ret = bt_stream_class_set_default_clock_class(ctx->ir_sc,
476 ctx->sc->default_clock_class->ir_cc);
477 BT_ASSERT(ret == 0);
478 }
479
480 ctx->sc->is_translated = true;
481 ctx->sc->ir_sc = ctx->ir_sc;
482
483 end:
484 return;
485 }
486
487 static inline
488 void ctf_clock_class_to_ir(bt_clock_class *ir_cc, struct ctf_clock_class *cc)
489 {
490 int ret;
491
492 if (strlen(cc->name->str) > 0) {
493 ret = bt_clock_class_set_name(ir_cc, cc->name->str);
494 BT_ASSERT(ret == 0);
495 }
496
497 if (strlen(cc->description->str) > 0) {
498 ret = bt_clock_class_set_description(ir_cc, cc->description->str);
499 BT_ASSERT(ret == 0);
500 }
501
502 bt_clock_class_set_frequency(ir_cc, cc->frequency);
503 bt_clock_class_set_precision(ir_cc, cc->precision);
504 bt_clock_class_set_offset(ir_cc, cc->offset_seconds, cc->offset_cycles);
505
506 if (cc->has_uuid) {
507 bt_clock_class_set_uuid(ir_cc, cc->uuid);
508 }
509
510 bt_clock_class_set_origin_is_unix_epoch(ir_cc, cc->is_absolute);
511 }
512
513 static inline
514 int ctf_trace_class_to_ir(struct ctx *ctx)
515 {
516 int ret = 0;
517 uint64_t i;
518
519 BT_ASSERT(ctx->tc);
520 BT_ASSERT(ctx->ir_tc);
521
522 if (ctx->tc->is_translated) {
523 goto end;
524 }
525
526 if (ctx->tc->is_uuid_set) {
527 bt_trace_class_set_uuid(ctx->ir_tc, ctx->tc->uuid);
528 }
529
530 for (i = 0; i < ctx->tc->env_entries->len; i++) {
531 struct ctf_trace_class_env_entry *env_entry =
532 ctf_trace_class_borrow_env_entry_by_index(ctx->tc, i);
533
534 switch (env_entry->type) {
535 case CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT:
536 ret = bt_trace_class_set_environment_entry_integer(
537 ctx->ir_tc, env_entry->name->str,
538 env_entry->value.i);
539 break;
540 case CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR:
541 ret = bt_trace_class_set_environment_entry_string(
542 ctx->ir_tc, env_entry->name->str,
543 env_entry->value.str->str);
544 break;
545 default:
546 abort();
547 }
548
549 if (ret) {
550 goto end;
551 }
552 }
553
554 for (i = 0; i < ctx->tc->clock_classes->len; i++) {
555 struct ctf_clock_class *cc = ctx->tc->clock_classes->pdata[i];
556
557 cc->ir_cc = bt_clock_class_create(
558 bt_self_component_source_as_self_component(
559 ctx->self_comp));
560 ctf_clock_class_to_ir(cc->ir_cc, cc);
561 }
562
563 bt_trace_class_set_assigns_automatic_stream_class_id(ctx->ir_tc,
564 BT_FALSE);
565 ctx->tc->is_translated = true;
566 ctx->tc->ir_tc = ctx->ir_tc;
567
568 end:
569 return ret;
570 }
571
572 BT_HIDDEN
573 int ctf_trace_class_translate(bt_self_component_source *self_comp,
574 bt_trace_class *ir_tc, struct ctf_trace_class *tc)
575 {
576 int ret = 0;
577 uint64_t i;
578 struct ctx ctx = { 0 };
579
580 ctx.self_comp = self_comp;
581 ctx.tc = tc;
582 ctx.ir_tc = ir_tc;
583 ret = ctf_trace_class_to_ir(&ctx);
584 if (ret) {
585 goto end;
586 }
587
588 for (i = 0; i < tc->stream_classes->len; i++) {
589 uint64_t j;
590 ctx.sc = tc->stream_classes->pdata[i];
591
592 ctf_stream_class_to_ir(&ctx);
593
594 for (j = 0; j < ctx.sc->event_classes->len; j++) {
595 ctx.ec = ctx.sc->event_classes->pdata[j];
596
597 ctf_event_class_to_ir(&ctx);
598 ctx.ec = NULL;
599 }
600
601 ctx.sc = NULL;
602 }
603
604 end:
605 return ret;
606 }
This page took 0.041243 seconds and 4 git commands to generate.