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 #include <babeltrace/ctf-ir/event.h>
30 #include <babeltrace/ctf-ir/packet.h>
31 #include <babeltrace/ctf-ir/event-class.h>
32 #include <babeltrace/ctf-ir/stream.h>
33 #include <babeltrace/ctf-ir/stream-class.h>
34 #include <babeltrace/ctf-ir/clock-class.h>
35 #include <babeltrace/ctf-ir/fields.h>
36 #include <babeltrace/ctf-writer/stream.h>
39 #include "ctfcopytrace.h"
40 #include "clock-fields.h"
43 struct bt_ctf_clock_class
*ctf_copy_clock_class(FILE *err
,
44 struct bt_ctf_clock_class
*clock_class
)
46 int64_t offset
, offset_s
;
49 const char *name
, *description
;
50 struct bt_ctf_clock_class
*writer_clock_class
= NULL
;
52 assert(err
&& clock_class
);
54 name
= bt_ctf_clock_class_get_name(clock_class
);
56 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
61 writer_clock_class
= bt_ctf_clock_class_create(name
,
62 bt_ctf_clock_class_get_frequency(clock_class
));
63 if (!writer_clock_class
) {
64 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
69 description
= bt_ctf_clock_class_get_description(clock_class
);
71 int_ret
= bt_ctf_clock_class_set_description(writer_clock_class
,
74 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
80 u64_ret
= bt_ctf_clock_class_get_precision(clock_class
);
81 if (u64_ret
== -1ULL) {
82 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
86 int_ret
= bt_ctf_clock_class_set_precision(writer_clock_class
,
89 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
94 int_ret
= bt_ctf_clock_class_get_offset_s(clock_class
, &offset_s
);
96 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
101 int_ret
= bt_ctf_clock_class_set_offset_s(writer_clock_class
, offset_s
);
103 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
108 int_ret
= bt_ctf_clock_class_get_offset_cycles(clock_class
, &offset
);
110 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
115 int_ret
= bt_ctf_clock_class_set_offset_cycles(writer_clock_class
, offset
);
117 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
122 int_ret
= bt_ctf_clock_class_is_absolute(clock_class
);
124 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
129 int_ret
= bt_ctf_clock_class_set_is_absolute(writer_clock_class
, int_ret
);
131 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
139 BT_PUT(writer_clock_class
);
141 return writer_clock_class
;
145 enum bt_component_status
ctf_copy_clock_classes(FILE *err
,
146 struct bt_ctf_trace
*writer_trace
,
147 struct bt_ctf_stream_class
*writer_stream_class
,
148 struct bt_ctf_trace
*trace
)
150 enum bt_component_status ret
;
151 int int_ret
, clock_class_count
, i
;
153 clock_class_count
= bt_ctf_trace_get_clock_class_count(trace
);
155 for (i
= 0; i
< clock_class_count
; i
++) {
156 struct bt_ctf_clock_class
*writer_clock_class
;
157 struct bt_ctf_clock_class
*clock_class
=
158 bt_ctf_trace_get_clock_class_by_index(trace
, i
);
161 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
163 ret
= BT_COMPONENT_STATUS_ERROR
;
167 writer_clock_class
= ctf_copy_clock_class(err
, clock_class
);
169 if (!writer_clock_class
) {
170 fprintf(err
, "Failed to copy clock class");
171 ret
= BT_COMPONENT_STATUS_ERROR
;
175 int_ret
= bt_ctf_trace_add_clock_class(writer_trace
, writer_clock_class
);
177 BT_PUT(writer_clock_class
);
178 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
180 ret
= BT_COMPONENT_STATUS_ERROR
;
185 * Ownership transferred to the trace.
187 bt_put(writer_clock_class
);
190 ret
= BT_COMPONENT_STATUS_OK
;
197 struct bt_ctf_event_class
*ctf_copy_event_class(FILE *err
,
198 struct bt_ctf_event_class
*event_class
)
200 struct bt_ctf_event_class
*writer_event_class
= NULL
;
201 struct bt_ctf_field_type
*context
, *payload_type
;
205 enum bt_ctf_event_class_log_level log_level
;
208 name
= bt_ctf_event_class_get_name(event_class
);
210 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
215 writer_event_class
= bt_ctf_event_class_create(name
);
216 if (!writer_event_class
) {
217 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
222 id
= bt_ctf_event_class_get_id(event_class
);
224 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
229 ret
= bt_ctf_event_class_set_id(writer_event_class
, id
);
231 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
236 log_level
= bt_ctf_event_class_get_log_level(event_class
);
238 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
243 ret
= bt_ctf_event_class_set_log_level(writer_event_class
, log_level
);
245 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
250 emf_uri
= bt_ctf_event_class_get_emf_uri(event_class
);
252 ret
= bt_ctf_event_class_set_emf_uri(writer_event_class
,
255 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
261 payload_type
= bt_ctf_event_class_get_payload_type(event_class
);
263 ret
= bt_ctf_event_class_set_payload_type(writer_event_class
,
266 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
270 BT_PUT(payload_type
);
273 context
= bt_ctf_event_class_get_context_type(event_class
);
275 ret
= bt_ctf_event_class_set_context_type(
276 writer_event_class
, context
);
279 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
288 BT_PUT(writer_event_class
);
290 return writer_event_class
;
294 enum bt_component_status
ctf_copy_event_classes(FILE *err
,
295 struct bt_ctf_stream_class
*stream_class
,
296 struct bt_ctf_stream_class
*writer_stream_class
)
298 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
299 struct bt_ctf_event_class
*event_class
= NULL
, *writer_event_class
= NULL
;
302 count
= bt_ctf_stream_class_get_event_class_count(stream_class
);
304 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
309 for (i
= 0; i
< count
; i
++) {
312 event_class
= bt_ctf_stream_class_get_event_class_by_index(
315 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
317 ret
= BT_COMPONENT_STATUS_ERROR
;
320 if (i
< bt_ctf_stream_class_get_event_class_count(writer_stream_class
)) {
321 writer_event_class
= bt_ctf_stream_class_get_event_class_by_index(
322 writer_stream_class
, i
);
323 if (writer_event_class
) {
325 * If the writer_event_class already exists,
326 * just skip it. It can be used to resync the
327 * event_classes after a trace has become
330 BT_PUT(writer_event_class
);
336 writer_event_class
= ctf_copy_event_class(err
, event_class
);
337 if (!writer_event_class
) {
338 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
340 ret
= BT_COMPONENT_STATUS_ERROR
;
344 int_ret
= bt_ctf_stream_class_add_event_class(writer_stream_class
,
347 fprintf(err
, "[error] Failed to add event class\n");
348 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
350 ret
= BT_COMPONENT_STATUS_ERROR
;
353 BT_PUT(writer_event_class
);
361 bt_put(writer_event_class
);
367 struct bt_ctf_stream_class
*ctf_copy_stream_class(FILE *err
,
368 struct bt_ctf_stream_class
*stream_class
,
369 struct bt_ctf_trace
*writer_trace
,
372 struct bt_ctf_field_type
*type
= NULL
;
373 struct bt_ctf_stream_class
*writer_stream_class
= NULL
;
375 const char *name
= bt_ctf_stream_class_get_name(stream_class
);
377 writer_stream_class
= bt_ctf_stream_class_create_empty(name
);
378 if (!writer_stream_class
) {
379 fprintf(err
, "[error] %s in %s:%d\n",
380 __func__
, __FILE__
, __LINE__
);
384 type
= bt_ctf_stream_class_get_packet_context_type(stream_class
);
386 ret_int
= bt_ctf_stream_class_set_packet_context_type(
387 writer_stream_class
, type
);
389 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
396 type
= bt_ctf_stream_class_get_event_header_type(stream_class
);
398 ret_int
= bt_ctf_trace_get_clock_class_count(writer_trace
);
400 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
404 if (override_ts64
&& ret_int
> 0) {
405 struct bt_ctf_field_type
*new_event_header_type
;
407 new_event_header_type
= override_header_type(err
, type
,
409 if (!new_event_header_type
) {
410 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
414 ret_int
= bt_ctf_stream_class_set_event_header_type(
415 writer_stream_class
, new_event_header_type
);
416 BT_PUT(new_event_header_type
);
418 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
423 ret_int
= bt_ctf_stream_class_set_event_header_type(
424 writer_stream_class
, type
);
426 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
434 type
= bt_ctf_stream_class_get_event_context_type(stream_class
);
436 ret_int
= bt_ctf_stream_class_set_event_context_type(
437 writer_stream_class
, type
);
439 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
449 BT_PUT(writer_stream_class
);
452 return writer_stream_class
;
456 int ctf_stream_copy_packet_header(FILE *err
, struct bt_ctf_packet
*packet
,
457 struct bt_ctf_stream
*writer_stream
)
459 struct bt_ctf_field
*packet_header
= NULL
, *writer_packet_header
= NULL
;
462 packet_header
= bt_ctf_packet_get_header(packet
);
463 if (!packet_header
) {
467 writer_packet_header
= bt_ctf_field_copy(packet_header
);
468 if (!writer_packet_header
) {
469 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
474 ret
= bt_ctf_stream_set_packet_header(writer_stream
,
475 writer_packet_header
);
477 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
487 bt_put(writer_packet_header
);
488 bt_put(packet_header
);
493 int ctf_packet_copy_header(FILE *err
, struct bt_ctf_packet
*packet
,
494 struct bt_ctf_packet
*writer_packet
)
496 struct bt_ctf_field
*packet_header
= NULL
, *writer_packet_header
= NULL
;
499 packet_header
= bt_ctf_packet_get_header(packet
);
500 if (!packet_header
) {
504 writer_packet_header
= bt_ctf_field_copy(packet_header
);
505 if (!writer_packet_header
) {
506 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
511 ret
= bt_ctf_packet_set_header(writer_packet
, writer_packet_header
);
513 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
523 bt_put(packet_header
);
524 bt_put(writer_packet_header
);
529 int ctf_stream_copy_packet_context(FILE *err
, struct bt_ctf_packet
*packet
,
530 struct bt_ctf_stream
*writer_stream
)
532 struct bt_ctf_field
*packet_context
= NULL
, *writer_packet_context
= NULL
;
535 packet_context
= bt_ctf_packet_get_context(packet
);
536 if (!packet_context
) {
540 writer_packet_context
= bt_ctf_field_copy(packet_context
);
541 if (!writer_packet_context
) {
542 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
547 ret
= bt_ctf_stream_set_packet_context(writer_stream
,
548 writer_packet_context
);
550 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
560 bt_put(packet_context
);
561 bt_put(writer_packet_context
);
566 int ctf_packet_copy_context(FILE *err
, struct bt_ctf_packet
*packet
,
567 struct bt_ctf_stream
*writer_stream
,
568 struct bt_ctf_packet
*writer_packet
)
570 struct bt_ctf_field
*packet_context
= NULL
, *writer_packet_context
= NULL
;
573 packet_context
= bt_ctf_packet_get_context(packet
);
574 if (!packet_context
) {
578 writer_packet_context
= bt_ctf_field_copy(packet_context
);
579 if (!writer_packet_context
) {
580 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
585 ret
= bt_ctf_packet_set_context(writer_packet
, writer_packet_context
);
587 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
597 bt_put(writer_packet_context
);
598 bt_put(packet_context
);
603 int ctf_copy_event_header(FILE *err
, struct bt_ctf_event
*event
,
604 struct bt_ctf_event_class
*writer_event_class
,
605 struct bt_ctf_event
*writer_event
,
606 struct bt_ctf_field
*event_header
)
608 struct bt_ctf_clock_class
*clock_class
= NULL
, *writer_clock_class
= NULL
;
609 struct bt_ctf_clock_value
*clock_value
= NULL
, *writer_clock_value
= NULL
;
612 struct bt_ctf_field
*writer_event_header
= NULL
;
615 clock_class
= event_get_clock_class(err
, event
);
617 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
622 clock_value
= bt_ctf_event_get_clock_value(event
, clock_class
);
625 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
630 ret
= bt_ctf_clock_value_get_value(clock_value
, &value
);
633 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
638 writer_clock_class
= event_get_clock_class(err
, writer_event
);
639 if (!writer_clock_class
) {
640 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
645 writer_clock_value
= bt_ctf_clock_value_create(writer_clock_class
, value
);
646 BT_PUT(writer_clock_class
);
647 if (!writer_clock_value
) {
648 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
653 ret
= bt_ctf_event_set_clock_value(writer_event
, writer_clock_value
);
654 BT_PUT(writer_clock_value
);
656 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
661 writer_event_header
= bt_ctf_field_copy(event_header
);
662 if (!writer_event_header
) {
663 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
668 ret
= bt_ctf_event_set_header(writer_event
, writer_event_header
);
669 BT_PUT(writer_event_header
);
671 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
687 struct bt_ctf_trace
*event_class_get_trace(FILE *err
,
688 struct bt_ctf_event_class
*event_class
)
690 struct bt_ctf_trace
*trace
= NULL
;
691 struct bt_ctf_stream_class
*stream_class
= NULL
;
693 stream_class
= bt_ctf_event_class_get_stream_class(event_class
);
695 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
700 trace
= bt_ctf_stream_class_get_trace(stream_class
);
702 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
712 bt_put(stream_class
);
717 struct bt_ctf_event
*ctf_copy_event(FILE *err
, struct bt_ctf_event
*event
,
718 struct bt_ctf_event_class
*writer_event_class
,
721 struct bt_ctf_event
*writer_event
= NULL
;
722 struct bt_ctf_field
*field
= NULL
, *copy_field
= NULL
;
723 struct bt_ctf_trace
*writer_trace
= NULL
;
726 writer_event
= bt_ctf_event_create(writer_event_class
);
728 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
733 writer_trace
= event_class_get_trace(err
, writer_event_class
);
735 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
740 field
= bt_ctf_event_get_header(event
);
743 * If override_ts64, we override all integer fields mapped to a
744 * clock to a uint64_t field type, otherwise, we just copy it as
747 ret
= bt_ctf_trace_get_clock_class_count(writer_trace
);
749 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
753 if (override_ts64
&& ret
> 0) {
754 copy_field
= bt_ctf_event_get_header(writer_event
);
756 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
761 ret
= copy_override_field(err
, event
, writer_event
, field
,
764 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
770 ret
= ctf_copy_event_header(err
, event
, writer_event_class
,
771 writer_event
, field
);
773 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
781 /* Optional field, so it can fail silently. */
782 field
= bt_ctf_event_get_stream_event_context(event
);
784 copy_field
= bt_ctf_field_copy(field
);
786 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
790 ret
= bt_ctf_event_set_stream_event_context(writer_event
,
793 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
801 /* Optional field, so it can fail silently. */
802 field
= bt_ctf_event_get_event_context(event
);
804 copy_field
= bt_ctf_field_copy(field
);
806 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
810 ret
= bt_ctf_event_set_event_context(writer_event
, copy_field
);
812 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
820 field
= bt_ctf_event_get_event_payload(event
);
822 copy_field
= bt_ctf_field_copy(field
);
824 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
828 ret
= bt_ctf_event_set_event_payload(writer_event
, copy_field
);
830 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
841 BT_PUT(writer_event
);
845 bt_put(writer_trace
);
850 enum bt_component_status
ctf_copy_trace(FILE *err
, struct bt_ctf_trace
*trace
,
851 struct bt_ctf_trace
*writer_trace
)
853 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
854 int field_count
, i
, int_ret
;
855 struct bt_ctf_field_type
*header_type
= NULL
;
856 enum bt_ctf_byte_order order
;
857 const char *trace_name
;
858 const unsigned char *trace_uuid
;
860 field_count
= bt_ctf_trace_get_environment_field_count(trace
);
861 for (i
= 0; i
< field_count
; i
++) {
864 struct bt_value
*value
= NULL
;
866 name
= bt_ctf_trace_get_environment_field_name_by_index(
869 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
871 ret
= BT_COMPONENT_STATUS_ERROR
;
874 value
= bt_ctf_trace_get_environment_field_value_by_index(
877 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
879 ret
= BT_COMPONENT_STATUS_ERROR
;
883 ret_int
= bt_ctf_trace_set_environment_field(writer_trace
,
887 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
,
889 fprintf(err
, "[error] Unable to set environment field %s\n",
891 ret
= BT_COMPONENT_STATUS_ERROR
;
896 order
= bt_ctf_trace_get_native_byte_order(trace
);
897 if (order
== BT_CTF_BYTE_ORDER_UNKNOWN
) {
898 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
, __LINE__
);
899 ret
= BT_COMPONENT_STATUS_ERROR
;
904 * Only explicitly set the writer trace's native byte order if
905 * the original trace has a specific one. Otherwise leave what
906 * the CTF writer object chooses, which is the machine's native
909 if (order
!= BT_CTF_BYTE_ORDER_UNSPECIFIED
) {
910 ret
= bt_ctf_trace_set_native_byte_order(writer_trace
, order
);
912 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
, __LINE__
);
913 ret
= BT_COMPONENT_STATUS_ERROR
;
918 header_type
= bt_ctf_trace_get_packet_header_type(trace
);
920 int_ret
= bt_ctf_trace_set_packet_header_type(writer_trace
, header_type
);
923 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
, __LINE__
);
924 ret
= BT_COMPONENT_STATUS_ERROR
;
929 trace_name
= bt_ctf_trace_get_name(trace
);
931 int_ret
= bt_ctf_trace_set_name(writer_trace
, trace_name
);
933 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
, __LINE__
);
934 ret
= BT_COMPONENT_STATUS_ERROR
;
939 trace_uuid
= bt_ctf_trace_get_uuid(trace
);
941 int_ret
= bt_ctf_trace_set_uuid(writer_trace
, trace_uuid
);
943 fprintf(err
, "[error] %s in %s:%d\n", __func__
, __FILE__
, __LINE__
);
944 ret
= BT_COMPONENT_STATUS_ERROR
;