4 * Babeltrace library to create a copy of a CTF trace
6 * Copyright 2017 Julien Desfossez <jdesfossez@efficios.com>
8 * Author: Julien Desfossez <jdesfossez@efficios.com>
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 #define BT_LOG_TAG "PLUGIN-CTFCOPYTRACE-LIB"
32 #include <babeltrace/ctf-ir/event.h>
33 #include <babeltrace/ctf-ir/packet.h>
34 #include <babeltrace/ctf-ir/event-class.h>
35 #include <babeltrace/ctf-ir/stream.h>
36 #include <babeltrace/ctf-ir/stream-class.h>
37 #include <babeltrace/ctf-ir/clock-class.h>
38 #include <babeltrace/ctf-ir/fields.h>
39 #include <babeltrace/ctf-writer/stream.h>
42 #include "ctfcopytrace.h"
43 #include "clock-fields.h"
46 struct bt_ctf_clock_class
*ctf_copy_clock_class(FILE *err
,
47 struct bt_ctf_clock_class
*clock_class
)
49 int64_t offset
, offset_s
;
52 const char *name
, *description
;
53 struct bt_ctf_clock_class
*writer_clock_class
= NULL
;
55 assert(err
&& clock_class
);
57 name
= bt_ctf_clock_class_get_name(clock_class
);
60 writer_clock_class
= bt_ctf_clock_class_create(name
,
61 bt_ctf_clock_class_get_frequency(clock_class
));
62 if (!writer_clock_class
) {
63 BT_LOGE_STR("Failed to create clock class.");
67 description
= bt_ctf_clock_class_get_description(clock_class
);
69 int_ret
= bt_ctf_clock_class_set_description(writer_clock_class
,
74 u64_ret
= bt_ctf_clock_class_get_precision(clock_class
);
75 assert(u64_ret
!= -1ULL);
77 int_ret
= bt_ctf_clock_class_set_precision(writer_clock_class
,
81 int_ret
= bt_ctf_clock_class_get_offset_s(clock_class
, &offset_s
);
84 int_ret
= bt_ctf_clock_class_set_offset_s(writer_clock_class
, offset_s
);
87 int_ret
= bt_ctf_clock_class_get_offset_cycles(clock_class
, &offset
);
90 int_ret
= bt_ctf_clock_class_set_offset_cycles(writer_clock_class
, offset
);
93 int_ret
= bt_ctf_clock_class_is_absolute(clock_class
);
96 int_ret
= bt_ctf_clock_class_set_is_absolute(writer_clock_class
, int_ret
);
100 return writer_clock_class
;
104 enum bt_component_status
ctf_copy_clock_classes(FILE *err
,
105 struct bt_ctf_trace
*writer_trace
,
106 struct bt_ctf_stream_class
*writer_stream_class
,
107 struct bt_ctf_trace
*trace
)
109 enum bt_component_status ret
;
110 int int_ret
, clock_class_count
, i
;
112 clock_class_count
= bt_ctf_trace_get_clock_class_count(trace
);
114 for (i
= 0; i
< clock_class_count
; i
++) {
115 struct bt_ctf_clock_class
*writer_clock_class
;
116 struct bt_ctf_clock_class
*clock_class
=
117 bt_ctf_trace_get_clock_class_by_index(trace
, i
);
121 writer_clock_class
= ctf_copy_clock_class(err
, clock_class
);
123 if (!writer_clock_class
) {
124 BT_LOGE_STR("Failed to copy clock class.");
125 ret
= BT_COMPONENT_STATUS_ERROR
;
129 int_ret
= bt_ctf_trace_add_clock_class(writer_trace
, writer_clock_class
);
131 BT_PUT(writer_clock_class
);
132 BT_LOGE_STR("Failed to add clock class.");
133 ret
= BT_COMPONENT_STATUS_ERROR
;
138 * Ownership transferred to the trace.
140 bt_put(writer_clock_class
);
143 ret
= BT_COMPONENT_STATUS_OK
;
150 struct bt_ctf_event_class
*ctf_copy_event_class(FILE *err
,
151 struct bt_ctf_event_class
*event_class
)
153 struct bt_ctf_event_class
*writer_event_class
= NULL
;
154 struct bt_ctf_field_type
*context
, *payload_type
;
158 enum bt_ctf_event_class_log_level log_level
;
161 name
= bt_ctf_event_class_get_name(event_class
);
163 writer_event_class
= bt_ctf_event_class_create(name
);
164 assert(writer_event_class
);
166 id
= bt_ctf_event_class_get_id(event_class
);
169 ret
= bt_ctf_event_class_set_id(writer_event_class
, id
);
171 BT_LOGE_STR("Failed to set event_class id.");
175 log_level
= bt_ctf_event_class_get_log_level(event_class
);
177 BT_LOGE_STR("Failed to get log_level.");
181 ret
= bt_ctf_event_class_set_log_level(writer_event_class
, log_level
);
183 BT_LOGE_STR("Failed to set log_level.");
187 emf_uri
= bt_ctf_event_class_get_emf_uri(event_class
);
189 ret
= bt_ctf_event_class_set_emf_uri(writer_event_class
,
192 BT_LOGE_STR("Failed to set emf uri.");
197 payload_type
= bt_ctf_event_class_get_payload_type(event_class
);
199 ret
= bt_ctf_event_class_set_payload_type(writer_event_class
,
202 BT_LOGE_STR("Failed to set payload type.");
205 BT_PUT(payload_type
);
208 context
= bt_ctf_event_class_get_context_type(event_class
);
210 ret
= bt_ctf_event_class_set_context_type(
211 writer_event_class
, context
);
214 BT_LOGE_STR("Failed to set context type.");
222 BT_PUT(writer_event_class
);
224 return writer_event_class
;
228 enum bt_component_status
ctf_copy_event_classes(FILE *err
,
229 struct bt_ctf_stream_class
*stream_class
,
230 struct bt_ctf_stream_class
*writer_stream_class
)
232 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
233 struct bt_ctf_event_class
*event_class
= NULL
, *writer_event_class
= NULL
;
236 count
= bt_ctf_stream_class_get_event_class_count(stream_class
);
239 for (i
= 0; i
< count
; i
++) {
242 event_class
= bt_ctf_stream_class_get_event_class_by_index(
246 if (i
< bt_ctf_stream_class_get_event_class_count(writer_stream_class
)) {
247 writer_event_class
= bt_ctf_stream_class_get_event_class_by_index(
248 writer_stream_class
, i
);
249 if (writer_event_class
) {
251 * If the writer_event_class already exists,
252 * just skip it. It can be used to resync the
253 * event_classes after a trace has become
256 BT_PUT(writer_event_class
);
262 writer_event_class
= ctf_copy_event_class(err
, event_class
);
263 if (!writer_event_class
) {
264 BT_LOGE_STR("Failed to copy event_class.");
265 ret
= BT_COMPONENT_STATUS_ERROR
;
269 int_ret
= bt_ctf_stream_class_add_event_class(writer_stream_class
,
272 BT_LOGE_STR("Failed to add event class.");
273 ret
= BT_COMPONENT_STATUS_ERROR
;
276 BT_PUT(writer_event_class
);
284 bt_put(writer_event_class
);
290 struct bt_ctf_stream_class
*ctf_copy_stream_class(FILE *err
,
291 struct bt_ctf_stream_class
*stream_class
,
292 struct bt_ctf_trace
*writer_trace
,
295 struct bt_ctf_field_type
*type
= NULL
;
296 struct bt_ctf_stream_class
*writer_stream_class
= NULL
;
298 const char *name
= bt_ctf_stream_class_get_name(stream_class
);
300 writer_stream_class
= bt_ctf_stream_class_create_empty(name
);
301 assert(writer_stream_class
);
303 type
= bt_ctf_stream_class_get_packet_context_type(stream_class
);
305 ret_int
= bt_ctf_stream_class_set_packet_context_type(
306 writer_stream_class
, type
);
308 BT_LOGE_STR("Failed to set packet_context type.");
314 type
= bt_ctf_stream_class_get_event_header_type(stream_class
);
316 ret_int
= bt_ctf_trace_get_clock_class_count(writer_trace
);
317 assert(ret_int
>= 0);
318 if (override_ts64
&& ret_int
> 0) {
319 struct bt_ctf_field_type
*new_event_header_type
;
321 new_event_header_type
= override_header_type(err
, type
,
323 if (!new_event_header_type
) {
324 BT_LOGE_STR("Failed to override header type.");
327 ret_int
= bt_ctf_stream_class_set_event_header_type(
328 writer_stream_class
, new_event_header_type
);
329 BT_PUT(new_event_header_type
);
331 BT_LOGE_STR("Failed to set event_header type.");
335 ret_int
= bt_ctf_stream_class_set_event_header_type(
336 writer_stream_class
, type
);
338 BT_LOGE_STR("Failed to set event_header type.");
345 type
= bt_ctf_stream_class_get_event_context_type(stream_class
);
347 ret_int
= bt_ctf_stream_class_set_event_context_type(
348 writer_stream_class
, type
);
350 BT_LOGE_STR("Failed to set event_contexttype.");
359 BT_PUT(writer_stream_class
);
362 return writer_stream_class
;
366 int ctf_stream_copy_packet_header(FILE *err
, struct bt_ctf_packet
*packet
,
367 struct bt_ctf_stream
*writer_stream
)
369 struct bt_ctf_field
*packet_header
= NULL
, *writer_packet_header
= NULL
;
372 packet_header
= bt_ctf_packet_get_header(packet
);
373 if (!packet_header
) {
377 writer_packet_header
= bt_ctf_field_copy(packet_header
);
378 if (!writer_packet_header
) {
379 BT_LOGE_STR("Failed to copy field from stream packet header.");
383 ret
= bt_ctf_stream_set_packet_header(writer_stream
,
384 writer_packet_header
);
386 BT_LOGE_STR("Failed to set stream packet header.");
395 bt_put(writer_packet_header
);
396 bt_put(packet_header
);
401 int ctf_packet_copy_header(FILE *err
, struct bt_ctf_packet
*packet
,
402 struct bt_ctf_packet
*writer_packet
)
404 struct bt_ctf_field
*packet_header
= NULL
, *writer_packet_header
= NULL
;
407 packet_header
= bt_ctf_packet_get_header(packet
);
408 if (!packet_header
) {
412 writer_packet_header
= bt_ctf_field_copy(packet_header
);
413 if (!writer_packet_header
) {
414 BT_LOGE_STR("Failed to copy field from packet header.");
418 ret
= bt_ctf_packet_set_header(writer_packet
, writer_packet_header
);
420 BT_LOGE_STR("Failed to set packet header.");
429 bt_put(packet_header
);
430 bt_put(writer_packet_header
);
435 int ctf_stream_copy_packet_context(FILE *err
, struct bt_ctf_packet
*packet
,
436 struct bt_ctf_stream
*writer_stream
)
438 struct bt_ctf_field
*packet_context
= NULL
, *writer_packet_context
= NULL
;
441 packet_context
= bt_ctf_packet_get_context(packet
);
442 if (!packet_context
) {
446 writer_packet_context
= bt_ctf_field_copy(packet_context
);
447 if (!writer_packet_context
) {
448 BT_LOGE_STR("Failed to copy field from stream packet context.");
452 ret
= bt_ctf_stream_set_packet_context(writer_stream
,
453 writer_packet_context
);
455 BT_LOGE_STR("Failed to set stream packet context.");
464 bt_put(packet_context
);
465 bt_put(writer_packet_context
);
470 int ctf_packet_copy_context(FILE *err
, struct bt_ctf_packet
*packet
,
471 struct bt_ctf_stream
*writer_stream
,
472 struct bt_ctf_packet
*writer_packet
)
474 struct bt_ctf_field
*packet_context
= NULL
, *writer_packet_context
= NULL
;
477 packet_context
= bt_ctf_packet_get_context(packet
);
478 if (!packet_context
) {
482 writer_packet_context
= bt_ctf_field_copy(packet_context
);
483 if (!writer_packet_context
) {
484 BT_LOGE_STR("Failed to copy field from packet context.");
488 ret
= bt_ctf_packet_set_context(writer_packet
, writer_packet_context
);
490 BT_LOGE_STR("Failed to set packet context.");
499 bt_put(writer_packet_context
);
500 bt_put(packet_context
);
505 int ctf_copy_event_header(FILE *err
, struct bt_ctf_event
*event
,
506 struct bt_ctf_event_class
*writer_event_class
,
507 struct bt_ctf_event
*writer_event
,
508 struct bt_ctf_field
*event_header
)
510 struct bt_ctf_clock_class
*clock_class
= NULL
, *writer_clock_class
= NULL
;
511 struct bt_ctf_clock_value
*clock_value
= NULL
, *writer_clock_value
= NULL
;
514 struct bt_ctf_field
*writer_event_header
= NULL
;
517 clock_class
= event_get_clock_class(err
, event
);
519 BT_LOGE_STR("Failed to get event clock_class.");
523 clock_value
= bt_ctf_event_get_clock_value(event
, clock_class
);
527 ret
= bt_ctf_clock_value_get_value(clock_value
, &value
);
530 BT_LOGE_STR("Failed to get clock value.");
534 writer_clock_class
= event_get_clock_class(err
, writer_event
);
535 if (!writer_clock_class
) {
536 BT_LOGE_STR("Failed to get event clock_class.");
540 writer_clock_value
= bt_ctf_clock_value_create(writer_clock_class
, value
);
541 BT_PUT(writer_clock_class
);
542 if (!writer_clock_value
) {
543 BT_LOGE_STR("Failed to create clock value.");
547 ret
= bt_ctf_event_set_clock_value(writer_event
, writer_clock_value
);
548 BT_PUT(writer_clock_value
);
550 BT_LOGE_STR("Failed to set clock value.");
554 writer_event_header
= bt_ctf_field_copy(event_header
);
555 if (!writer_event_header
) {
556 BT_LOGE_STR("Failed to copy event_header.");
560 ret
= bt_ctf_event_set_header(writer_event
, writer_event_header
);
561 BT_PUT(writer_event_header
);
563 BT_LOGE_STR("Failed to set event_header.");
578 struct bt_ctf_trace
*event_class_get_trace(FILE *err
,
579 struct bt_ctf_event_class
*event_class
)
581 struct bt_ctf_trace
*trace
= NULL
;
582 struct bt_ctf_stream_class
*stream_class
= NULL
;
584 stream_class
= bt_ctf_event_class_get_stream_class(event_class
);
585 assert(stream_class
);
587 trace
= bt_ctf_stream_class_get_trace(stream_class
);
590 bt_put(stream_class
);
595 struct bt_ctf_event
*ctf_copy_event(FILE *err
, struct bt_ctf_event
*event
,
596 struct bt_ctf_event_class
*writer_event_class
,
599 struct bt_ctf_event
*writer_event
= NULL
;
600 struct bt_ctf_field
*field
= NULL
, *copy_field
= NULL
;
601 struct bt_ctf_trace
*writer_trace
= NULL
;
604 writer_event
= bt_ctf_event_create(writer_event_class
);
606 BT_LOGE_STR("Failed to create event.");
610 writer_trace
= event_class_get_trace(err
, writer_event_class
);
612 BT_LOGE_STR("Failed to get trace from event_class.");
616 field
= bt_ctf_event_get_header(event
);
619 * If override_ts64, we override all integer fields mapped to a
620 * clock to a uint64_t field type, otherwise, we just copy it as
623 ret
= bt_ctf_trace_get_clock_class_count(writer_trace
);
626 if (override_ts64
&& ret
> 0) {
627 copy_field
= bt_ctf_event_get_header(writer_event
);
630 ret
= copy_override_field(err
, event
, writer_event
, field
,
633 BT_LOGE_STR("Failed to copy and override field.");
638 ret
= ctf_copy_event_header(err
, event
, writer_event_class
,
639 writer_event
, field
);
641 BT_LOGE_STR("Failed to copy event_header.");
648 /* Optional field, so it can fail silently. */
649 field
= bt_ctf_event_get_stream_event_context(event
);
651 copy_field
= bt_ctf_field_copy(field
);
653 BT_LOGE_STR("Failed to copy field.");
656 ret
= bt_ctf_event_set_stream_event_context(writer_event
,
659 BT_LOGE_STR("Failed to set stream_event_context.");
666 /* Optional field, so it can fail silently. */
667 field
= bt_ctf_event_get_event_context(event
);
669 copy_field
= bt_ctf_field_copy(field
);
671 BT_LOGE_STR("Failed to copy field.");
674 ret
= bt_ctf_event_set_event_context(writer_event
, copy_field
);
676 BT_LOGE_STR("Failed to set event_context.");
683 field
= bt_ctf_event_get_event_payload(event
);
685 copy_field
= bt_ctf_field_copy(field
);
687 BT_LOGE_STR("Failed to copy field.");
690 ret
= bt_ctf_event_set_event_payload(writer_event
, copy_field
);
692 BT_LOGE_STR("Failed to set event_payload.");
702 BT_PUT(writer_event
);
706 bt_put(writer_trace
);
711 enum bt_component_status
ctf_copy_trace(FILE *err
, struct bt_ctf_trace
*trace
,
712 struct bt_ctf_trace
*writer_trace
)
714 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
715 int field_count
, i
, int_ret
;
716 struct bt_ctf_field_type
*header_type
= NULL
;
717 enum bt_ctf_byte_order order
;
718 const char *trace_name
;
719 const unsigned char *trace_uuid
;
721 field_count
= bt_ctf_trace_get_environment_field_count(trace
);
722 for (i
= 0; i
< field_count
; i
++) {
725 struct bt_value
*value
= NULL
;
727 name
= bt_ctf_trace_get_environment_field_name_by_index(
731 value
= bt_ctf_trace_get_environment_field_value_by_index(
735 ret_int
= bt_ctf_trace_set_environment_field(writer_trace
,
739 BT_LOGE("Failed to set environment: field-name=\"%s\"",
741 ret
= BT_COMPONENT_STATUS_ERROR
;
746 order
= bt_ctf_trace_get_native_byte_order(trace
);
747 assert(order
!= BT_CTF_BYTE_ORDER_UNKNOWN
);
750 * Only explicitly set the writer trace's native byte order if
751 * the original trace has a specific one. Otherwise leave what
752 * the CTF writer object chooses, which is the machine's native
755 if (order
!= BT_CTF_BYTE_ORDER_UNSPECIFIED
) {
756 ret
= bt_ctf_trace_set_native_byte_order(writer_trace
, order
);
758 BT_LOGE_STR("Failed to set native byte order.");
759 ret
= BT_COMPONENT_STATUS_ERROR
;
764 header_type
= bt_ctf_trace_get_packet_header_type(trace
);
766 int_ret
= bt_ctf_trace_set_packet_header_type(writer_trace
, header_type
);
769 BT_LOGE_STR("Failed to set packet header type.");
770 ret
= BT_COMPONENT_STATUS_ERROR
;
775 trace_name
= bt_ctf_trace_get_name(trace
);
777 int_ret
= bt_ctf_trace_set_name(writer_trace
, trace_name
);
779 BT_LOGE_STR("Failed to set trace name.");
780 ret
= BT_COMPONENT_STATUS_ERROR
;
785 trace_uuid
= bt_ctf_trace_get_uuid(trace
);
787 int_ret
= bt_ctf_trace_set_uuid(writer_trace
, trace_uuid
);
789 BT_LOGE_STR("Failed to set trace UUID.");
790 ret
= BT_COMPONENT_STATUS_ERROR
;