2 * Babeltrace - Mapping of IR metadata and data object between input and output
5 * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation
6 * Copyright (c) 2018 Philippe Proulx <pproulx@efficios.com>
7 * Copyright (c) 2019 Francis Deslauriers <francis.deslauriers@efficios.com>
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 #define BT_LOG_TAG "PLUGIN-LTTNG-UTILS-DEBUG-INFO-TRACE-IR-MAPPING"
33 #include <babeltrace2/assert-internal.h>
34 #include <babeltrace2/babeltrace.h>
35 /* For bt_property_availability */
36 #include <babeltrace2/property.h>
38 #include "debug-info.h"
39 #include "trace-ir-data-copy.h"
40 #include "trace-ir-mapping.h"
41 #include "trace-ir-metadata-copy.h"
44 bt_trace_class
*create_new_mapped_trace_class(struct trace_ir_maps
*ir_maps
,
45 const bt_trace_class
*in_trace_class
)
48 bt_trace_class
*out_trace_class
;
50 BT_LOGD("Creating new mapped trace class: in-tc-addr=%p", in_trace_class
);
53 BT_ASSERT(in_trace_class
);
55 /* Create the ouput trace class. */
56 out_trace_class
= bt_trace_class_create(ir_maps
->self_comp
);
57 if (!out_trace_class
) {
58 BT_LOGE_STR("Error create output trace class");
62 /* If not, create a new one and add it to the mapping. */
63 ret
= copy_trace_class_content(in_trace_class
, out_trace_class
);
65 BT_LOGE_STR("Error copy content to output trace class");
66 out_trace_class
= NULL
;
70 BT_LOGD("Created new mapped trace class: in-tc-addr=%p, out-tc-addr=%p",
71 in_trace_class
, out_trace_class
);
74 return out_trace_class
;
78 bt_trace
*create_new_mapped_trace(struct trace_ir_maps
*ir_maps
,
79 const bt_trace
*in_trace
)
82 const bt_trace_class
*in_trace_class
;
83 struct trace_ir_metadata_maps
*metadata_maps
;
85 BT_LOGD("Creating new mapped trace: in-t-addr=%p", in_trace
);
89 in_trace_class
= bt_trace_borrow_class_const(in_trace
);
90 metadata_maps
= borrow_metadata_maps_from_input_trace_class(ir_maps
,
93 if (!metadata_maps
->output_trace_class
) {
94 metadata_maps
->output_trace_class
=
95 create_new_mapped_trace_class(ir_maps
, in_trace_class
);
96 if (!metadata_maps
->output_trace_class
) {
102 out_trace
= bt_trace_create(metadata_maps
->output_trace_class
);
104 BT_LOGE_STR("Error create output trace");
108 /* If not, create a new one and add it to the mapping. */
109 copy_trace_content(in_trace
, out_trace
);
111 BT_LOGD("Created new mapped trace: in-t-addr=%p, out-t-addr=%p",
112 in_trace
, out_trace
);
118 bt_stream_class
*borrow_mapped_stream_class(struct trace_ir_metadata_maps
*md_maps
,
119 const bt_stream_class
*in_stream_class
)
122 BT_ASSERT(in_stream_class
);
124 return g_hash_table_lookup(md_maps
->stream_class_map
,
125 (gpointer
) in_stream_class
);
129 bt_stream_class
*create_new_mapped_stream_class(struct trace_ir_maps
*ir_maps
,
130 const bt_stream_class
*in_stream_class
)
133 bt_stream_class
*out_stream_class
;
134 struct trace_ir_metadata_maps
*md_maps
;
136 BT_LOGD("Creating new mapped stream class: in-sc-addr=%p",
139 md_maps
= borrow_metadata_maps_from_input_stream_class(ir_maps
,
143 BT_ASSERT(in_stream_class
);
144 BT_ASSERT(!borrow_mapped_stream_class(md_maps
, in_stream_class
));
146 /* Create an out_stream_class. */
147 out_stream_class
= bt_stream_class_create_with_id(
148 md_maps
->output_trace_class
,
149 bt_stream_class_get_id(in_stream_class
));
150 if (!out_stream_class
) {
151 BT_LOGE_STR("Error create output stream class");
155 /* If not, create a new one and add it to the mapping. */
156 ret
= copy_stream_class_content(ir_maps
, in_stream_class
,
159 BT_LOGE_STR("Error copy content to output stream class");
160 out_stream_class
= NULL
;
164 g_hash_table_insert(md_maps
->stream_class_map
,
165 (gpointer
) in_stream_class
, out_stream_class
);
167 BT_LOGD("Created new mapped stream class: in-sc-addr=%p, out-sc-addr=%p",
168 in_stream_class
, out_stream_class
);
171 return out_stream_class
;
175 bt_stream
*borrow_mapped_stream(struct trace_ir_data_maps
*d_maps
,
176 const bt_stream
*in_stream
)
179 BT_ASSERT(in_stream
);
181 return g_hash_table_lookup(d_maps
->stream_map
, (gpointer
) in_stream
);
185 bt_stream
*trace_ir_mapping_create_new_mapped_stream(
186 struct trace_ir_maps
*ir_maps
,
187 const bt_stream
*in_stream
)
189 struct trace_ir_data_maps
*d_maps
;
190 struct trace_ir_metadata_maps
*md_maps
;
191 const bt_stream_class
*in_stream_class
;
192 const bt_trace
*in_trace
;
193 bt_stream_class
*out_stream_class
;
194 bt_stream
*out_stream
= NULL
;
196 BT_LOGD("Creating new mapped stream: in-s-addr=%p", in_stream
);
199 BT_ASSERT(in_stream
);
201 in_trace
= bt_stream_borrow_trace_const(in_stream
);
203 d_maps
= borrow_data_maps_from_input_trace(ir_maps
, in_trace
);
204 if (!d_maps
->output_trace
) {
205 d_maps
->output_trace
= create_new_mapped_trace(ir_maps
, in_trace
);
206 if (!d_maps
->output_trace
) {
211 BT_ASSERT(d_maps
->output_trace
);
212 BT_ASSERT(!borrow_mapped_stream(d_maps
, in_stream
));
214 in_stream_class
= bt_stream_borrow_class_const(in_stream
);
215 md_maps
= borrow_metadata_maps_from_input_stream_class(ir_maps
, in_stream_class
);
216 out_stream_class
= borrow_mapped_stream_class(md_maps
, in_stream_class
);
217 if (!out_stream_class
) {
218 out_stream_class
= create_new_mapped_stream_class(ir_maps
,
220 if (!out_stream_class
) {
224 BT_ASSERT(out_stream_class
);
226 out_stream
= bt_stream_create_with_id(out_stream_class
,
227 d_maps
->output_trace
, bt_stream_get_id(in_stream
));
229 BT_LOGE_STR("Error creating output stream");
233 * Release our ref since the trace object will be managing the life
234 * time of the stream objects.
237 copy_stream_content(in_stream
, out_stream
);
239 g_hash_table_insert(d_maps
->stream_map
, (gpointer
) in_stream
,
242 BT_LOGD("Created new mapped stream: in-s-addr=%p, out-s-addr=%p",
243 in_stream
, out_stream
);
250 bt_stream
*trace_ir_mapping_borrow_mapped_stream(struct trace_ir_maps
*ir_maps
,
251 const bt_stream
*in_stream
)
254 BT_ASSERT(in_stream
);
255 struct trace_ir_data_maps
*d_maps
;
257 d_maps
= borrow_data_maps_from_input_stream(ir_maps
, in_stream
);
258 /* Return the mapped stream. */
259 return borrow_mapped_stream(d_maps
, in_stream
);
263 bt_event_class
*borrow_mapped_event_class(struct trace_ir_metadata_maps
*md_maps
,
264 const bt_event_class
*in_event_class
)
266 return g_hash_table_lookup(md_maps
->event_class_map
,
267 (gpointer
) in_event_class
);
271 bt_event_class
*trace_ir_mapping_create_new_mapped_event_class(
272 struct trace_ir_maps
*ir_maps
,
273 const bt_event_class
*in_event_class
)
275 bt_event_class
*out_event_class
;
276 const bt_trace_class
*in_trace_class
;
277 const bt_stream_class
*in_stream_class
;
278 bt_stream_class
*out_stream_class
;
279 struct trace_ir_metadata_maps
*md_maps
;
282 BT_LOGD("Creating new mapped event class: in-ec-addr=%p",
286 BT_ASSERT(in_event_class
);
288 in_trace_class
= bt_stream_class_borrow_trace_class_const(
289 bt_event_class_borrow_stream_class_const(
292 md_maps
= borrow_metadata_maps_from_input_trace_class(ir_maps
, in_trace_class
);
294 BT_ASSERT(!borrow_mapped_event_class(md_maps
, in_event_class
));
297 bt_event_class_borrow_stream_class_const(in_event_class
);
298 BT_ASSERT(in_stream_class
);
300 /* Get the right output stream class to add the new event class to. */
301 out_stream_class
= borrow_mapped_stream_class(md_maps
, in_stream_class
);
302 BT_ASSERT(out_stream_class
);
304 /* Create an output event class. */
305 out_event_class
= bt_event_class_create_with_id(out_stream_class
,
306 bt_event_class_get_id(in_event_class
));
307 if (!out_event_class
) {
308 BT_LOGE_STR("Error creating output event class");
312 /* If not, create a new one and add it to the mapping. */
313 ret
= copy_event_class_content(ir_maps
, in_event_class
,
316 BT_LOGE_STR("Error copy content to output event class");
317 out_event_class
= NULL
;
321 g_hash_table_insert(md_maps
->event_class_map
,
322 (gpointer
) in_event_class
, out_event_class
);
324 BT_LOGD("Created new mapped event class: in-ec-addr=%p, out-ec-addr=%p",
325 in_event_class
, out_event_class
);
328 return out_event_class
;
332 bt_event_class
*trace_ir_mapping_borrow_mapped_event_class(
333 struct trace_ir_maps
*ir_maps
,
334 const bt_event_class
*in_event_class
)
336 struct trace_ir_metadata_maps
*md_maps
;
339 BT_ASSERT(in_event_class
);
341 md_maps
= borrow_metadata_maps_from_input_event_class(ir_maps
, in_event_class
);
343 /* Return the mapped event_class. */
344 return borrow_mapped_event_class(md_maps
, in_event_class
);
348 bt_packet
*borrow_mapped_packet(struct trace_ir_data_maps
*d_maps
,
349 const bt_packet
*in_packet
)
352 BT_ASSERT(in_packet
);
354 return g_hash_table_lookup(d_maps
->packet_map
,
355 (gpointer
) in_packet
);
359 bt_packet
*trace_ir_mapping_create_new_mapped_packet(
360 struct trace_ir_maps
*ir_maps
,
361 const bt_packet
*in_packet
)
363 struct trace_ir_data_maps
*d_maps
;
364 const bt_trace
*in_trace
;
365 const bt_stream
*in_stream
;
366 bt_packet
*out_packet
;
367 bt_stream
*out_stream
;
369 BT_LOGD("Creating new mapped packet: in-p-addr=%p", in_packet
);
371 in_stream
= bt_packet_borrow_stream_const(in_packet
);
372 in_trace
= bt_stream_borrow_trace_const(in_stream
);
373 d_maps
= borrow_data_maps_from_input_trace(ir_maps
, in_trace
);
375 /* There should never be a mapped packet. */
376 BT_ASSERT(!borrow_mapped_packet(d_maps
, in_packet
));
378 BT_ASSERT(in_stream
);
380 /* Get output stream corresponding to this input stream. */
381 out_stream
= borrow_mapped_stream(d_maps
, in_stream
);
382 BT_ASSERT(out_stream
);
384 /* Create the output packet. */
385 out_packet
= bt_packet_create(out_stream
);
387 BT_LOGE_STR("Error create output packet");
392 * Release our ref since the stream object will be managing the life
393 * time of the packet objects.
395 copy_packet_content(in_packet
, out_packet
);
397 g_hash_table_insert(d_maps
->packet_map
,
398 (gpointer
) in_packet
, out_packet
);
400 BT_LOGD("Created new mapped packet: in-p-addr=%p, out-p-addr=%p",
401 in_packet
, out_packet
);
408 bt_packet
*trace_ir_mapping_borrow_mapped_packet(struct trace_ir_maps
*ir_maps
,
409 const bt_packet
*in_packet
)
411 struct trace_ir_data_maps
*d_maps
;
413 BT_ASSERT(in_packet
);
415 d_maps
= borrow_data_maps_from_input_packet(ir_maps
, in_packet
);
417 return borrow_mapped_packet(d_maps
, in_packet
);
421 void trace_ir_mapping_remove_mapped_packet(struct trace_ir_maps
*ir_maps
,
422 const bt_packet
*in_packet
)
426 struct trace_ir_data_maps
*d_maps
;
428 BT_ASSERT(in_packet
);
430 d_maps
= borrow_data_maps_from_input_packet(ir_maps
, in_packet
);
432 ret
= g_hash_table_remove(d_maps
->packet_map
, in_packet
);
438 void trace_ir_mapping_remove_mapped_stream(struct trace_ir_maps
*ir_maps
,
439 const bt_stream
*in_stream
)
442 struct trace_ir_data_maps
*d_maps
;
445 BT_ASSERT(in_stream
);
447 d_maps
= borrow_data_maps_from_input_stream(ir_maps
, in_stream
);
449 ret
= g_hash_table_remove(d_maps
->stream_map
, in_stream
);
455 void trace_ir_metadata_maps_remove_func(const bt_trace_class
*in_trace_class
,
458 struct trace_ir_maps
*maps
= (struct trace_ir_maps
*) data
;
459 if (maps
->metadata_maps
) {
461 ret
= g_hash_table_remove(maps
->metadata_maps
,
462 (gpointer
) in_trace_class
);
468 void trace_ir_data_maps_remove_func(const bt_trace
*in_trace
, void *data
)
470 struct trace_ir_maps
*maps
= (struct trace_ir_maps
*) data
;
471 if (maps
->data_maps
) {
473 ret
= g_hash_table_remove(maps
->data_maps
, (gpointer
) in_trace
);
478 struct trace_ir_data_maps
*trace_ir_data_maps_create(struct trace_ir_maps
*ir_maps
,
479 const bt_trace
*in_trace
)
481 struct trace_ir_data_maps
*d_maps
=
482 g_new0(struct trace_ir_data_maps
, 1);
484 BT_LOGE_STR("Error allocating trace_ir_maps");
488 d_maps
->input_trace
= in_trace
;
490 /* Create the hashtables used to map data objects. */
491 d_maps
->stream_map
= g_hash_table_new_full(g_direct_hash
,
492 g_direct_equal
, NULL
,(GDestroyNotify
) bt_stream_put_ref
);
493 d_maps
->packet_map
= g_hash_table_new_full(g_direct_hash
,
494 g_direct_equal
, NULL
,(GDestroyNotify
) bt_packet_put_ref
);
496 bt_trace_add_destruction_listener(in_trace
, trace_ir_data_maps_remove_func
,
497 ir_maps
, &d_maps
->destruction_listener_id
);
502 struct trace_ir_metadata_maps
*trace_ir_metadata_maps_create(
503 struct trace_ir_maps
*ir_maps
,
504 const bt_trace_class
*in_trace_class
)
506 struct trace_ir_metadata_maps
*md_maps
=
507 g_new0(struct trace_ir_metadata_maps
, 1);
509 BT_LOGE_STR("Error allocating trace_ir_maps");
513 md_maps
->input_trace_class
= in_trace_class
;
515 * Create the field class resolving context. This is needed to keep
516 * track of the field class already copied in order to do the field
517 * path resolution correctly.
519 md_maps
->fc_resolving_ctx
=
520 g_new0(struct field_class_resolving_context
, 1);
521 if (!md_maps
->fc_resolving_ctx
) {
522 BT_LOGE_STR("Error allocating field_class_resolving_context");
526 /* Create the hashtables used to map metadata objects. */
527 md_maps
->stream_class_map
= g_hash_table_new_full(g_direct_hash
,
528 g_direct_equal
, NULL
, (GDestroyNotify
) bt_stream_class_put_ref
);
529 md_maps
->event_class_map
= g_hash_table_new_full(g_direct_hash
,
530 g_direct_equal
, NULL
, (GDestroyNotify
) bt_event_class_put_ref
);
531 md_maps
->field_class_map
= g_hash_table_new_full(g_direct_hash
,
532 g_direct_equal
, NULL
, (GDestroyNotify
) bt_field_class_put_ref
);
533 md_maps
->clock_class_map
= g_hash_table_new_full(g_direct_hash
,
534 g_direct_equal
, NULL
, (GDestroyNotify
) bt_clock_class_put_ref
);
536 bt_trace_class_add_destruction_listener(in_trace_class
,
537 trace_ir_metadata_maps_remove_func
,
538 ir_maps
, &md_maps
->destruction_listener_id
);
544 void trace_ir_data_maps_destroy(struct trace_ir_data_maps
*maps
)
546 bt_trace_status status
;
551 if (maps
->packet_map
) {
552 g_hash_table_destroy(maps
->packet_map
);
555 if (maps
->stream_map
) {
556 g_hash_table_destroy(maps
->stream_map
);
559 if (maps
->output_trace
) {
560 bt_trace_put_ref(maps
->output_trace
);
563 status
= bt_trace_remove_destruction_listener(maps
->input_trace
,
564 maps
->destruction_listener_id
);
565 if (status
!= BT_TRACE_STATUS_OK
) {
566 BT_LOGD("Trace destruction listener removal failed.");
573 void trace_ir_metadata_maps_destroy(struct trace_ir_metadata_maps
*maps
)
575 bt_trace_class_status status
;
580 if (maps
->stream_class_map
) {
581 g_hash_table_destroy(maps
->stream_class_map
);
584 if (maps
->event_class_map
) {
585 g_hash_table_destroy(maps
->event_class_map
);
588 if (maps
->field_class_map
) {
589 g_hash_table_destroy(maps
->field_class_map
);
592 if (maps
->clock_class_map
) {
593 g_hash_table_destroy(maps
->clock_class_map
);
596 if (maps
->fc_resolving_ctx
) {
597 g_free(maps
->fc_resolving_ctx
);
600 if (maps
->output_trace_class
) {
601 bt_trace_class_put_ref(maps
->output_trace_class
);
604 status
= bt_trace_class_remove_destruction_listener(maps
->input_trace_class
,
605 maps
->destruction_listener_id
);
606 if (status
!= BT_TRACE_CLASS_STATUS_OK
) {
607 BT_LOGD("Trace destruction listener removal failed.");
613 void trace_ir_maps_clear(struct trace_ir_maps
*maps
)
615 if (maps
->data_maps
) {
616 g_hash_table_remove_all(maps
->data_maps
);
619 if (maps
->metadata_maps
) {
620 g_hash_table_remove_all(maps
->metadata_maps
);
625 void trace_ir_maps_destroy(struct trace_ir_maps
*maps
)
631 if (maps
->debug_info_field_class_name
) {
632 g_free(maps
->debug_info_field_class_name
);
635 if (maps
->data_maps
) {
636 g_hash_table_destroy(maps
->data_maps
);
637 maps
->data_maps
= NULL
;
640 if (maps
->metadata_maps
) {
641 g_hash_table_destroy(maps
->metadata_maps
);
642 maps
->metadata_maps
= NULL
;
649 struct trace_ir_maps
*trace_ir_maps_create(bt_self_component
*self_comp
,
650 const char *debug_info_field_name
)
652 struct trace_ir_maps
*trace_ir_maps
=
653 g_new0(struct trace_ir_maps
, 1);
654 if (!trace_ir_maps
) {
655 BT_LOGE_STR("Error allocating trace_ir_maps");
659 /* Copy debug info field name received from the user. */
660 trace_ir_maps
->debug_info_field_class_name
=
661 g_strdup(debug_info_field_name
);
662 if (!trace_ir_maps
->debug_info_field_class_name
) {
663 BT_LOGE_STR("Cannot copy debug info field name");
667 trace_ir_maps
->self_comp
= self_comp
;
669 trace_ir_maps
->data_maps
= g_hash_table_new_full(g_direct_hash
,
670 g_direct_equal
, (GDestroyNotify
) NULL
,
671 (GDestroyNotify
) trace_ir_data_maps_destroy
);
673 trace_ir_maps
->metadata_maps
= g_hash_table_new_full(g_direct_hash
,
674 g_direct_equal
, (GDestroyNotify
) NULL
,
675 (GDestroyNotify
) trace_ir_metadata_maps_destroy
);
679 trace_ir_maps_destroy(trace_ir_maps
);
680 trace_ir_maps
= NULL
;
682 return trace_ir_maps
;