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_TAG "PLUGIN-LTTNG-UTILS-DEBUG-INFO-TRACE-IR-METADATA-COPY"
33 #include <babeltrace/assert-internal.h>
35 #include "trace-ir-metadata-copy.h"
36 #include "trace-ir-metadata-field-class-copy.h"
40 int copy_trace_class_content(const bt_trace_class
*in_trace_class
,
41 bt_trace_class
*out_trace_class
)
44 uint64_t i
, env_field_count
;
45 const char *in_trace_class_name
;
47 BT_LOGD("Copying content of trace class: in-tc-addr=%p, out-tc-addr=%p",
48 in_trace_class
, out_trace_class
);
50 /* Use the same stream class ids as in the origin trace class. */
51 bt_trace_class_set_assigns_automatic_stream_class_id(out_trace_class
,
54 in_trace_class_name
= bt_trace_class_get_name(in_trace_class
);
55 if (in_trace_class_name
) {
56 bt_trace_class_set_name(out_trace_class
, in_trace_class_name
);
60 * Do not copy the trace class UUID as it may be modified and should no
61 * longer have the same UUID.
65 * Go over all the entries in the environment section of the trace class
66 * and copy the content to the new trace class.
68 env_field_count
= bt_trace_class_get_environment_entry_count(in_trace_class
);
69 for (i
= 0; i
< env_field_count
; i
++) {
70 const char *value_name
;
71 const bt_value
*value
= NULL
;
72 bt_trace_class_status trace_class_status
;
74 bt_trace_class_borrow_environment_entry_by_index_const(
75 in_trace_class
, i
, &value_name
, &value
);
77 BT_LOGD("Copying trace class environnement entry: "
78 "index=%" PRId64
", value-addr=%p, value-name=%s",
79 i
, value
, value_name
);
81 BT_ASSERT(value_name
);
84 if (bt_value_is_integer(value
)) {
86 bt_trace_class_set_environment_entry_integer(
87 out_trace_class
, value_name
,
88 bt_value_integer_get(value
));
89 } else if (bt_value_is_string(value
)) {
91 bt_trace_class_set_environment_entry_string(
92 out_trace_class
, value_name
,
93 bt_value_string_get(value
));
98 if (trace_class_status
!= BT_TRACE_CLASS_STATUS_OK
) {
104 BT_LOGD("Copied content of trace class: in-tc-addr=%p, out-tc-addr=%p",
105 in_trace_class
, out_trace_class
);
111 int copy_clock_class_content(const bt_clock_class
*in_clock_class
,
112 bt_clock_class
*out_clock_class
)
114 bt_clock_class_status status
;
115 const char *clock_class_name
, *clock_class_description
;
121 BT_LOGD("Copying content of clock class: in-cc-addr=%p, out-cc-addr=%p",
122 in_clock_class
, out_clock_class
);
124 clock_class_name
= bt_clock_class_get_name(in_clock_class
);
126 if (clock_class_name
) {
127 status
= bt_clock_class_set_name(out_clock_class
, clock_class_name
);
128 if (status
!= BT_CLOCK_CLASS_STATUS_OK
) {
129 BT_LOGE("Error setting clock class' name cc-addr=%p, name=%p",
130 out_clock_class
, clock_class_name
);
131 out_clock_class
= NULL
;
137 clock_class_description
= bt_clock_class_get_description(in_clock_class
);
139 if (clock_class_description
) {
140 status
= bt_clock_class_set_description(out_clock_class
,
141 clock_class_description
);
142 if (status
!= BT_CLOCK_CLASS_STATUS_OK
) {
143 BT_LOGE("Error setting clock class' description cc-addr=%p, "
144 "name=%p", out_clock_class
, clock_class_description
);
145 out_clock_class
= NULL
;
151 in_uuid
= bt_clock_class_get_uuid(in_clock_class
);
153 bt_clock_class_set_uuid(out_clock_class
, in_uuid
);
156 bt_clock_class_set_frequency(out_clock_class
,
157 bt_clock_class_get_frequency(in_clock_class
));
158 bt_clock_class_set_precision(out_clock_class
,
159 bt_clock_class_get_precision(in_clock_class
));
160 bt_clock_class_get_offset(in_clock_class
, &seconds
, &cycles
);
161 bt_clock_class_set_offset(out_clock_class
, seconds
, cycles
);
162 bt_clock_class_set_origin_is_unix_epoch(out_clock_class
,
163 bt_clock_class_origin_is_unix_epoch(in_clock_class
));
165 BT_LOGD("Copied content of clock class: in-cc-addr=%p, out-cc-addr=%p",
166 in_clock_class
, out_clock_class
);
173 bt_clock_class
*borrow_mapped_clock_class(
174 struct trace_ir_metadata_maps
*md_maps
,
175 const bt_clock_class
*in_clock_class
)
178 BT_ASSERT(in_clock_class
);
180 return g_hash_table_lookup(md_maps
->clock_class_map
,
181 (gpointer
) in_clock_class
);
185 bt_clock_class
*create_new_mapped_clock_class(
186 bt_self_component
*self_comp
,
187 struct trace_ir_metadata_maps
*md_maps
,
188 const bt_clock_class
*in_clock_class
)
190 bt_clock_class
*out_clock_class
;
193 BT_LOGD("Creating new mapped clock class: in-cc-addr=%p",
197 BT_ASSERT(in_clock_class
);
199 BT_ASSERT(!borrow_mapped_clock_class(md_maps
, in_clock_class
));
201 out_clock_class
= bt_clock_class_create(self_comp
);
202 if (!out_clock_class
) {
203 BT_LOGE_STR("Cannot create clock class");
206 /* If not, create a new one and add it to the mapping. */
207 ret
= copy_clock_class_content(in_clock_class
, out_clock_class
);
209 BT_LOGE_STR("Cannot copy clock class");
213 g_hash_table_insert(md_maps
->clock_class_map
,
214 (gpointer
) in_clock_class
, out_clock_class
);
216 BT_LOGD("Created new mapped clock class: in-cc-addr=%p, out-cc-addr=%p",
217 in_clock_class
, out_clock_class
);
219 return out_clock_class
;
223 int copy_stream_class_content(struct trace_ir_maps
*ir_maps
,
224 const bt_stream_class
*in_stream_class
,
225 bt_stream_class
*out_stream_class
)
227 struct trace_ir_metadata_maps
*md_maps
;
228 const bt_clock_class
*in_clock_class
;
229 bt_clock_class
*out_clock_class
;
230 const bt_field_class
*in_packet_context_fc
, *in_common_context_fc
;
231 bt_field_class
*out_packet_context_fc
, *out_common_context_fc
;
232 bt_stream_class_status status
;
236 BT_LOGD("Copying content of stream class: in-sc-addr=%p, out-sc-addr=%p",
237 in_stream_class
, out_stream_class
);
239 md_maps
= borrow_metadata_maps_from_input_stream_class(ir_maps
, in_stream_class
);
240 in_clock_class
= bt_stream_class_borrow_default_clock_class_const(
243 if (in_clock_class
) {
244 /* Copy the clock class. */
246 borrow_mapped_clock_class(md_maps
, in_clock_class
);
247 if (!out_clock_class
) {
248 out_clock_class
= create_new_mapped_clock_class(
249 ir_maps
->self_comp
, md_maps
,
252 bt_stream_class_set_default_clock_class(out_stream_class
,
257 in_name
= bt_stream_class_get_name(in_stream_class
);
259 status
= bt_stream_class_set_name(out_stream_class
, in_name
);
260 if (status
!= BT_STREAM_CLASS_STATUS_OK
) {
261 BT_LOGE("Error set stream class name: out-sc-addr=%p, "
262 "name=%s", out_stream_class
, in_name
);
268 bt_stream_class_set_assigns_automatic_stream_id(out_stream_class
,
270 bt_stream_class_set_assigns_automatic_event_class_id(out_stream_class
,
274 * Add the input packet context field class to the context to
275 * resolution in the further steps.
277 in_packet_context_fc
=
278 bt_stream_class_borrow_packet_context_field_class_const(
280 md_maps
->fc_resolving_ctx
->packet_context
=
281 in_packet_context_fc
;
283 if (in_packet_context_fc
) {
284 /* Copy packet context. */
285 out_packet_context_fc
= create_field_class_copy(
286 md_maps
, in_packet_context_fc
);
288 ret
= copy_field_class_content(md_maps
,
289 in_packet_context_fc
, out_packet_context_fc
);
295 status
= bt_stream_class_set_packet_context_field_class(
296 out_stream_class
, out_packet_context_fc
);
297 if (status
!= BT_STREAM_CLASS_STATUS_OK
) {
298 BT_LOGE("Error setting stream class' packet context "
299 "field class: sc-addr=%p, packet-fc-addr=%p",
300 out_stream_class
, out_packet_context_fc
);
307 * Add the input common context field class to the context to
308 * resolution in the further steps.
310 in_common_context_fc
=
311 bt_stream_class_borrow_event_common_context_field_class_const(
313 md_maps
->fc_resolving_ctx
->event_common_context
=
314 in_common_context_fc
;
316 if (in_common_context_fc
) {
317 /* Copy common context. */
318 /* TODO: I find it a bit awkward to have this special function
319 * here to add the debug-info field class. I would like to
321 out_common_context_fc
= create_field_class_copy(
322 md_maps
, in_common_context_fc
);
324 ret
= copy_event_common_context_field_class_content(
325 md_maps
, ir_maps
->debug_info_field_class_name
,
326 in_common_context_fc
, out_common_context_fc
);
331 status
= bt_stream_class_set_event_common_context_field_class(
332 out_stream_class
, out_common_context_fc
);
333 if (status
!= BT_STREAM_CLASS_STATUS_OK
) {
334 BT_LOGE("Error setting stream class' packet context "
335 "field class: sc-addr=%p, packet-fc-addr=%p",
336 out_stream_class
, out_common_context_fc
);
342 /* Set packet snapshot boolean fields. */
343 BT_LOGD("Copied content of stream class: in-sc-addr=%p, out-sc-addr=%p",
344 in_stream_class
, out_stream_class
);
350 int copy_event_class_content(struct trace_ir_maps
*ir_maps
,
351 const bt_event_class
*in_event_class
,
352 bt_event_class
*out_event_class
)
354 struct trace_ir_metadata_maps
*md_maps
;
355 const char *in_event_class_name
, *in_emf_uri
;
356 bt_property_availability prop_avail
;
357 bt_event_class_log_level log_level
;
358 bt_event_class_status status
;
359 bt_field_class
*out_specific_context_fc
, *out_payload_fc
;
360 const bt_field_class
*in_event_specific_context
, *in_event_payload
;
363 BT_LOGD("Copying content of event class: in-ec-addr=%p, out-ec-addr=%p",
364 in_event_class
, out_event_class
);
366 /* Copy event class name. */
367 in_event_class_name
= bt_event_class_get_name(in_event_class
);
368 if (in_event_class_name
) {
369 status
= bt_event_class_set_name(out_event_class
, in_event_class_name
);
370 if (status
!= BT_EVENT_CLASS_STATUS_OK
) {
371 BT_LOGE("Error setting event class' name: ec-addr=%p, "
372 "name=%s", out_event_class
, in_event_class_name
);
378 /* Copy event class loglevel. */
379 prop_avail
= bt_event_class_get_log_level(in_event_class
, &log_level
);
380 if (prop_avail
== BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
381 bt_event_class_set_log_level(out_event_class
,
385 /* Copy event class emf uri. */
386 in_emf_uri
= bt_event_class_get_emf_uri(in_event_class
);
388 status
= bt_event_class_set_emf_uri(out_event_class
, in_emf_uri
);
389 if (status
!= BT_EVENT_CLASS_STATUS_OK
) {
390 BT_LOGE("Error setting event class' emf uri: ec-addr=%p, "
391 "emf uri=%s", out_event_class
, in_emf_uri
);
397 md_maps
= borrow_metadata_maps_from_input_event_class(ir_maps
, in_event_class
);
399 * Add the input event class' specific ctx to te
402 in_event_specific_context
=
403 bt_event_class_borrow_specific_context_field_class_const(
406 md_maps
->fc_resolving_ctx
->event_specific_context
=
407 in_event_specific_context
;
409 if (in_event_specific_context
) {
410 /* Copy the specific context of this event class. */
411 out_specific_context_fc
= create_field_class_copy(md_maps
,
412 in_event_specific_context
);
414 copy_field_class_content(md_maps
,
415 in_event_specific_context
, out_specific_context_fc
);
420 * Add the output specific context to the output event
423 status
= bt_event_class_set_specific_context_field_class(
424 out_event_class
, out_specific_context_fc
);
425 if (status
!= BT_EVENT_CLASS_STATUS_OK
) {
426 BT_LOGE("Error setting event class' specific context "
427 "field class: ec-addr=%p, ctx-fc-addr=%p",
428 out_event_class
, out_specific_context_fc
);
435 * Add the input event class' payload field class to
438 in_event_payload
= bt_event_class_borrow_payload_field_class_const(
441 md_maps
->fc_resolving_ctx
->event_payload
= in_event_payload
;
443 if (in_event_payload
) {
444 /* Copy the payload of this event class. */
445 out_payload_fc
= create_field_class_copy(md_maps
,
447 copy_field_class_content(md_maps
,
448 in_event_payload
, out_payload_fc
);
453 /* Add the output payload to the output event class. */
454 status
= bt_event_class_set_payload_field_class(
455 out_event_class
, out_payload_fc
);
456 if (status
!= BT_EVENT_CLASS_STATUS_OK
) {
457 BT_LOGE("Error setting event class' payload "
458 "field class: ec-addr=%p, payload-fc-addr=%p",
459 out_event_class
, out_payload_fc
);
465 BT_LOGD("Copied content of event class: in-ec-addr=%p, out-ec-addr=%p",
466 in_event_class
, out_event_class
);
472 int copy_event_common_context_field_class_content(
473 struct trace_ir_metadata_maps
*md_maps
,
474 const char *debug_info_fc_name
,
475 const bt_field_class
*in_field_class
,
476 bt_field_class
*out_field_class
)
478 bt_field_class_status status
;
479 bt_field_class
*debug_field_class
= NULL
, *bin_field_class
= NULL
,
480 *func_field_class
= NULL
, *src_field_class
= NULL
;
483 BT_LOGD("Copying content of event common context field class: "
484 "in-fc-addr=%p, out-fc-addr=%p", in_field_class
, out_field_class
);
486 /* Copy the content of the input common context. */
487 ret
= copy_field_class_content(md_maps
, in_field_class
, out_field_class
);
493 * If this event common context has the necessary fields to compute the
494 * debug information append the debug-info field class to the event
497 if (is_event_common_ctx_dbg_info_compatible(in_field_class
, debug_info_fc_name
)) {
499 * The struct field and 3 sub-fields are not stored in the
500 * field class map because they don't have input equivalent.
501 * We need to put our reference each of these field classes
502 * once they are added to their respective containing field
505 debug_field_class
= bt_field_class_structure_create(
506 md_maps
->output_trace_class
);
507 if (!debug_field_class
) {
508 BT_LOGE_STR("Failed to create debug_info structure.");
513 bin_field_class
= bt_field_class_string_create(
514 md_maps
->output_trace_class
);
515 if (!bin_field_class
) {
516 BT_LOGE_STR("Failed to create string for field=bin.");
521 func_field_class
= bt_field_class_string_create(
522 md_maps
->output_trace_class
);
523 if (!func_field_class
) {
524 BT_LOGE_STR("Failed to create string for field=func.");
529 src_field_class
= bt_field_class_string_create(
530 md_maps
->output_trace_class
);
531 if (!src_field_class
) {
532 BT_LOGE_STR("Failed to create string for field=src.");
537 status
= bt_field_class_structure_append_member(
538 debug_field_class
, "bin", bin_field_class
);
539 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
540 BT_LOGE_STR("Failed to add a field to debug_info "
541 "struct: field=bin.");
545 BT_FIELD_CLASS_PUT_REF_AND_RESET(bin_field_class
);
547 status
= bt_field_class_structure_append_member(
548 debug_field_class
, "func", func_field_class
);
549 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
550 BT_LOGE_STR("Failed to add a field to debug_info "
551 "struct: field=func.");
555 BT_FIELD_CLASS_PUT_REF_AND_RESET(func_field_class
);
557 status
= bt_field_class_structure_append_member(
558 debug_field_class
, "src", src_field_class
);
559 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
560 BT_LOGE_STR("Failed to add a field to debug_info "
561 "struct: field=src.");
565 BT_FIELD_CLASS_PUT_REF_AND_RESET(src_field_class
);
567 /*Add the filled debug-info field class to the common context. */
568 status
= bt_field_class_structure_append_member(out_field_class
,
571 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
572 BT_LOGE_STR("Failed to add debug_info field to "
573 "event common context.");
577 BT_FIELD_CLASS_PUT_REF_AND_RESET(debug_field_class
);
579 BT_LOGD("Copied content of event common context field class: "
580 "in-fc-addr=%p, out-fc-addr=%p", in_field_class
, out_field_class
);
584 if (debug_field_class
) {
585 bt_field_class_put_ref(debug_field_class
);
587 if (bin_field_class
) {
588 bt_field_class_put_ref(bin_field_class
);
590 if (func_field_class
) {
591 bt_field_class_put_ref(func_field_class
);
593 if (src_field_class
) {
594 bt_field_class_put_ref(src_field_class
);
601 bt_field_class
*create_field_class_copy(struct trace_ir_metadata_maps
*md_maps
,
602 const bt_field_class
*in_field_class
)
604 return create_field_class_copy_internal(md_maps
, in_field_class
);
608 int copy_field_class_content(struct trace_ir_metadata_maps
*md_maps
,
609 const bt_field_class
*in_field_class
,
610 bt_field_class
*out_field_class
)
612 return copy_field_class_content_internal(md_maps
, in_field_class
,