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 <babeltrace/assert-internal.h>
34 #include <babeltrace/babeltrace.h>
35 /* For bt_property_availability */
36 #include <babeltrace/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 if (bt_stream_class_default_clock_is_always_known(in_stream_class
)
217 BT_LOGE("Stream class default clock class is not always "
218 "known: in-sc-addr=%p", in_stream_class
);
222 md_maps
= borrow_metadata_maps_from_input_stream_class(ir_maps
, in_stream_class
);
223 out_stream_class
= borrow_mapped_stream_class(md_maps
, in_stream_class
);
224 if (!out_stream_class
) {
225 out_stream_class
= create_new_mapped_stream_class(ir_maps
,
227 if (!out_stream_class
) {
231 BT_ASSERT(out_stream_class
);
233 out_stream
= bt_stream_create_with_id(out_stream_class
,
234 d_maps
->output_trace
, bt_stream_get_id(in_stream
));
236 BT_LOGE_STR("Error creating output stream");
240 * Release our ref since the trace object will be managing the life
241 * time of the stream objects.
244 copy_stream_content(in_stream
, out_stream
);
246 g_hash_table_insert(d_maps
->stream_map
, (gpointer
) in_stream
,
249 BT_LOGD("Created new mapped stream: in-s-addr=%p, out-s-addr=%p",
250 in_stream
, out_stream
);
257 bt_stream
*trace_ir_mapping_borrow_mapped_stream(struct trace_ir_maps
*ir_maps
,
258 const bt_stream
*in_stream
)
261 BT_ASSERT(in_stream
);
262 struct trace_ir_data_maps
*d_maps
;
264 d_maps
= borrow_data_maps_from_input_stream(ir_maps
, in_stream
);
265 /* Return the mapped stream. */
266 return borrow_mapped_stream(d_maps
, in_stream
);
270 bt_event_class
*borrow_mapped_event_class(struct trace_ir_metadata_maps
*md_maps
,
271 const bt_event_class
*in_event_class
)
273 return g_hash_table_lookup(md_maps
->event_class_map
,
274 (gpointer
) in_event_class
);
278 bt_event_class
*trace_ir_mapping_create_new_mapped_event_class(
279 struct trace_ir_maps
*ir_maps
,
280 const bt_event_class
*in_event_class
)
282 bt_event_class
*out_event_class
;
283 const bt_trace_class
*in_trace_class
;
284 const bt_stream_class
*in_stream_class
;
285 bt_stream_class
*out_stream_class
;
286 struct trace_ir_metadata_maps
*md_maps
;
289 BT_LOGD("Creating new mapped event class: in-ec-addr=%p",
293 BT_ASSERT(in_event_class
);
295 in_trace_class
= bt_stream_class_borrow_trace_class_const(
296 bt_event_class_borrow_stream_class_const(
299 md_maps
= borrow_metadata_maps_from_input_trace_class(ir_maps
, in_trace_class
);
301 BT_ASSERT(!borrow_mapped_event_class(md_maps
, in_event_class
));
304 bt_event_class_borrow_stream_class_const(in_event_class
);
305 BT_ASSERT(in_stream_class
);
307 /* Get the right output stream class to add the new event class to. */
308 out_stream_class
= borrow_mapped_stream_class(md_maps
, in_stream_class
);
309 BT_ASSERT(out_stream_class
);
311 /* Create an output event class. */
312 out_event_class
= bt_event_class_create_with_id(out_stream_class
,
313 bt_event_class_get_id(in_event_class
));
314 if (!out_event_class
) {
315 BT_LOGE_STR("Error creating output event class");
319 /* If not, create a new one and add it to the mapping. */
320 ret
= copy_event_class_content(ir_maps
, in_event_class
,
323 BT_LOGE_STR("Error copy content to output event class");
324 out_event_class
= NULL
;
328 g_hash_table_insert(md_maps
->event_class_map
,
329 (gpointer
) in_event_class
, out_event_class
);
331 BT_LOGD("Created new mapped event class: in-ec-addr=%p, out-ec-addr=%p",
332 in_event_class
, out_event_class
);
335 return out_event_class
;
339 bt_event_class
*trace_ir_mapping_borrow_mapped_event_class(
340 struct trace_ir_maps
*ir_maps
,
341 const bt_event_class
*in_event_class
)
343 struct trace_ir_metadata_maps
*md_maps
;
346 BT_ASSERT(in_event_class
);
348 md_maps
= borrow_metadata_maps_from_input_event_class(ir_maps
, in_event_class
);
350 /* Return the mapped event_class. */
351 return borrow_mapped_event_class(md_maps
, in_event_class
);
355 bt_packet
*borrow_mapped_packet(struct trace_ir_data_maps
*d_maps
,
356 const bt_packet
*in_packet
)
359 BT_ASSERT(in_packet
);
361 return g_hash_table_lookup(d_maps
->packet_map
,
362 (gpointer
) in_packet
);
366 bt_packet
*trace_ir_mapping_create_new_mapped_packet(
367 struct trace_ir_maps
*ir_maps
,
368 const bt_packet
*in_packet
)
370 struct trace_ir_data_maps
*d_maps
;
371 const bt_trace
*in_trace
;
372 const bt_stream
*in_stream
;
373 bt_packet
*out_packet
;
374 bt_stream
*out_stream
;
376 BT_LOGD("Creating new mapped packet: in-p-addr=%p", in_packet
);
378 in_stream
= bt_packet_borrow_stream_const(in_packet
);
379 in_trace
= bt_stream_borrow_trace_const(in_stream
);
380 d_maps
= borrow_data_maps_from_input_trace(ir_maps
, in_trace
);
382 /* There should never be a mapped packet. */
383 BT_ASSERT(!borrow_mapped_packet(d_maps
, in_packet
));
385 BT_ASSERT(in_stream
);
387 /* Get output stream corresponding to this input stream. */
388 out_stream
= borrow_mapped_stream(d_maps
, in_stream
);
389 BT_ASSERT(out_stream
);
391 /* Create the output packet. */
392 out_packet
= bt_packet_create(out_stream
);
394 BT_LOGE_STR("Error create output packet");
399 * Release our ref since the stream object will be managing the life
400 * time of the packet objects.
402 copy_packet_content(in_packet
, out_packet
);
404 g_hash_table_insert(d_maps
->packet_map
,
405 (gpointer
) in_packet
, out_packet
);
407 BT_LOGD("Created new mapped packet: in-p-addr=%p, out-p-addr=%p",
408 in_packet
, out_packet
);
415 bt_packet
*trace_ir_mapping_borrow_mapped_packet(struct trace_ir_maps
*ir_maps
,
416 const bt_packet
*in_packet
)
418 struct trace_ir_data_maps
*d_maps
;
420 BT_ASSERT(in_packet
);
422 d_maps
= borrow_data_maps_from_input_packet(ir_maps
, in_packet
);
424 return borrow_mapped_packet(d_maps
, in_packet
);
428 void trace_ir_mapping_remove_mapped_packet(struct trace_ir_maps
*ir_maps
,
429 const bt_packet
*in_packet
)
433 struct trace_ir_data_maps
*d_maps
;
435 BT_ASSERT(in_packet
);
437 d_maps
= borrow_data_maps_from_input_packet(ir_maps
, in_packet
);
439 ret
= g_hash_table_remove(d_maps
->packet_map
, in_packet
);
445 void trace_ir_mapping_remove_mapped_stream(struct trace_ir_maps
*ir_maps
,
446 const bt_stream
*in_stream
)
449 struct trace_ir_data_maps
*d_maps
;
452 BT_ASSERT(in_stream
);
454 d_maps
= borrow_data_maps_from_input_stream(ir_maps
, in_stream
);
456 ret
= g_hash_table_remove(d_maps
->stream_map
, in_stream
);
462 void trace_ir_metadata_maps_remove_func(const bt_trace_class
*in_trace_class
,
465 struct trace_ir_maps
*maps
= (struct trace_ir_maps
*) data
;
466 if (maps
->metadata_maps
) {
468 ret
= g_hash_table_remove(maps
->metadata_maps
,
469 (gpointer
) in_trace_class
);
475 void trace_ir_data_maps_remove_func(const bt_trace
*in_trace
, void *data
)
477 struct trace_ir_maps
*maps
= (struct trace_ir_maps
*) data
;
478 if (maps
->data_maps
) {
480 ret
= g_hash_table_remove(maps
->data_maps
, (gpointer
) in_trace
);
485 struct trace_ir_data_maps
*trace_ir_data_maps_create(struct trace_ir_maps
*ir_maps
,
486 const bt_trace
*in_trace
)
488 struct trace_ir_data_maps
*d_maps
=
489 g_new0(struct trace_ir_data_maps
, 1);
491 BT_LOGE_STR("Error allocating trace_ir_maps");
495 d_maps
->input_trace
= in_trace
;
497 /* Create the hashtables used to map data objects. */
498 d_maps
->stream_map
= g_hash_table_new_full(g_direct_hash
,
499 g_direct_equal
, NULL
,(GDestroyNotify
) bt_stream_put_ref
);
500 d_maps
->packet_map
= g_hash_table_new_full(g_direct_hash
,
501 g_direct_equal
, NULL
,(GDestroyNotify
) bt_packet_put_ref
);
503 bt_trace_add_destruction_listener(in_trace
, trace_ir_data_maps_remove_func
,
504 ir_maps
, &d_maps
->destruction_listener_id
);
509 struct trace_ir_metadata_maps
*trace_ir_metadata_maps_create(
510 struct trace_ir_maps
*ir_maps
,
511 const bt_trace_class
*in_trace_class
)
513 struct trace_ir_metadata_maps
*md_maps
=
514 g_new0(struct trace_ir_metadata_maps
, 1);
516 BT_LOGE_STR("Error allocating trace_ir_maps");
520 md_maps
->input_trace_class
= in_trace_class
;
522 * Create the field class resolving context. This is needed to keep
523 * track of the field class already copied in order to do the field
524 * path resolution correctly.
526 md_maps
->fc_resolving_ctx
=
527 g_new0(struct field_class_resolving_context
, 1);
528 if (!md_maps
->fc_resolving_ctx
) {
529 BT_LOGE_STR("Error allocating field_class_resolving_context");
533 /* Create the hashtables used to map metadata objects. */
534 md_maps
->stream_class_map
= g_hash_table_new_full(g_direct_hash
,
535 g_direct_equal
, NULL
, (GDestroyNotify
) bt_stream_class_put_ref
);
536 md_maps
->event_class_map
= g_hash_table_new_full(g_direct_hash
,
537 g_direct_equal
, NULL
, (GDestroyNotify
) bt_event_class_put_ref
);
538 md_maps
->field_class_map
= g_hash_table_new_full(g_direct_hash
,
539 g_direct_equal
, NULL
, (GDestroyNotify
) bt_field_class_put_ref
);
540 md_maps
->clock_class_map
= g_hash_table_new_full(g_direct_hash
,
541 g_direct_equal
, NULL
, (GDestroyNotify
) bt_clock_class_put_ref
);
543 bt_trace_class_add_destruction_listener(in_trace_class
,
544 trace_ir_metadata_maps_remove_func
,
545 ir_maps
, &md_maps
->destruction_listener_id
);
551 void trace_ir_data_maps_destroy(struct trace_ir_data_maps
*maps
)
553 bt_trace_status status
;
558 if (maps
->packet_map
) {
559 g_hash_table_destroy(maps
->packet_map
);
562 if (maps
->stream_map
) {
563 g_hash_table_destroy(maps
->stream_map
);
566 if (maps
->output_trace
) {
567 bt_trace_put_ref(maps
->output_trace
);
570 status
= bt_trace_remove_destruction_listener(maps
->input_trace
,
571 maps
->destruction_listener_id
);
572 if (status
!= BT_TRACE_STATUS_OK
) {
573 BT_LOGD("Trace destruction listener removal failed.");
580 void trace_ir_metadata_maps_destroy(struct trace_ir_metadata_maps
*maps
)
582 bt_trace_class_status status
;
587 if (maps
->stream_class_map
) {
588 g_hash_table_destroy(maps
->stream_class_map
);
591 if (maps
->event_class_map
) {
592 g_hash_table_destroy(maps
->event_class_map
);
595 if (maps
->field_class_map
) {
596 g_hash_table_destroy(maps
->field_class_map
);
599 if (maps
->clock_class_map
) {
600 g_hash_table_destroy(maps
->clock_class_map
);
603 if (maps
->fc_resolving_ctx
) {
604 g_free(maps
->fc_resolving_ctx
);
607 if (maps
->output_trace_class
) {
608 bt_trace_class_put_ref(maps
->output_trace_class
);
611 status
= bt_trace_class_remove_destruction_listener(maps
->input_trace_class
,
612 maps
->destruction_listener_id
);
613 if (status
!= BT_TRACE_CLASS_STATUS_OK
) {
614 BT_LOGD("Trace destruction listener removal failed.");
620 void trace_ir_maps_clear(struct trace_ir_maps
*maps
)
622 if (maps
->data_maps
) {
623 g_hash_table_remove_all(maps
->data_maps
);
626 if (maps
->metadata_maps
) {
627 g_hash_table_remove_all(maps
->metadata_maps
);
632 void trace_ir_maps_destroy(struct trace_ir_maps
*maps
)
638 if (maps
->debug_info_field_class_name
) {
639 g_free(maps
->debug_info_field_class_name
);
642 if (maps
->data_maps
) {
643 g_hash_table_destroy(maps
->data_maps
);
644 maps
->data_maps
= NULL
;
647 if (maps
->metadata_maps
) {
648 g_hash_table_destroy(maps
->metadata_maps
);
649 maps
->metadata_maps
= NULL
;
656 struct trace_ir_maps
*trace_ir_maps_create(bt_self_component
*self_comp
,
657 const char *debug_info_field_name
)
659 struct trace_ir_maps
*trace_ir_maps
=
660 g_new0(struct trace_ir_maps
, 1);
661 if (!trace_ir_maps
) {
662 BT_LOGE_STR("Error allocating trace_ir_maps");
666 /* Copy debug info field name received from the user. */
667 trace_ir_maps
->debug_info_field_class_name
=
668 g_strdup(debug_info_field_name
);
669 if (!trace_ir_maps
->debug_info_field_class_name
) {
670 BT_LOGE_STR("Cannot copy debug info field name");
674 trace_ir_maps
->self_comp
= self_comp
;
676 trace_ir_maps
->data_maps
= g_hash_table_new_full(g_direct_hash
,
677 g_direct_equal
, (GDestroyNotify
) NULL
,
678 (GDestroyNotify
) trace_ir_data_maps_destroy
);
680 trace_ir_maps
->metadata_maps
= g_hash_table_new_full(g_direct_hash
,
681 g_direct_equal
, (GDestroyNotify
) NULL
,
682 (GDestroyNotify
) trace_ir_metadata_maps_destroy
);
686 trace_ir_maps_destroy(trace_ir_maps
);
687 trace_ir_maps
= NULL
;
689 return trace_ir_maps
;