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 "logging/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
)
46 BT_COMP_LOGD("Copying content of trace class: in-tc-addr=%p, out-tc-addr=%p",
47 in_trace_class
, out_trace_class
);
50 * Safe to use the same value object because it's frozen at this
53 bt_trace_class_set_user_attributes(out_trace_class
,
54 bt_trace_class_borrow_user_attributes_const(in_trace_class
));
56 /* Use the same stream class ids as in the origin trace class. */
57 bt_trace_class_set_assigns_automatic_stream_class_id(out_trace_class
,
59 BT_COMP_LOGD("Copied content of trace class: in-tc-addr=%p, out-tc-addr=%p",
60 in_trace_class
, out_trace_class
);
65 int copy_clock_class_content(const bt_clock_class
*in_clock_class
,
66 bt_clock_class
*out_clock_class
, bt_logging_level log_level
,
67 bt_self_component
*self_comp
)
69 const char *clock_class_name
, *clock_class_description
;
75 BT_COMP_LOGD("Copying content of clock class: in-cc-addr=%p, out-cc-addr=%p",
76 in_clock_class
, out_clock_class
);
78 clock_class_name
= bt_clock_class_get_name(in_clock_class
);
80 if (clock_class_name
) {
81 if (bt_clock_class_set_name(out_clock_class
, clock_class_name
)
82 != BT_CLOCK_CLASS_SET_NAME_STATUS_OK
) {
83 BT_COMP_LOGE("Error setting clock class' name cc-addr=%p, name=%p",
84 out_clock_class
, clock_class_name
);
85 out_clock_class
= NULL
;
92 * Safe to use the same value object because it's frozen at this
95 bt_clock_class_set_user_attributes(out_clock_class
,
96 bt_clock_class_borrow_user_attributes_const(in_clock_class
));
98 clock_class_description
= bt_clock_class_get_description(in_clock_class
);
100 if (clock_class_description
) {
101 if (bt_clock_class_set_description(out_clock_class
,
102 clock_class_description
) !=
103 BT_CLOCK_CLASS_SET_DESCRIPTION_STATUS_OK
) {
104 BT_COMP_LOGE("Error setting clock class' description cc-addr=%p, "
105 "name=%p", out_clock_class
, clock_class_description
);
106 out_clock_class
= NULL
;
112 in_uuid
= bt_clock_class_get_uuid(in_clock_class
);
114 bt_clock_class_set_uuid(out_clock_class
, in_uuid
);
117 bt_clock_class_set_frequency(out_clock_class
,
118 bt_clock_class_get_frequency(in_clock_class
));
119 bt_clock_class_set_precision(out_clock_class
,
120 bt_clock_class_get_precision(in_clock_class
));
121 bt_clock_class_get_offset(in_clock_class
, &seconds
, &cycles
);
122 bt_clock_class_set_offset(out_clock_class
, seconds
, cycles
);
123 bt_clock_class_set_origin_is_unix_epoch(out_clock_class
,
124 bt_clock_class_origin_is_unix_epoch(in_clock_class
));
126 BT_COMP_LOGD("Copied content of clock class: in-cc-addr=%p, out-cc-addr=%p",
127 in_clock_class
, out_clock_class
);
134 bt_clock_class
*borrow_mapped_clock_class(
135 struct trace_ir_metadata_maps
*md_maps
,
136 const bt_clock_class
*in_clock_class
)
139 BT_ASSERT(in_clock_class
);
141 return g_hash_table_lookup(md_maps
->clock_class_map
,
142 (gpointer
) in_clock_class
);
146 bt_clock_class
*create_new_mapped_clock_class(
147 bt_self_component
*self_comp
,
148 struct trace_ir_metadata_maps
*md_maps
,
149 const bt_clock_class
*in_clock_class
)
151 bt_clock_class
*out_clock_class
;
153 bt_logging_level log_level
= md_maps
->log_level
;
155 BT_COMP_LOGD("Creating new mapped clock class: in-cc-addr=%p",
159 BT_ASSERT(in_clock_class
);
161 BT_ASSERT(!borrow_mapped_clock_class(md_maps
, in_clock_class
));
163 out_clock_class
= bt_clock_class_create(self_comp
);
164 if (!out_clock_class
) {
165 BT_COMP_LOGE_STR("Cannot create clock class");
168 /* If not, create a new one and add it to the mapping. */
169 ret
= copy_clock_class_content(in_clock_class
, out_clock_class
,
170 log_level
, self_comp
);
172 BT_COMP_LOGE_STR("Cannot copy clock class");
176 g_hash_table_insert(md_maps
->clock_class_map
,
177 (gpointer
) in_clock_class
, out_clock_class
);
179 BT_COMP_LOGD("Created new mapped clock class: in-cc-addr=%p, out-cc-addr=%p",
180 in_clock_class
, out_clock_class
);
182 return out_clock_class
;
186 int copy_stream_class_content(struct trace_ir_maps
*ir_maps
,
187 const bt_stream_class
*in_stream_class
,
188 bt_stream_class
*out_stream_class
)
190 struct trace_ir_metadata_maps
*md_maps
;
191 const bt_clock_class
*in_clock_class
;
192 bt_clock_class
*out_clock_class
;
193 const bt_field_class
*in_packet_context_fc
, *in_common_context_fc
;
194 bt_field_class
*out_packet_context_fc
, *out_common_context_fc
;
197 bt_logging_level log_level
= ir_maps
->log_level
;
198 bt_self_component
*self_comp
= ir_maps
->self_comp
;
200 BT_COMP_LOGD("Copying content of stream class: in-sc-addr=%p, out-sc-addr=%p",
201 in_stream_class
, out_stream_class
);
203 md_maps
= borrow_metadata_maps_from_input_stream_class(ir_maps
, in_stream_class
);
204 in_clock_class
= bt_stream_class_borrow_default_clock_class_const(
207 if (in_clock_class
) {
208 /* Copy the clock class. */
210 borrow_mapped_clock_class(md_maps
, in_clock_class
);
211 if (!out_clock_class
) {
212 out_clock_class
= create_new_mapped_clock_class(
213 ir_maps
->self_comp
, md_maps
,
216 bt_stream_class_set_default_clock_class(out_stream_class
,
222 * Safe to use the same value object because it's frozen at this
225 bt_stream_class_set_user_attributes(out_stream_class
,
226 bt_stream_class_borrow_user_attributes_const(in_stream_class
));
228 bt_stream_class_set_supports_packets(
230 bt_stream_class_supports_packets(in_stream_class
),
231 bt_stream_class_packets_have_beginning_default_clock_snapshot(
233 bt_stream_class_packets_have_end_default_clock_snapshot(
235 bt_stream_class_set_supports_discarded_events(
237 bt_stream_class_supports_discarded_events(in_stream_class
),
238 bt_stream_class_discarded_events_have_default_clock_snapshots(
240 bt_stream_class_set_supports_discarded_packets(
242 bt_stream_class_supports_discarded_packets(in_stream_class
),
243 bt_stream_class_discarded_packets_have_default_clock_snapshots(
246 in_name
= bt_stream_class_get_name(in_stream_class
);
248 if (bt_stream_class_set_name(out_stream_class
, in_name
) !=
249 BT_STREAM_CLASS_SET_NAME_STATUS_OK
) {
250 BT_COMP_LOGE("Error set stream class name: out-sc-addr=%p, "
251 "name=%s", out_stream_class
, in_name
);
257 bt_stream_class_set_assigns_automatic_stream_id(out_stream_class
,
259 bt_stream_class_set_assigns_automatic_event_class_id(out_stream_class
,
263 * Add the input packet context field class to the context to
264 * resolution in the further steps.
266 in_packet_context_fc
=
267 bt_stream_class_borrow_packet_context_field_class_const(
269 md_maps
->fc_resolving_ctx
->packet_context
=
270 in_packet_context_fc
;
272 if (in_packet_context_fc
) {
273 /* Copy packet context. */
274 out_packet_context_fc
= create_field_class_copy(
275 md_maps
, in_packet_context_fc
);
277 ret
= copy_field_class_content(md_maps
,
278 in_packet_context_fc
, out_packet_context_fc
);
284 if (bt_stream_class_set_packet_context_field_class(
285 out_stream_class
, out_packet_context_fc
) !=
286 BT_STREAM_CLASS_SET_FIELD_CLASS_STATUS_OK
) {
287 BT_COMP_LOGE("Error setting stream class' packet context "
288 "field class: sc-addr=%p, packet-fc-addr=%p",
289 out_stream_class
, out_packet_context_fc
);
296 * Add the input common context field class to the context to
297 * resolution in the further steps.
299 in_common_context_fc
=
300 bt_stream_class_borrow_event_common_context_field_class_const(
302 md_maps
->fc_resolving_ctx
->event_common_context
=
303 in_common_context_fc
;
305 if (in_common_context_fc
) {
306 /* Copy common context. */
307 /* TODO: I find it a bit awkward to have this special function
308 * here to add the debug-info field class. I would like to
310 out_common_context_fc
= create_field_class_copy(
311 md_maps
, in_common_context_fc
);
313 ret
= copy_event_common_context_field_class_content(
314 md_maps
, ir_maps
->debug_info_field_class_name
,
315 in_common_context_fc
, out_common_context_fc
);
320 if (bt_stream_class_set_event_common_context_field_class(
321 out_stream_class
, out_common_context_fc
) !=
322 BT_STREAM_CLASS_SET_FIELD_CLASS_STATUS_OK
) {
323 BT_COMP_LOGE("Error setting stream class' packet context "
324 "field class: sc-addr=%p, packet-fc-addr=%p",
325 out_stream_class
, out_common_context_fc
);
331 BT_COMP_LOGD("Copied content of stream class: in-sc-addr=%p, out-sc-addr=%p",
332 in_stream_class
, out_stream_class
);
338 int copy_event_class_content(struct trace_ir_maps
*ir_maps
,
339 const bt_event_class
*in_event_class
,
340 bt_event_class
*out_event_class
)
342 struct trace_ir_metadata_maps
*md_maps
;
343 const char *in_event_class_name
, *in_emf_uri
;
344 bt_property_availability prop_avail
;
345 bt_event_class_log_level ec_log_level
;
346 bt_field_class
*out_specific_context_fc
, *out_payload_fc
;
347 const bt_field_class
*in_event_specific_context
, *in_event_payload
;
349 bt_logging_level log_level
= ir_maps
->log_level
;
350 bt_self_component
*self_comp
= ir_maps
->self_comp
;
352 BT_COMP_LOGD("Copying content of event class: in-ec-addr=%p, out-ec-addr=%p",
353 in_event_class
, out_event_class
);
355 /* Copy event class name. */
356 in_event_class_name
= bt_event_class_get_name(in_event_class
);
357 if (in_event_class_name
) {
358 if (bt_event_class_set_name(out_event_class
,
359 in_event_class_name
) !=
360 BT_EVENT_CLASS_SET_NAME_STATUS_OK
) {
361 BT_COMP_LOGE("Error setting event class' name: ec-addr=%p, "
362 "name=%s", out_event_class
, in_event_class_name
);
369 * Safe to use the same value object because it's frozen at this
372 bt_event_class_set_user_attributes(out_event_class
,
373 bt_event_class_borrow_user_attributes_const(in_event_class
));
375 /* Copy event class loglevel. */
376 prop_avail
= bt_event_class_get_log_level(in_event_class
,
378 if (prop_avail
== BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
379 bt_event_class_set_log_level(out_event_class
,
383 /* Copy event class emf uri. */
384 in_emf_uri
= bt_event_class_get_emf_uri(in_event_class
);
386 if (bt_event_class_set_emf_uri(out_event_class
, in_emf_uri
) !=
387 BT_EVENT_CLASS_SET_EMF_URI_STATUS_OK
) {
388 BT_COMP_LOGE("Error setting event class' emf uri: ec-addr=%p, "
389 "emf uri=%s", out_event_class
, in_emf_uri
);
395 md_maps
= borrow_metadata_maps_from_input_event_class(ir_maps
, in_event_class
);
397 * Add the input event class' specific ctx to te
400 in_event_specific_context
=
401 bt_event_class_borrow_specific_context_field_class_const(
404 md_maps
->fc_resolving_ctx
->event_specific_context
=
405 in_event_specific_context
;
407 if (in_event_specific_context
) {
408 /* Copy the specific context of this event class. */
409 out_specific_context_fc
= create_field_class_copy(md_maps
,
410 in_event_specific_context
);
412 ret
= copy_field_class_content(md_maps
,
413 in_event_specific_context
, out_specific_context_fc
);
418 * Add the output specific context to the output event
421 if (bt_event_class_set_specific_context_field_class(
422 out_event_class
, out_specific_context_fc
) !=
423 BT_EVENT_CLASS_SET_FIELD_CLASS_STATUS_OK
) {
424 BT_COMP_LOGE("Error setting event class' specific context "
425 "field class: ec-addr=%p, ctx-fc-addr=%p",
426 out_event_class
, out_specific_context_fc
);
433 * Add the input event class' payload field class to
436 in_event_payload
= bt_event_class_borrow_payload_field_class_const(
439 md_maps
->fc_resolving_ctx
->event_payload
= in_event_payload
;
441 if (in_event_payload
) {
442 /* Copy the payload of this event class. */
443 out_payload_fc
= create_field_class_copy(md_maps
,
445 ret
= copy_field_class_content(md_maps
,
446 in_event_payload
, out_payload_fc
);
451 /* Add the output payload to the output event class. */
452 if (bt_event_class_set_payload_field_class(
453 out_event_class
, out_payload_fc
) !=
454 BT_EVENT_CLASS_SET_FIELD_CLASS_STATUS_OK
) {
455 BT_COMP_LOGE("Error setting event class' payload "
456 "field class: ec-addr=%p, payload-fc-addr=%p",
457 out_event_class
, out_payload_fc
);
463 BT_COMP_LOGD("Copied content of event class: in-ec-addr=%p, out-ec-addr=%p",
464 in_event_class
, out_event_class
);
470 int copy_event_common_context_field_class_content(
471 struct trace_ir_metadata_maps
*md_maps
,
472 const char *debug_info_fc_name
,
473 const bt_field_class
*in_field_class
,
474 bt_field_class
*out_field_class
)
476 bt_field_class
*debug_field_class
= NULL
, *bin_field_class
= NULL
,
477 *func_field_class
= NULL
, *src_field_class
= NULL
;
479 bt_logging_level log_level
= md_maps
->log_level
;
480 bt_self_component
*self_comp
= md_maps
->self_comp
;
482 BT_COMP_LOGD("Copying content of event common context field class: "
483 "in-fc-addr=%p, out-fc-addr=%p", in_field_class
, out_field_class
);
485 /* Copy the content of the input common context. */
486 ret
= copy_field_class_content(md_maps
, in_field_class
, out_field_class
);
492 * If this event common context has the necessary fields to compute the
493 * debug information append the debug-info field class to the event
496 if (is_event_common_ctx_dbg_info_compatible(in_field_class
, debug_info_fc_name
)) {
498 * The struct field and 3 sub-fields are not stored in the
499 * field class map because they don't have input equivalent.
500 * We need to put our reference each of these field classes
501 * once they are added to their respective containing field
504 debug_field_class
= bt_field_class_structure_create(
505 md_maps
->output_trace_class
);
506 if (!debug_field_class
) {
507 BT_COMP_LOGE_STR("Failed to create debug_info structure.");
512 bin_field_class
= bt_field_class_string_create(
513 md_maps
->output_trace_class
);
514 if (!bin_field_class
) {
515 BT_COMP_LOGE_STR("Failed to create string for field=bin.");
520 func_field_class
= bt_field_class_string_create(
521 md_maps
->output_trace_class
);
522 if (!func_field_class
) {
523 BT_COMP_LOGE_STR("Failed to create string for field=func.");
528 src_field_class
= bt_field_class_string_create(
529 md_maps
->output_trace_class
);
530 if (!src_field_class
) {
531 BT_COMP_LOGE_STR("Failed to create string for field=src.");
536 if (bt_field_class_structure_append_member(
537 debug_field_class
, "bin", bin_field_class
) !=
538 BT_FIELD_CLASS_STRUCTURE_APPEND_MEMBER_STATUS_OK
) {
539 BT_COMP_LOGE_STR("Failed to add a field to debug_info "
540 "struct: field=bin.");
544 BT_FIELD_CLASS_PUT_REF_AND_RESET(bin_field_class
);
546 if (bt_field_class_structure_append_member(
547 debug_field_class
, "func", func_field_class
) !=
548 BT_FIELD_CLASS_STRUCTURE_APPEND_MEMBER_STATUS_OK
) {
549 BT_COMP_LOGE_STR("Failed to add a field to debug_info "
550 "struct: field=func.");
554 BT_FIELD_CLASS_PUT_REF_AND_RESET(func_field_class
);
556 if (bt_field_class_structure_append_member(
557 debug_field_class
, "src", src_field_class
) !=
558 BT_FIELD_CLASS_STRUCTURE_APPEND_MEMBER_STATUS_OK
) {
559 BT_COMP_LOGE_STR("Failed to add a field to debug_info "
560 "struct: field=src.");
564 BT_FIELD_CLASS_PUT_REF_AND_RESET(src_field_class
);
566 /*Add the filled debug-info field class to the common context. */
567 if (bt_field_class_structure_append_member(out_field_class
,
568 debug_info_fc_name
, debug_field_class
) !=
569 BT_FIELD_CLASS_STRUCTURE_APPEND_MEMBER_STATUS_OK
) {
570 BT_COMP_LOGE_STR("Failed to add debug_info field to "
571 "event common context.");
575 BT_FIELD_CLASS_PUT_REF_AND_RESET(debug_field_class
);
577 BT_COMP_LOGD("Copied content of event common context field class: "
578 "in-fc-addr=%p, out-fc-addr=%p", in_field_class
, out_field_class
);
582 if (debug_field_class
) {
583 bt_field_class_put_ref(debug_field_class
);
585 if (bin_field_class
) {
586 bt_field_class_put_ref(bin_field_class
);
588 if (func_field_class
) {
589 bt_field_class_put_ref(func_field_class
);
591 if (src_field_class
) {
592 bt_field_class_put_ref(src_field_class
);
599 bt_field_class
*create_field_class_copy(struct trace_ir_metadata_maps
*md_maps
,
600 const bt_field_class
*in_field_class
)
602 return create_field_class_copy_internal(md_maps
, in_field_class
);
606 int copy_field_class_content(struct trace_ir_metadata_maps
*md_maps
,
607 const bt_field_class
*in_field_class
,
608 bt_field_class
*out_field_class
)
610 return copy_field_class_content_internal(md_maps
, in_field_class
,