2 * Babeltrace - Trace IR metadata object copy
4 * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2018 Philippe Proulx <pproulx@efficios.com>
6 * Copyright (c) 2019 Francis Deslauriers <francis.deslauriers@efficios.com>
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 #define BT_LOG_OUTPUT_LEVEL log_level
28 #define BT_LOG_TAG "PLUGIN/FLT.LTTNG-UTILS.DEBUG-INFO/TRACE-IR-META-COPY"
29 #include "logging/log.h"
34 #include "common/assert.h"
36 #include "trace-ir-metadata-copy.h"
37 #include "trace-ir-metadata-field-class-copy.h"
41 int copy_trace_class_content(const bt_trace_class
*in_trace_class
,
42 bt_trace_class
*out_trace_class
, bt_logging_level log_level
)
45 uint64_t i
, env_field_count
;
46 const char *in_trace_class_name
;
48 BT_LOGD("Copying content of trace class: in-tc-addr=%p, out-tc-addr=%p",
49 in_trace_class
, out_trace_class
);
51 /* Use the same stream class ids as in the origin trace class. */
52 bt_trace_class_set_assigns_automatic_stream_class_id(out_trace_class
,
55 in_trace_class_name
= bt_trace_class_get_name(in_trace_class
);
56 if (in_trace_class_name
) {
57 bt_trace_class_set_name(out_trace_class
, in_trace_class_name
);
61 * Do not copy the trace class UUID as it may be modified and should no
62 * longer have the same UUID.
66 * Go over all the entries in the environment section of the trace class
67 * and copy the content to the new trace class.
69 env_field_count
= bt_trace_class_get_environment_entry_count(in_trace_class
);
70 for (i
= 0; i
< env_field_count
; i
++) {
71 const char *value_name
;
72 const bt_value
*value
= NULL
;
73 bt_trace_class_status trace_class_status
;
75 bt_trace_class_borrow_environment_entry_by_index_const(
76 in_trace_class
, i
, &value_name
, &value
);
78 BT_LOGD("Copying trace class environnement entry: "
79 "index=%" PRId64
", value-addr=%p, value-name=%s",
80 i
, value
, value_name
);
82 BT_ASSERT(value_name
);
85 if (bt_value_is_signed_integer(value
)) {
87 bt_trace_class_set_environment_entry_integer(
88 out_trace_class
, value_name
,
89 bt_value_signed_integer_get(
91 } else if (bt_value_is_string(value
)) {
93 bt_trace_class_set_environment_entry_string(
94 out_trace_class
, value_name
,
95 bt_value_string_get(value
));
100 if (trace_class_status
!= BT_TRACE_CLASS_STATUS_OK
) {
106 BT_LOGD("Copied content of trace class: in-tc-addr=%p, out-tc-addr=%p",
107 in_trace_class
, out_trace_class
);
113 int copy_clock_class_content(const bt_clock_class
*in_clock_class
,
114 bt_clock_class
*out_clock_class
, bt_logging_level log_level
)
116 bt_clock_class_status status
;
117 const char *clock_class_name
, *clock_class_description
;
123 BT_LOGD("Copying content of clock class: in-cc-addr=%p, out-cc-addr=%p",
124 in_clock_class
, out_clock_class
);
126 clock_class_name
= bt_clock_class_get_name(in_clock_class
);
128 if (clock_class_name
) {
129 status
= bt_clock_class_set_name(out_clock_class
, clock_class_name
);
130 if (status
!= BT_CLOCK_CLASS_STATUS_OK
) {
131 BT_LOGE("Error setting clock class' name cc-addr=%p, name=%p",
132 out_clock_class
, clock_class_name
);
133 out_clock_class
= NULL
;
139 clock_class_description
= bt_clock_class_get_description(in_clock_class
);
141 if (clock_class_description
) {
142 status
= bt_clock_class_set_description(out_clock_class
,
143 clock_class_description
);
144 if (status
!= BT_CLOCK_CLASS_STATUS_OK
) {
145 BT_LOGE("Error setting clock class' description cc-addr=%p, "
146 "name=%p", out_clock_class
, clock_class_description
);
147 out_clock_class
= NULL
;
153 in_uuid
= bt_clock_class_get_uuid(in_clock_class
);
155 bt_clock_class_set_uuid(out_clock_class
, in_uuid
);
158 bt_clock_class_set_frequency(out_clock_class
,
159 bt_clock_class_get_frequency(in_clock_class
));
160 bt_clock_class_set_precision(out_clock_class
,
161 bt_clock_class_get_precision(in_clock_class
));
162 bt_clock_class_get_offset(in_clock_class
, &seconds
, &cycles
);
163 bt_clock_class_set_offset(out_clock_class
, seconds
, cycles
);
164 bt_clock_class_set_origin_is_unix_epoch(out_clock_class
,
165 bt_clock_class_origin_is_unix_epoch(in_clock_class
));
167 BT_LOGD("Copied content of clock class: in-cc-addr=%p, out-cc-addr=%p",
168 in_clock_class
, out_clock_class
);
175 bt_clock_class
*borrow_mapped_clock_class(
176 struct trace_ir_metadata_maps
*md_maps
,
177 const bt_clock_class
*in_clock_class
)
180 BT_ASSERT(in_clock_class
);
182 return g_hash_table_lookup(md_maps
->clock_class_map
,
183 (gpointer
) in_clock_class
);
187 bt_clock_class
*create_new_mapped_clock_class(
188 bt_self_component
*self_comp
,
189 struct trace_ir_metadata_maps
*md_maps
,
190 const bt_clock_class
*in_clock_class
)
192 bt_clock_class
*out_clock_class
;
194 bt_logging_level log_level
= md_maps
->log_level
;
196 BT_LOGD("Creating new mapped clock class: in-cc-addr=%p",
200 BT_ASSERT(in_clock_class
);
202 BT_ASSERT(!borrow_mapped_clock_class(md_maps
, in_clock_class
));
204 out_clock_class
= bt_clock_class_create(self_comp
);
205 if (!out_clock_class
) {
206 BT_LOGE_STR("Cannot create clock class");
209 /* If not, create a new one and add it to the mapping. */
210 ret
= copy_clock_class_content(in_clock_class
, out_clock_class
,
213 BT_LOGE_STR("Cannot copy clock class");
217 g_hash_table_insert(md_maps
->clock_class_map
,
218 (gpointer
) in_clock_class
, out_clock_class
);
220 BT_LOGD("Created new mapped clock class: in-cc-addr=%p, out-cc-addr=%p",
221 in_clock_class
, out_clock_class
);
223 return out_clock_class
;
227 int copy_stream_class_content(struct trace_ir_maps
*ir_maps
,
228 const bt_stream_class
*in_stream_class
,
229 bt_stream_class
*out_stream_class
)
231 struct trace_ir_metadata_maps
*md_maps
;
232 const bt_clock_class
*in_clock_class
;
233 bt_clock_class
*out_clock_class
;
234 const bt_field_class
*in_packet_context_fc
, *in_common_context_fc
;
235 bt_field_class
*out_packet_context_fc
, *out_common_context_fc
;
236 bt_stream_class_status status
;
239 bt_logging_level log_level
= ir_maps
->log_level
;
241 BT_LOGD("Copying content of stream class: in-sc-addr=%p, out-sc-addr=%p",
242 in_stream_class
, out_stream_class
);
244 md_maps
= borrow_metadata_maps_from_input_stream_class(ir_maps
, in_stream_class
);
245 in_clock_class
= bt_stream_class_borrow_default_clock_class_const(
248 if (in_clock_class
) {
249 /* Copy the clock class. */
251 borrow_mapped_clock_class(md_maps
, in_clock_class
);
252 if (!out_clock_class
) {
253 out_clock_class
= create_new_mapped_clock_class(
254 ir_maps
->self_comp
, md_maps
,
257 bt_stream_class_set_default_clock_class(out_stream_class
,
262 bt_stream_class_set_packets_have_beginning_default_clock_snapshot(
264 bt_stream_class_packets_have_beginning_default_clock_snapshot(
266 bt_stream_class_set_packets_have_end_default_clock_snapshot(
268 bt_stream_class_packets_have_end_default_clock_snapshot(
270 bt_stream_class_set_supports_discarded_events(
272 bt_stream_class_supports_discarded_events(in_stream_class
),
273 bt_stream_class_discarded_events_have_default_clock_snapshots(
275 bt_stream_class_set_supports_discarded_packets(
277 bt_stream_class_supports_discarded_packets(in_stream_class
),
278 bt_stream_class_discarded_packets_have_default_clock_snapshots(
281 in_name
= bt_stream_class_get_name(in_stream_class
);
283 status
= bt_stream_class_set_name(out_stream_class
, in_name
);
284 if (status
!= BT_STREAM_CLASS_STATUS_OK
) {
285 BT_LOGE("Error set stream class name: out-sc-addr=%p, "
286 "name=%s", out_stream_class
, in_name
);
292 bt_stream_class_set_assigns_automatic_stream_id(out_stream_class
,
294 bt_stream_class_set_assigns_automatic_event_class_id(out_stream_class
,
298 * Add the input packet context field class to the context to
299 * resolution in the further steps.
301 in_packet_context_fc
=
302 bt_stream_class_borrow_packet_context_field_class_const(
304 md_maps
->fc_resolving_ctx
->packet_context
=
305 in_packet_context_fc
;
307 if (in_packet_context_fc
) {
308 /* Copy packet context. */
309 out_packet_context_fc
= create_field_class_copy(
310 md_maps
, in_packet_context_fc
);
312 ret
= copy_field_class_content(md_maps
,
313 in_packet_context_fc
, out_packet_context_fc
);
319 status
= bt_stream_class_set_packet_context_field_class(
320 out_stream_class
, out_packet_context_fc
);
321 if (status
!= BT_STREAM_CLASS_STATUS_OK
) {
322 BT_LOGE("Error setting stream class' packet context "
323 "field class: sc-addr=%p, packet-fc-addr=%p",
324 out_stream_class
, out_packet_context_fc
);
331 * Add the input common context field class to the context to
332 * resolution in the further steps.
334 in_common_context_fc
=
335 bt_stream_class_borrow_event_common_context_field_class_const(
337 md_maps
->fc_resolving_ctx
->event_common_context
=
338 in_common_context_fc
;
340 if (in_common_context_fc
) {
341 /* Copy common context. */
342 /* TODO: I find it a bit awkward to have this special function
343 * here to add the debug-info field class. I would like to
345 out_common_context_fc
= create_field_class_copy(
346 md_maps
, in_common_context_fc
);
348 ret
= copy_event_common_context_field_class_content(
349 md_maps
, ir_maps
->debug_info_field_class_name
,
350 in_common_context_fc
, out_common_context_fc
);
355 status
= bt_stream_class_set_event_common_context_field_class(
356 out_stream_class
, out_common_context_fc
);
357 if (status
!= BT_STREAM_CLASS_STATUS_OK
) {
358 BT_LOGE("Error setting stream class' packet context "
359 "field class: sc-addr=%p, packet-fc-addr=%p",
360 out_stream_class
, out_common_context_fc
);
366 /* Set packet snapshot boolean fields. */
367 BT_LOGD("Copied content of stream class: in-sc-addr=%p, out-sc-addr=%p",
368 in_stream_class
, out_stream_class
);
374 int copy_event_class_content(struct trace_ir_maps
*ir_maps
,
375 const bt_event_class
*in_event_class
,
376 bt_event_class
*out_event_class
)
378 struct trace_ir_metadata_maps
*md_maps
;
379 const char *in_event_class_name
, *in_emf_uri
;
380 bt_property_availability prop_avail
;
381 bt_event_class_log_level ec_log_level
;
382 bt_event_class_status status
;
383 bt_field_class
*out_specific_context_fc
, *out_payload_fc
;
384 const bt_field_class
*in_event_specific_context
, *in_event_payload
;
386 bt_logging_level log_level
= ir_maps
->log_level
;
388 BT_LOGD("Copying content of event class: in-ec-addr=%p, out-ec-addr=%p",
389 in_event_class
, out_event_class
);
391 /* Copy event class name. */
392 in_event_class_name
= bt_event_class_get_name(in_event_class
);
393 if (in_event_class_name
) {
394 status
= bt_event_class_set_name(out_event_class
, in_event_class_name
);
395 if (status
!= BT_EVENT_CLASS_STATUS_OK
) {
396 BT_LOGE("Error setting event class' name: ec-addr=%p, "
397 "name=%s", out_event_class
, in_event_class_name
);
403 /* Copy event class loglevel. */
404 prop_avail
= bt_event_class_get_log_level(in_event_class
,
406 if (prop_avail
== BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
407 bt_event_class_set_log_level(out_event_class
,
411 /* Copy event class emf uri. */
412 in_emf_uri
= bt_event_class_get_emf_uri(in_event_class
);
414 status
= bt_event_class_set_emf_uri(out_event_class
, in_emf_uri
);
415 if (status
!= BT_EVENT_CLASS_STATUS_OK
) {
416 BT_LOGE("Error setting event class' emf uri: ec-addr=%p, "
417 "emf uri=%s", out_event_class
, in_emf_uri
);
423 md_maps
= borrow_metadata_maps_from_input_event_class(ir_maps
, in_event_class
);
425 * Add the input event class' specific ctx to te
428 in_event_specific_context
=
429 bt_event_class_borrow_specific_context_field_class_const(
432 md_maps
->fc_resolving_ctx
->event_specific_context
=
433 in_event_specific_context
;
435 if (in_event_specific_context
) {
436 /* Copy the specific context of this event class. */
437 out_specific_context_fc
= create_field_class_copy(md_maps
,
438 in_event_specific_context
);
440 ret
= copy_field_class_content(md_maps
,
441 in_event_specific_context
, out_specific_context_fc
);
446 * Add the output specific context to the output event
449 status
= bt_event_class_set_specific_context_field_class(
450 out_event_class
, out_specific_context_fc
);
451 if (status
!= BT_EVENT_CLASS_STATUS_OK
) {
452 BT_LOGE("Error setting event class' specific context "
453 "field class: ec-addr=%p, ctx-fc-addr=%p",
454 out_event_class
, out_specific_context_fc
);
461 * Add the input event class' payload field class to
464 in_event_payload
= bt_event_class_borrow_payload_field_class_const(
467 md_maps
->fc_resolving_ctx
->event_payload
= in_event_payload
;
469 if (in_event_payload
) {
470 /* Copy the payload of this event class. */
471 out_payload_fc
= create_field_class_copy(md_maps
,
473 ret
= copy_field_class_content(md_maps
,
474 in_event_payload
, out_payload_fc
);
479 /* Add the output payload to the output event class. */
480 status
= bt_event_class_set_payload_field_class(
481 out_event_class
, out_payload_fc
);
482 if (status
!= BT_EVENT_CLASS_STATUS_OK
) {
483 BT_LOGE("Error setting event class' payload "
484 "field class: ec-addr=%p, payload-fc-addr=%p",
485 out_event_class
, out_payload_fc
);
491 BT_LOGD("Copied content of event class: in-ec-addr=%p, out-ec-addr=%p",
492 in_event_class
, out_event_class
);
498 int copy_event_common_context_field_class_content(
499 struct trace_ir_metadata_maps
*md_maps
,
500 const char *debug_info_fc_name
,
501 const bt_field_class
*in_field_class
,
502 bt_field_class
*out_field_class
)
504 bt_field_class_status status
;
505 bt_field_class
*debug_field_class
= NULL
, *bin_field_class
= NULL
,
506 *func_field_class
= NULL
, *src_field_class
= NULL
;
508 bt_logging_level log_level
= md_maps
->log_level
;
510 BT_LOGD("Copying content of event common context field class: "
511 "in-fc-addr=%p, out-fc-addr=%p", in_field_class
, out_field_class
);
513 /* Copy the content of the input common context. */
514 ret
= copy_field_class_content(md_maps
, in_field_class
, out_field_class
);
520 * If this event common context has the necessary fields to compute the
521 * debug information append the debug-info field class to the event
524 if (is_event_common_ctx_dbg_info_compatible(in_field_class
, debug_info_fc_name
)) {
526 * The struct field and 3 sub-fields are not stored in the
527 * field class map because they don't have input equivalent.
528 * We need to put our reference each of these field classes
529 * once they are added to their respective containing field
532 debug_field_class
= bt_field_class_structure_create(
533 md_maps
->output_trace_class
);
534 if (!debug_field_class
) {
535 BT_LOGE_STR("Failed to create debug_info structure.");
540 bin_field_class
= bt_field_class_string_create(
541 md_maps
->output_trace_class
);
542 if (!bin_field_class
) {
543 BT_LOGE_STR("Failed to create string for field=bin.");
548 func_field_class
= bt_field_class_string_create(
549 md_maps
->output_trace_class
);
550 if (!func_field_class
) {
551 BT_LOGE_STR("Failed to create string for field=func.");
556 src_field_class
= bt_field_class_string_create(
557 md_maps
->output_trace_class
);
558 if (!src_field_class
) {
559 BT_LOGE_STR("Failed to create string for field=src.");
564 status
= bt_field_class_structure_append_member(
565 debug_field_class
, "bin", bin_field_class
);
566 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
567 BT_LOGE_STR("Failed to add a field to debug_info "
568 "struct: field=bin.");
572 BT_FIELD_CLASS_PUT_REF_AND_RESET(bin_field_class
);
574 status
= bt_field_class_structure_append_member(
575 debug_field_class
, "func", func_field_class
);
576 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
577 BT_LOGE_STR("Failed to add a field to debug_info "
578 "struct: field=func.");
582 BT_FIELD_CLASS_PUT_REF_AND_RESET(func_field_class
);
584 status
= bt_field_class_structure_append_member(
585 debug_field_class
, "src", src_field_class
);
586 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
587 BT_LOGE_STR("Failed to add a field to debug_info "
588 "struct: field=src.");
592 BT_FIELD_CLASS_PUT_REF_AND_RESET(src_field_class
);
594 /*Add the filled debug-info field class to the common context. */
595 status
= bt_field_class_structure_append_member(out_field_class
,
598 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
599 BT_LOGE_STR("Failed to add debug_info field to "
600 "event common context.");
604 BT_FIELD_CLASS_PUT_REF_AND_RESET(debug_field_class
);
606 BT_LOGD("Copied content of event common context field class: "
607 "in-fc-addr=%p, out-fc-addr=%p", in_field_class
, out_field_class
);
611 if (debug_field_class
) {
612 bt_field_class_put_ref(debug_field_class
);
614 if (bin_field_class
) {
615 bt_field_class_put_ref(bin_field_class
);
617 if (func_field_class
) {
618 bt_field_class_put_ref(func_field_class
);
620 if (src_field_class
) {
621 bt_field_class_put_ref(src_field_class
);
628 bt_field_class
*create_field_class_copy(struct trace_ir_metadata_maps
*md_maps
,
629 const bt_field_class
*in_field_class
)
631 return create_field_class_copy_internal(md_maps
, in_field_class
);
635 int copy_field_class_content(struct trace_ir_metadata_maps
*md_maps
,
636 const bt_field_class
*in_field_class
,
637 bt_field_class
*out_field_class
)
639 return copy_field_class_content_internal(md_maps
, in_field_class
,