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_COMP_LOG_SELF_COMP (ir_maps->self_comp)
29 #define BT_LOG_OUTPUT_LEVEL (ir_maps->log_level)
30 #define BT_LOG_TAG "PLUGIN/FLT.LTTNG-UTILS.DEBUG-INFO/TRACE-IR-MAPPING"
31 #include "logging/comp-logging.h"
35 #include "common/assert.h"
36 #include <babeltrace2/babeltrace.h>
37 /* For bt_property_availability */
38 #include <babeltrace2/property.h>
40 #include "debug-info.h"
41 #include "trace-ir-data-copy.h"
42 #include "trace-ir-mapping.h"
43 #include "trace-ir-metadata-copy.h"
46 bt_trace_class
*create_new_mapped_trace_class(struct trace_ir_maps
*ir_maps
,
47 const bt_trace_class
*in_trace_class
)
49 struct trace_ir_metadata_maps
*metadata_maps
;
52 BT_COMP_LOGD("Creating new mapped trace class: in-tc-addr=%p", in_trace_class
);
55 BT_ASSERT(in_trace_class
);
57 metadata_maps
= borrow_metadata_maps_from_input_trace_class(ir_maps
,
60 BT_ASSERT(!metadata_maps
->output_trace_class
);
62 /* Create the ouput trace class. */
63 metadata_maps
->output_trace_class
=
64 bt_trace_class_create(ir_maps
->self_comp
);
65 if (!metadata_maps
->output_trace_class
) {
66 BT_COMP_LOGE_STR("Error create output trace class");
70 /* Copy the content over and add to the mapping. */
71 ret
= copy_trace_class_content(ir_maps
, in_trace_class
,
72 metadata_maps
->output_trace_class
, ir_maps
->log_level
,
75 BT_COMP_LOGE_STR("Error copy content to output trace class");
76 BT_TRACE_CLASS_PUT_REF_AND_RESET(metadata_maps
->output_trace_class
);
77 metadata_maps
->output_trace_class
= NULL
;
81 BT_COMP_LOGD("Created new mapped trace class: in-tc-addr=%p, out-tc-addr=%p",
82 in_trace_class
, metadata_maps
->output_trace_class
);
85 return metadata_maps
->output_trace_class
;
89 bt_trace
*create_new_mapped_trace(struct trace_ir_maps
*ir_maps
,
90 const bt_trace
*in_trace
)
92 struct trace_ir_metadata_maps
*metadata_maps
;
93 const bt_trace_class
*in_trace_class
;
96 BT_COMP_LOGD("Creating new mapped trace: in-t-addr=%p", in_trace
);
100 in_trace_class
= bt_trace_borrow_class_const(in_trace
);
101 metadata_maps
= borrow_metadata_maps_from_input_trace_class(ir_maps
,
104 if (!metadata_maps
->output_trace_class
) {
106 * If there is no output trace class yet, create a one and add
109 metadata_maps
->output_trace_class
=
110 create_new_mapped_trace_class(ir_maps
, in_trace_class
);
111 if (!metadata_maps
->output_trace_class
) {
117 /* Create the output trace from the output trace class. */
118 out_trace
= bt_trace_create(metadata_maps
->output_trace_class
);
120 BT_COMP_LOGE_STR("Error create output trace");
124 /* Copy the content over to the output trace. */
125 copy_trace_content(in_trace
, out_trace
, ir_maps
->log_level
,
128 BT_COMP_LOGD("Created new mapped trace: in-t-addr=%p, out-t-addr=%p",
129 in_trace
, out_trace
);
135 bt_stream_class
*trace_ir_mapping_borrow_mapped_stream_class(
136 struct trace_ir_maps
*ir_maps
,
137 const bt_stream_class
*in_stream_class
)
139 BT_ASSERT_DBG(ir_maps
);
140 BT_ASSERT_DBG(in_stream_class
);
142 struct trace_ir_metadata_maps
*md_maps
=
143 borrow_metadata_maps_from_input_stream_class(ir_maps
,
145 return g_hash_table_lookup(md_maps
->stream_class_map
,
146 (gpointer
) in_stream_class
);
150 bt_stream_class
*trace_ir_mapping_create_new_mapped_stream_class(
151 struct trace_ir_maps
*ir_maps
,
152 const bt_stream_class
*in_stream_class
)
154 struct trace_ir_metadata_maps
*md_maps
;
155 bt_stream_class
*out_stream_class
;
158 BT_COMP_LOGD("Creating new mapped stream class: in-sc-addr=%p",
162 BT_ASSERT(in_stream_class
);
163 BT_ASSERT(!trace_ir_mapping_borrow_mapped_stream_class(ir_maps
,
166 md_maps
= borrow_metadata_maps_from_input_stream_class(ir_maps
,
171 /* Create the output stream class. */
172 out_stream_class
= bt_stream_class_create_with_id(
173 md_maps
->output_trace_class
,
174 bt_stream_class_get_id(in_stream_class
));
175 if (!out_stream_class
) {
176 BT_COMP_LOGE_STR("Error create output stream class");
180 /* Add it to the mapping. */
181 g_hash_table_insert(md_maps
->stream_class_map
,
182 (gpointer
) in_stream_class
, out_stream_class
);
184 /* Copy the content over to the output stream class. */
185 ret
= copy_stream_class_content(ir_maps
, in_stream_class
,
188 BT_COMP_LOGE_STR("Error copy content to output stream class");
189 out_stream_class
= NULL
;
193 BT_COMP_LOGD("Created new mapped stream class: in-sc-addr=%p, out-sc-addr=%p",
194 in_stream_class
, out_stream_class
);
197 return out_stream_class
;
201 bt_stream
*borrow_mapped_stream(struct trace_ir_data_maps
*d_maps
,
202 const bt_stream
*in_stream
)
204 BT_ASSERT_DBG(d_maps
);
205 BT_ASSERT_DBG(in_stream
);
207 return g_hash_table_lookup(d_maps
->stream_map
, (gpointer
) in_stream
);
211 bt_stream
*trace_ir_mapping_create_new_mapped_stream(
212 struct trace_ir_maps
*ir_maps
, const bt_stream
*in_stream
)
214 struct trace_ir_data_maps
*d_maps
;
215 const bt_stream_class
*in_stream_class
;
216 const bt_trace
*in_trace
;
217 bt_stream_class
*out_stream_class
;
218 bt_stream
*out_stream
= NULL
;
221 BT_ASSERT(in_stream
);
222 BT_COMP_LOGD("Creating new mapped stream: in-s-addr=%p", in_stream
);
224 in_trace
= bt_stream_borrow_trace_const(in_stream
);
226 d_maps
= borrow_data_maps_from_input_trace(ir_maps
, in_trace
);
227 if (!d_maps
->output_trace
) {
228 /* Create the output trace for this input trace. */
229 d_maps
->output_trace
= create_new_mapped_trace(ir_maps
, in_trace
);
230 if (!d_maps
->output_trace
) {
235 BT_ASSERT(d_maps
->output_trace
);
236 BT_ASSERT(!borrow_mapped_stream(d_maps
, in_stream
));
238 in_stream_class
= bt_stream_borrow_class_const(in_stream
);
239 out_stream_class
= trace_ir_mapping_borrow_mapped_stream_class(ir_maps
,
242 if (!out_stream_class
) {
243 /* Create the output stream class for this input stream class. */
244 out_stream_class
= trace_ir_mapping_create_new_mapped_stream_class(
245 ir_maps
, in_stream_class
);
246 if (!out_stream_class
) {
250 BT_ASSERT(out_stream_class
);
252 /* Create the output stream for this input stream. */
253 out_stream
= bt_stream_create_with_id(out_stream_class
,
254 d_maps
->output_trace
, bt_stream_get_id(in_stream
));
256 BT_COMP_LOGE_STR("Error creating output stream");
260 /* Add it to the mapping. */
261 g_hash_table_insert(d_maps
->stream_map
, (gpointer
) in_stream
,
264 /* Copy the content over to the output stream. */
265 copy_stream_content(in_stream
, out_stream
, ir_maps
->log_level
,
268 BT_COMP_LOGD("Created new mapped stream: in-s-addr=%p, out-s-addr=%p",
269 in_stream
, out_stream
);
276 bt_stream
*trace_ir_mapping_borrow_mapped_stream(struct trace_ir_maps
*ir_maps
,
277 const bt_stream
*in_stream
)
279 struct trace_ir_data_maps
*d_maps
;
281 BT_ASSERT_DBG(ir_maps
);
282 BT_ASSERT_DBG(in_stream
);
284 d_maps
= borrow_data_maps_from_input_stream(ir_maps
, in_stream
);
285 /* Return the mapped stream. */
286 return borrow_mapped_stream(d_maps
, in_stream
);
290 bt_event_class
*borrow_mapped_event_class(struct trace_ir_metadata_maps
*md_maps
,
291 const bt_event_class
*in_event_class
)
293 return g_hash_table_lookup(md_maps
->event_class_map
,
294 (gpointer
) in_event_class
);
298 bt_event_class
*trace_ir_mapping_create_new_mapped_event_class(
299 struct trace_ir_maps
*ir_maps
,
300 const bt_event_class
*in_event_class
)
302 struct trace_ir_metadata_maps
*md_maps
;
303 const bt_stream_class
*in_stream_class
;
304 bt_stream_class
*out_stream_class
;
305 bt_event_class
*out_event_class
;
308 BT_COMP_LOGD("Creating new mapped event class: in-ec-addr=%p",
312 BT_ASSERT(in_event_class
);
314 in_stream_class
= bt_event_class_borrow_stream_class_const(in_event_class
);
316 BT_ASSERT(in_stream_class
);
318 md_maps
= borrow_metadata_maps_from_input_stream_class(ir_maps
,
322 BT_ASSERT(!borrow_mapped_event_class(md_maps
, in_event_class
));
324 /* Get the right output stream class to add the new event class to it. */
325 out_stream_class
= trace_ir_mapping_borrow_mapped_stream_class(
326 ir_maps
, in_stream_class
);
327 BT_ASSERT(out_stream_class
);
329 /* Create an output event class. */
330 out_event_class
= bt_event_class_create_with_id(out_stream_class
,
331 bt_event_class_get_id(in_event_class
));
332 if (!out_event_class
) {
333 BT_COMP_LOGE_STR("Error creating output event class");
337 /* Add it to the mapping. */
338 g_hash_table_insert(md_maps
->event_class_map
,
339 (gpointer
) in_event_class
, out_event_class
);
341 /* Copy the content over to the output event class. */
342 ret
= copy_event_class_content(ir_maps
, in_event_class
,
345 BT_COMP_LOGE_STR("Error copy content to output event class");
346 out_event_class
= NULL
;
350 BT_COMP_LOGD("Created new mapped event class: in-ec-addr=%p, out-ec-addr=%p",
351 in_event_class
, out_event_class
);
354 return out_event_class
;
358 bt_event_class
*trace_ir_mapping_borrow_mapped_event_class(
359 struct trace_ir_maps
*ir_maps
,
360 const bt_event_class
*in_event_class
)
362 struct trace_ir_metadata_maps
*md_maps
;
364 BT_ASSERT_DBG(ir_maps
);
365 BT_ASSERT_DBG(in_event_class
);
367 md_maps
= borrow_metadata_maps_from_input_event_class(ir_maps
,
370 /* Return the mapped event_class. */
371 return borrow_mapped_event_class(md_maps
, in_event_class
);
375 bt_packet
*borrow_mapped_packet(struct trace_ir_data_maps
*d_maps
,
376 const bt_packet
*in_packet
)
378 BT_ASSERT_DBG(d_maps
);
379 BT_ASSERT_DBG(in_packet
);
381 return g_hash_table_lookup(d_maps
->packet_map
, (gpointer
) in_packet
);
385 bt_packet
*trace_ir_mapping_create_new_mapped_packet(
386 struct trace_ir_maps
*ir_maps
,
387 const bt_packet
*in_packet
)
389 struct trace_ir_data_maps
*d_maps
;
390 const bt_stream
*in_stream
;
391 const bt_trace
*in_trace
;
392 bt_packet
*out_packet
;
393 bt_stream
*out_stream
;
395 BT_COMP_LOGD("Creating new mapped packet: in-p-addr=%p", in_packet
);
397 in_stream
= bt_packet_borrow_stream_const(in_packet
);
398 in_trace
= bt_stream_borrow_trace_const(in_stream
);
399 d_maps
= borrow_data_maps_from_input_trace(ir_maps
, in_trace
);
401 /* There should never be a mapped packet already. */
402 BT_ASSERT(!borrow_mapped_packet(d_maps
, in_packet
));
403 BT_ASSERT(in_stream
);
405 /* Get output stream corresponding to this input stream. */
406 out_stream
= borrow_mapped_stream(d_maps
, in_stream
);
407 BT_ASSERT(out_stream
);
409 /* Create the output packet. */
410 out_packet
= bt_packet_create(out_stream
);
412 BT_COMP_LOGE_STR("Error create output packet");
416 /* Add it to the mapping. */
417 g_hash_table_insert(d_maps
->packet_map
,
418 (gpointer
) in_packet
, out_packet
);
420 /* Copy the content over to the output packet. */
421 copy_packet_content(in_packet
, out_packet
, ir_maps
->log_level
,
424 BT_COMP_LOGD("Created new mapped packet: in-p-addr=%p, out-p-addr=%p",
425 in_packet
, out_packet
);
432 bt_packet
*trace_ir_mapping_borrow_mapped_packet(struct trace_ir_maps
*ir_maps
,
433 const bt_packet
*in_packet
)
435 struct trace_ir_data_maps
*d_maps
;
436 BT_ASSERT_DBG(ir_maps
);
437 BT_ASSERT_DBG(in_packet
);
439 d_maps
= borrow_data_maps_from_input_packet(ir_maps
, in_packet
);
441 return borrow_mapped_packet(d_maps
, in_packet
);
445 void trace_ir_mapping_remove_mapped_packet(struct trace_ir_maps
*ir_maps
,
446 const bt_packet
*in_packet
)
448 struct trace_ir_data_maps
*d_maps
;
452 BT_ASSERT(in_packet
);
454 d_maps
= borrow_data_maps_from_input_packet(ir_maps
, in_packet
);
456 ret
= g_hash_table_remove(d_maps
->packet_map
, in_packet
);
462 void trace_ir_mapping_remove_mapped_stream(struct trace_ir_maps
*ir_maps
,
463 const bt_stream
*in_stream
)
465 struct trace_ir_data_maps
*d_maps
;
469 BT_ASSERT(in_stream
);
471 d_maps
= borrow_data_maps_from_input_stream(ir_maps
, in_stream
);
473 ret
= g_hash_table_remove(d_maps
->stream_map
, in_stream
);
479 void trace_ir_metadata_maps_remove_func(const bt_trace_class
*in_trace_class
,
482 struct trace_ir_maps
*maps
= (struct trace_ir_maps
*) data
;
483 if (maps
->metadata_maps
) {
485 ret
= g_hash_table_remove(maps
->metadata_maps
,
486 (gpointer
) in_trace_class
);
492 void trace_ir_data_maps_remove_func(const bt_trace
*in_trace
, void *data
)
494 struct trace_ir_maps
*maps
= (struct trace_ir_maps
*) data
;
495 if (maps
->data_maps
) {
497 ret
= g_hash_table_remove(maps
->data_maps
, (gpointer
) in_trace
);
502 struct trace_ir_data_maps
*trace_ir_data_maps_create(struct trace_ir_maps
*ir_maps
,
503 const bt_trace
*in_trace
)
505 bt_trace_add_listener_status add_listener_status
;
506 struct trace_ir_data_maps
*d_maps
= g_new0(struct trace_ir_data_maps
, 1);
509 BT_COMP_LOGE_STR("Error allocating trace_ir_maps");
513 d_maps
->log_level
= ir_maps
->log_level
;
514 d_maps
->self_comp
= ir_maps
->self_comp
;
515 d_maps
->input_trace
= in_trace
;
517 /* Create the hashtables used to map data objects. */
518 d_maps
->stream_map
= g_hash_table_new_full(g_direct_hash
,
519 g_direct_equal
, NULL
,(GDestroyNotify
) bt_stream_put_ref
);
520 d_maps
->packet_map
= g_hash_table_new_full(g_direct_hash
,
521 g_direct_equal
, NULL
,(GDestroyNotify
) bt_packet_put_ref
);
523 add_listener_status
= bt_trace_add_destruction_listener(
524 in_trace
, trace_ir_data_maps_remove_func
,
525 ir_maps
, &d_maps
->destruction_listener_id
);
526 BT_ASSERT(add_listener_status
== BT_TRACE_ADD_LISTENER_STATUS_OK
);
532 struct trace_ir_metadata_maps
*trace_ir_metadata_maps_create(
533 struct trace_ir_maps
*ir_maps
,
534 const bt_trace_class
*in_trace_class
)
536 bt_trace_class_add_listener_status add_listener_status
;
537 struct trace_ir_metadata_maps
*md_maps
=
538 g_new0(struct trace_ir_metadata_maps
, 1);
541 BT_COMP_LOGE_STR("Error allocating trace_ir_maps");
545 md_maps
->log_level
= ir_maps
->log_level
;
546 md_maps
->self_comp
= ir_maps
->self_comp
;
547 md_maps
->input_trace_class
= in_trace_class
;
549 * Create the field class resolving context. This is needed to keep
550 * track of the field class already copied in order to do the field
551 * path resolution correctly.
553 md_maps
->fc_resolving_ctx
=
554 g_new0(struct field_class_resolving_context
, 1);
555 if (!md_maps
->fc_resolving_ctx
) {
556 BT_COMP_LOGE_STR("Error allocating field_class_resolving_context");
560 /* Create the hashtables used to map metadata objects. */
561 md_maps
->stream_class_map
= g_hash_table_new_full(g_direct_hash
,
562 g_direct_equal
, NULL
, (GDestroyNotify
) bt_stream_class_put_ref
);
563 md_maps
->event_class_map
= g_hash_table_new_full(g_direct_hash
,
564 g_direct_equal
, NULL
, (GDestroyNotify
) bt_event_class_put_ref
);
565 md_maps
->field_class_map
= g_hash_table_new_full(g_direct_hash
,
566 g_direct_equal
, NULL
, (GDestroyNotify
) bt_field_class_put_ref
);
567 md_maps
->clock_class_map
= g_hash_table_new_full(g_direct_hash
,
568 g_direct_equal
, NULL
, (GDestroyNotify
) bt_clock_class_put_ref
);
570 add_listener_status
= bt_trace_class_add_destruction_listener(
571 in_trace_class
, trace_ir_metadata_maps_remove_func
,
572 ir_maps
, &md_maps
->destruction_listener_id
);
573 BT_ASSERT(add_listener_status
== BT_TRACE_CLASS_ADD_LISTENER_STATUS_OK
);
580 void trace_ir_data_maps_destroy(struct trace_ir_data_maps
*maps
)
582 bt_trace_remove_listener_status status
;
588 if (maps
->packet_map
) {
589 g_hash_table_destroy(maps
->packet_map
);
592 if (maps
->stream_map
) {
593 g_hash_table_destroy(maps
->stream_map
);
596 if (maps
->output_trace
) {
597 bt_trace_put_ref(maps
->output_trace
);
600 status
= bt_trace_remove_destruction_listener(maps
->input_trace
,
601 maps
->destruction_listener_id
);
602 if (status
!= BT_TRACE_REMOVE_LISTENER_STATUS_OK
) {
603 BT_COMP_LOG_CUR_LVL(BT_LOG_DEBUG
, maps
->log_level
,
605 "Trace destruction listener removal failed.");
606 bt_current_thread_clear_error();
613 void trace_ir_metadata_maps_destroy(struct trace_ir_metadata_maps
*maps
)
615 bt_trace_class_remove_listener_status status
;
621 if (maps
->stream_class_map
) {
622 g_hash_table_destroy(maps
->stream_class_map
);
625 if (maps
->event_class_map
) {
626 g_hash_table_destroy(maps
->event_class_map
);
629 if (maps
->field_class_map
) {
630 g_hash_table_destroy(maps
->field_class_map
);
633 if (maps
->clock_class_map
) {
634 g_hash_table_destroy(maps
->clock_class_map
);
637 g_free(maps
->fc_resolving_ctx
);
639 if (maps
->output_trace_class
) {
640 bt_trace_class_put_ref(maps
->output_trace_class
);
643 status
= bt_trace_class_remove_destruction_listener(
644 maps
->input_trace_class
, maps
->destruction_listener_id
);
645 if (status
!= BT_TRACE_CLASS_REMOVE_LISTENER_STATUS_OK
) {
646 BT_COMP_LOG_CUR_LVL(BT_LOG_DEBUG
, maps
->log_level
,
648 "Trace destruction listener removal failed.");
649 bt_current_thread_clear_error();
655 void trace_ir_maps_clear(struct trace_ir_maps
*maps
)
657 if (maps
->data_maps
) {
658 g_hash_table_remove_all(maps
->data_maps
);
661 if (maps
->metadata_maps
) {
662 g_hash_table_remove_all(maps
->metadata_maps
);
667 void trace_ir_maps_destroy(struct trace_ir_maps
*maps
)
673 g_free(maps
->debug_info_field_class_name
);
675 if (maps
->data_maps
) {
676 g_hash_table_destroy(maps
->data_maps
);
677 maps
->data_maps
= NULL
;
680 if (maps
->metadata_maps
) {
681 g_hash_table_destroy(maps
->metadata_maps
);
682 maps
->metadata_maps
= NULL
;
689 struct trace_ir_maps
*trace_ir_maps_create(bt_self_component
*self_comp
,
690 const char *debug_info_field_name
, bt_logging_level log_level
)
692 struct trace_ir_maps
*ir_maps
= g_new0(struct trace_ir_maps
, 1);
694 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, log_level
, self_comp
,
695 "Error allocating trace_ir_maps");
699 ir_maps
->log_level
= log_level
;
700 ir_maps
->self_comp
= self_comp
;
702 /* Copy debug info field name received from the user. */
703 ir_maps
->debug_info_field_class_name
= g_strdup(debug_info_field_name
);
704 if (!ir_maps
->debug_info_field_class_name
) {
705 BT_COMP_LOGE_STR("Cannot copy debug info field name");
709 ir_maps
->self_comp
= self_comp
;
711 ir_maps
->data_maps
= g_hash_table_new_full(g_direct_hash
,
712 g_direct_equal
, (GDestroyNotify
) NULL
,
713 (GDestroyNotify
) trace_ir_data_maps_destroy
);
715 ir_maps
->metadata_maps
= g_hash_table_new_full(g_direct_hash
,
716 g_direct_equal
, (GDestroyNotify
) NULL
,
717 (GDestroyNotify
) trace_ir_metadata_maps_destroy
);
721 trace_ir_maps_destroy(ir_maps
);