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_COMP_LOG_SELF_COMP self_comp
28 #define BT_LOG_OUTPUT_LEVEL log_level
29 #define BT_LOG_TAG "PLUGIN/FLT.LTTNG-UTILS.DEBUG-INFO/TRACE-IR-META-COPY"
30 #include "plugins/comp-logging.h"
35 #include "common/assert.h"
37 #include "trace-ir-metadata-copy.h"
38 #include "trace-ir-metadata-field-class-copy.h"
42 int copy_trace_class_content(const bt_trace_class
*in_trace_class
,
43 bt_trace_class
*out_trace_class
, bt_logging_level log_level
,
44 bt_self_component
*self_comp
)
47 uint64_t i
, env_field_count
;
48 const char *in_trace_class_name
;
50 BT_COMP_LOGD("Copying content of trace class: in-tc-addr=%p, out-tc-addr=%p",
51 in_trace_class
, out_trace_class
);
53 /* Use the same stream class ids as in the origin trace class. */
54 bt_trace_class_set_assigns_automatic_stream_class_id(out_trace_class
,
57 in_trace_class_name
= bt_trace_class_get_name(in_trace_class
);
58 if (in_trace_class_name
) {
59 bt_trace_class_set_name(out_trace_class
, in_trace_class_name
);
63 * Do not copy the trace class UUID as it may be modified and should no
64 * longer have the same UUID.
68 * Go over all the entries in the environment section of the trace class
69 * and copy the content to the new trace class.
71 env_field_count
= bt_trace_class_get_environment_entry_count(in_trace_class
);
72 for (i
= 0; i
< env_field_count
; i
++) {
73 const char *value_name
;
74 const bt_value
*value
= NULL
;
75 bt_trace_class_status trace_class_status
;
77 bt_trace_class_borrow_environment_entry_by_index_const(
78 in_trace_class
, i
, &value_name
, &value
);
80 BT_COMP_LOGD("Copying trace class environnement entry: "
81 "index=%" PRId64
", value-addr=%p, value-name=%s",
82 i
, value
, value_name
);
84 BT_ASSERT(value_name
);
87 if (bt_value_is_signed_integer(value
)) {
89 bt_trace_class_set_environment_entry_integer(
90 out_trace_class
, value_name
,
91 bt_value_signed_integer_get(
93 } else if (bt_value_is_string(value
)) {
95 bt_trace_class_set_environment_entry_string(
96 out_trace_class
, value_name
,
97 bt_value_string_get(value
));
102 if (trace_class_status
!= BT_TRACE_CLASS_STATUS_OK
) {
108 BT_COMP_LOGD("Copied content of trace class: in-tc-addr=%p, out-tc-addr=%p",
109 in_trace_class
, out_trace_class
);
115 int copy_clock_class_content(const bt_clock_class
*in_clock_class
,
116 bt_clock_class
*out_clock_class
, bt_logging_level log_level
,
117 bt_self_component
*self_comp
)
119 bt_clock_class_status status
;
120 const char *clock_class_name
, *clock_class_description
;
126 BT_COMP_LOGD("Copying content of clock class: in-cc-addr=%p, out-cc-addr=%p",
127 in_clock_class
, out_clock_class
);
129 clock_class_name
= bt_clock_class_get_name(in_clock_class
);
131 if (clock_class_name
) {
132 status
= bt_clock_class_set_name(out_clock_class
, clock_class_name
);
133 if (status
!= BT_CLOCK_CLASS_STATUS_OK
) {
134 BT_COMP_LOGE("Error setting clock class' name cc-addr=%p, name=%p",
135 out_clock_class
, clock_class_name
);
136 out_clock_class
= NULL
;
142 clock_class_description
= bt_clock_class_get_description(in_clock_class
);
144 if (clock_class_description
) {
145 status
= bt_clock_class_set_description(out_clock_class
,
146 clock_class_description
);
147 if (status
!= BT_CLOCK_CLASS_STATUS_OK
) {
148 BT_COMP_LOGE("Error setting clock class' description cc-addr=%p, "
149 "name=%p", out_clock_class
, clock_class_description
);
150 out_clock_class
= NULL
;
156 in_uuid
= bt_clock_class_get_uuid(in_clock_class
);
158 bt_clock_class_set_uuid(out_clock_class
, in_uuid
);
161 bt_clock_class_set_frequency(out_clock_class
,
162 bt_clock_class_get_frequency(in_clock_class
));
163 bt_clock_class_set_precision(out_clock_class
,
164 bt_clock_class_get_precision(in_clock_class
));
165 bt_clock_class_get_offset(in_clock_class
, &seconds
, &cycles
);
166 bt_clock_class_set_offset(out_clock_class
, seconds
, cycles
);
167 bt_clock_class_set_origin_is_unix_epoch(out_clock_class
,
168 bt_clock_class_origin_is_unix_epoch(in_clock_class
));
170 BT_COMP_LOGD("Copied content of clock class: in-cc-addr=%p, out-cc-addr=%p",
171 in_clock_class
, out_clock_class
);
178 bt_clock_class
*borrow_mapped_clock_class(
179 struct trace_ir_metadata_maps
*md_maps
,
180 const bt_clock_class
*in_clock_class
)
183 BT_ASSERT(in_clock_class
);
185 return g_hash_table_lookup(md_maps
->clock_class_map
,
186 (gpointer
) in_clock_class
);
190 bt_clock_class
*create_new_mapped_clock_class(
191 bt_self_component
*self_comp
,
192 struct trace_ir_metadata_maps
*md_maps
,
193 const bt_clock_class
*in_clock_class
)
195 bt_clock_class
*out_clock_class
;
197 bt_logging_level log_level
= md_maps
->log_level
;
199 BT_COMP_LOGD("Creating new mapped clock class: in-cc-addr=%p",
203 BT_ASSERT(in_clock_class
);
205 BT_ASSERT(!borrow_mapped_clock_class(md_maps
, in_clock_class
));
207 out_clock_class
= bt_clock_class_create(self_comp
);
208 if (!out_clock_class
) {
209 BT_COMP_LOGE_STR("Cannot create clock class");
212 /* If not, create a new one and add it to the mapping. */
213 ret
= copy_clock_class_content(in_clock_class
, out_clock_class
,
214 log_level
, self_comp
);
216 BT_COMP_LOGE_STR("Cannot copy clock class");
220 g_hash_table_insert(md_maps
->clock_class_map
,
221 (gpointer
) in_clock_class
, out_clock_class
);
223 BT_COMP_LOGD("Created new mapped clock class: in-cc-addr=%p, out-cc-addr=%p",
224 in_clock_class
, out_clock_class
);
226 return out_clock_class
;
230 int copy_stream_class_content(struct trace_ir_maps
*ir_maps
,
231 const bt_stream_class
*in_stream_class
,
232 bt_stream_class
*out_stream_class
)
234 struct trace_ir_metadata_maps
*md_maps
;
235 const bt_clock_class
*in_clock_class
;
236 bt_clock_class
*out_clock_class
;
237 const bt_field_class
*in_packet_context_fc
, *in_common_context_fc
;
238 bt_field_class
*out_packet_context_fc
, *out_common_context_fc
;
239 bt_stream_class_status status
;
242 bt_logging_level log_level
= ir_maps
->log_level
;
243 bt_self_component
*self_comp
= ir_maps
->self_comp
;
245 BT_COMP_LOGD("Copying content of stream class: in-sc-addr=%p, out-sc-addr=%p",
246 in_stream_class
, out_stream_class
);
248 md_maps
= borrow_metadata_maps_from_input_stream_class(ir_maps
, in_stream_class
);
249 in_clock_class
= bt_stream_class_borrow_default_clock_class_const(
252 if (in_clock_class
) {
253 /* Copy the clock class. */
255 borrow_mapped_clock_class(md_maps
, in_clock_class
);
256 if (!out_clock_class
) {
257 out_clock_class
= create_new_mapped_clock_class(
258 ir_maps
->self_comp
, md_maps
,
261 bt_stream_class_set_default_clock_class(out_stream_class
,
266 bt_stream_class_set_packets_have_beginning_default_clock_snapshot(
268 bt_stream_class_packets_have_beginning_default_clock_snapshot(
270 bt_stream_class_set_packets_have_end_default_clock_snapshot(
272 bt_stream_class_packets_have_end_default_clock_snapshot(
274 bt_stream_class_set_supports_discarded_events(
276 bt_stream_class_supports_discarded_events(in_stream_class
),
277 bt_stream_class_discarded_events_have_default_clock_snapshots(
279 bt_stream_class_set_supports_discarded_packets(
281 bt_stream_class_supports_discarded_packets(in_stream_class
),
282 bt_stream_class_discarded_packets_have_default_clock_snapshots(
285 in_name
= bt_stream_class_get_name(in_stream_class
);
287 status
= bt_stream_class_set_name(out_stream_class
, in_name
);
288 if (status
!= BT_STREAM_CLASS_STATUS_OK
) {
289 BT_COMP_LOGE("Error set stream class name: out-sc-addr=%p, "
290 "name=%s", out_stream_class
, in_name
);
296 bt_stream_class_set_assigns_automatic_stream_id(out_stream_class
,
298 bt_stream_class_set_assigns_automatic_event_class_id(out_stream_class
,
302 * Add the input packet context field class to the context to
303 * resolution in the further steps.
305 in_packet_context_fc
=
306 bt_stream_class_borrow_packet_context_field_class_const(
308 md_maps
->fc_resolving_ctx
->packet_context
=
309 in_packet_context_fc
;
311 if (in_packet_context_fc
) {
312 /* Copy packet context. */
313 out_packet_context_fc
= create_field_class_copy(
314 md_maps
, in_packet_context_fc
);
316 ret
= copy_field_class_content(md_maps
,
317 in_packet_context_fc
, out_packet_context_fc
);
323 status
= bt_stream_class_set_packet_context_field_class(
324 out_stream_class
, out_packet_context_fc
);
325 if (status
!= BT_STREAM_CLASS_STATUS_OK
) {
326 BT_COMP_LOGE("Error setting stream class' packet context "
327 "field class: sc-addr=%p, packet-fc-addr=%p",
328 out_stream_class
, out_packet_context_fc
);
335 * Add the input common context field class to the context to
336 * resolution in the further steps.
338 in_common_context_fc
=
339 bt_stream_class_borrow_event_common_context_field_class_const(
341 md_maps
->fc_resolving_ctx
->event_common_context
=
342 in_common_context_fc
;
344 if (in_common_context_fc
) {
345 /* Copy common context. */
346 /* TODO: I find it a bit awkward to have this special function
347 * here to add the debug-info field class. I would like to
349 out_common_context_fc
= create_field_class_copy(
350 md_maps
, in_common_context_fc
);
352 ret
= copy_event_common_context_field_class_content(
353 md_maps
, ir_maps
->debug_info_field_class_name
,
354 in_common_context_fc
, out_common_context_fc
);
359 status
= bt_stream_class_set_event_common_context_field_class(
360 out_stream_class
, out_common_context_fc
);
361 if (status
!= BT_STREAM_CLASS_STATUS_OK
) {
362 BT_COMP_LOGE("Error setting stream class' packet context "
363 "field class: sc-addr=%p, packet-fc-addr=%p",
364 out_stream_class
, out_common_context_fc
);
370 /* Set packet snapshot boolean fields. */
371 BT_COMP_LOGD("Copied content of stream class: in-sc-addr=%p, out-sc-addr=%p",
372 in_stream_class
, out_stream_class
);
378 int copy_event_class_content(struct trace_ir_maps
*ir_maps
,
379 const bt_event_class
*in_event_class
,
380 bt_event_class
*out_event_class
)
382 struct trace_ir_metadata_maps
*md_maps
;
383 const char *in_event_class_name
, *in_emf_uri
;
384 bt_property_availability prop_avail
;
385 bt_event_class_log_level ec_log_level
;
386 bt_event_class_status status
;
387 bt_field_class
*out_specific_context_fc
, *out_payload_fc
;
388 const bt_field_class
*in_event_specific_context
, *in_event_payload
;
390 bt_logging_level log_level
= ir_maps
->log_level
;
391 bt_self_component
*self_comp
= ir_maps
->self_comp
;
393 BT_COMP_LOGD("Copying content of event class: in-ec-addr=%p, out-ec-addr=%p",
394 in_event_class
, out_event_class
);
396 /* Copy event class name. */
397 in_event_class_name
= bt_event_class_get_name(in_event_class
);
398 if (in_event_class_name
) {
399 status
= bt_event_class_set_name(out_event_class
, in_event_class_name
);
400 if (status
!= BT_EVENT_CLASS_STATUS_OK
) {
401 BT_COMP_LOGE("Error setting event class' name: ec-addr=%p, "
402 "name=%s", out_event_class
, in_event_class_name
);
408 /* Copy event class loglevel. */
409 prop_avail
= bt_event_class_get_log_level(in_event_class
,
411 if (prop_avail
== BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
412 bt_event_class_set_log_level(out_event_class
,
416 /* Copy event class emf uri. */
417 in_emf_uri
= bt_event_class_get_emf_uri(in_event_class
);
419 status
= bt_event_class_set_emf_uri(out_event_class
, in_emf_uri
);
420 if (status
!= BT_EVENT_CLASS_STATUS_OK
) {
421 BT_COMP_LOGE("Error setting event class' emf uri: ec-addr=%p, "
422 "emf uri=%s", out_event_class
, in_emf_uri
);
428 md_maps
= borrow_metadata_maps_from_input_event_class(ir_maps
, in_event_class
);
430 * Add the input event class' specific ctx to te
433 in_event_specific_context
=
434 bt_event_class_borrow_specific_context_field_class_const(
437 md_maps
->fc_resolving_ctx
->event_specific_context
=
438 in_event_specific_context
;
440 if (in_event_specific_context
) {
441 /* Copy the specific context of this event class. */
442 out_specific_context_fc
= create_field_class_copy(md_maps
,
443 in_event_specific_context
);
445 ret
= copy_field_class_content(md_maps
,
446 in_event_specific_context
, out_specific_context_fc
);
451 * Add the output specific context to the output event
454 status
= bt_event_class_set_specific_context_field_class(
455 out_event_class
, out_specific_context_fc
);
456 if (status
!= BT_EVENT_CLASS_STATUS_OK
) {
457 BT_COMP_LOGE("Error setting event class' specific context "
458 "field class: ec-addr=%p, ctx-fc-addr=%p",
459 out_event_class
, out_specific_context_fc
);
466 * Add the input event class' payload field class to
469 in_event_payload
= bt_event_class_borrow_payload_field_class_const(
472 md_maps
->fc_resolving_ctx
->event_payload
= in_event_payload
;
474 if (in_event_payload
) {
475 /* Copy the payload of this event class. */
476 out_payload_fc
= create_field_class_copy(md_maps
,
478 ret
= copy_field_class_content(md_maps
,
479 in_event_payload
, out_payload_fc
);
484 /* Add the output payload to the output event class. */
485 status
= bt_event_class_set_payload_field_class(
486 out_event_class
, out_payload_fc
);
487 if (status
!= BT_EVENT_CLASS_STATUS_OK
) {
488 BT_COMP_LOGE("Error setting event class' payload "
489 "field class: ec-addr=%p, payload-fc-addr=%p",
490 out_event_class
, out_payload_fc
);
496 BT_COMP_LOGD("Copied content of event class: in-ec-addr=%p, out-ec-addr=%p",
497 in_event_class
, out_event_class
);
503 int copy_event_common_context_field_class_content(
504 struct trace_ir_metadata_maps
*md_maps
,
505 const char *debug_info_fc_name
,
506 const bt_field_class
*in_field_class
,
507 bt_field_class
*out_field_class
)
509 bt_field_class_status status
;
510 bt_field_class
*debug_field_class
= NULL
, *bin_field_class
= NULL
,
511 *func_field_class
= NULL
, *src_field_class
= NULL
;
513 bt_logging_level log_level
= md_maps
->log_level
;
514 bt_self_component
*self_comp
= md_maps
->self_comp
;
516 BT_COMP_LOGD("Copying content of event common context field class: "
517 "in-fc-addr=%p, out-fc-addr=%p", in_field_class
, out_field_class
);
519 /* Copy the content of the input common context. */
520 ret
= copy_field_class_content(md_maps
, in_field_class
, out_field_class
);
526 * If this event common context has the necessary fields to compute the
527 * debug information append the debug-info field class to the event
530 if (is_event_common_ctx_dbg_info_compatible(in_field_class
, debug_info_fc_name
)) {
532 * The struct field and 3 sub-fields are not stored in the
533 * field class map because they don't have input equivalent.
534 * We need to put our reference each of these field classes
535 * once they are added to their respective containing field
538 debug_field_class
= bt_field_class_structure_create(
539 md_maps
->output_trace_class
);
540 if (!debug_field_class
) {
541 BT_COMP_LOGE_STR("Failed to create debug_info structure.");
546 bin_field_class
= bt_field_class_string_create(
547 md_maps
->output_trace_class
);
548 if (!bin_field_class
) {
549 BT_COMP_LOGE_STR("Failed to create string for field=bin.");
554 func_field_class
= bt_field_class_string_create(
555 md_maps
->output_trace_class
);
556 if (!func_field_class
) {
557 BT_COMP_LOGE_STR("Failed to create string for field=func.");
562 src_field_class
= bt_field_class_string_create(
563 md_maps
->output_trace_class
);
564 if (!src_field_class
) {
565 BT_COMP_LOGE_STR("Failed to create string for field=src.");
570 status
= bt_field_class_structure_append_member(
571 debug_field_class
, "bin", bin_field_class
);
572 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
573 BT_COMP_LOGE_STR("Failed to add a field to debug_info "
574 "struct: field=bin.");
578 BT_FIELD_CLASS_PUT_REF_AND_RESET(bin_field_class
);
580 status
= bt_field_class_structure_append_member(
581 debug_field_class
, "func", func_field_class
);
582 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
583 BT_COMP_LOGE_STR("Failed to add a field to debug_info "
584 "struct: field=func.");
588 BT_FIELD_CLASS_PUT_REF_AND_RESET(func_field_class
);
590 status
= bt_field_class_structure_append_member(
591 debug_field_class
, "src", src_field_class
);
592 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
593 BT_COMP_LOGE_STR("Failed to add a field to debug_info "
594 "struct: field=src.");
598 BT_FIELD_CLASS_PUT_REF_AND_RESET(src_field_class
);
600 /*Add the filled debug-info field class to the common context. */
601 status
= bt_field_class_structure_append_member(out_field_class
,
604 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
605 BT_COMP_LOGE_STR("Failed to add debug_info field to "
606 "event common context.");
610 BT_FIELD_CLASS_PUT_REF_AND_RESET(debug_field_class
);
612 BT_COMP_LOGD("Copied content of event common context field class: "
613 "in-fc-addr=%p, out-fc-addr=%p", in_field_class
, out_field_class
);
617 if (debug_field_class
) {
618 bt_field_class_put_ref(debug_field_class
);
620 if (bin_field_class
) {
621 bt_field_class_put_ref(bin_field_class
);
623 if (func_field_class
) {
624 bt_field_class_put_ref(func_field_class
);
626 if (src_field_class
) {
627 bt_field_class_put_ref(src_field_class
);
634 bt_field_class
*create_field_class_copy(struct trace_ir_metadata_maps
*md_maps
,
635 const bt_field_class
*in_field_class
)
637 return create_field_class_copy_internal(md_maps
, in_field_class
);
641 int copy_field_class_content(struct trace_ir_metadata_maps
*md_maps
,
642 const bt_field_class
*in_field_class
,
643 bt_field_class
*out_field_class
)
645 return copy_field_class_content_internal(md_maps
, in_field_class
,