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/babeltrace.h>
35 #include "ctfcopytrace.h"
36 #include "clock-fields.h"
39 struct bt_ctf_clock_class
*ctf_copy_clock_class(FILE *err
,
40 struct bt_ctf_clock_class
*clock_class
)
42 int64_t offset
, offset_s
;
45 const char *name
, *description
;
46 struct bt_ctf_clock_class
*writer_clock_class
= NULL
;
48 assert(err
&& clock_class
);
50 name
= bt_ctf_clock_class_get_name(clock_class
);
53 writer_clock_class
= bt_ctf_clock_class_create(name
,
54 bt_ctf_clock_class_get_frequency(clock_class
));
55 if (!writer_clock_class
) {
56 BT_LOGE_STR("Failed to create clock class.");
60 description
= bt_ctf_clock_class_get_description(clock_class
);
62 int_ret
= bt_ctf_clock_class_set_description(writer_clock_class
,
67 u64_ret
= bt_ctf_clock_class_get_precision(clock_class
);
68 assert(u64_ret
!= -1ULL);
70 int_ret
= bt_ctf_clock_class_set_precision(writer_clock_class
,
74 int_ret
= bt_ctf_clock_class_get_offset_s(clock_class
, &offset_s
);
77 int_ret
= bt_ctf_clock_class_set_offset_s(writer_clock_class
, offset_s
);
80 int_ret
= bt_ctf_clock_class_get_offset_cycles(clock_class
, &offset
);
83 int_ret
= bt_ctf_clock_class_set_offset_cycles(writer_clock_class
, offset
);
86 int_ret
= bt_ctf_clock_class_is_absolute(clock_class
);
89 int_ret
= bt_ctf_clock_class_set_is_absolute(writer_clock_class
, int_ret
);
93 return writer_clock_class
;
97 enum bt_component_status
ctf_copy_clock_classes(FILE *err
,
98 struct bt_ctf_trace
*writer_trace
,
99 struct bt_ctf_stream_class
*writer_stream_class
,
100 struct bt_ctf_trace
*trace
)
102 enum bt_component_status ret
;
103 int int_ret
, clock_class_count
, i
;
105 clock_class_count
= bt_ctf_trace_get_clock_class_count(trace
);
107 for (i
= 0; i
< clock_class_count
; i
++) {
108 struct bt_ctf_clock_class
*writer_clock_class
;
109 struct bt_ctf_clock_class
*clock_class
=
110 bt_ctf_trace_get_clock_class_by_index(trace
, i
);
114 writer_clock_class
= ctf_copy_clock_class(err
, clock_class
);
116 if (!writer_clock_class
) {
117 BT_LOGE_STR("Failed to copy clock class.");
118 ret
= BT_COMPONENT_STATUS_ERROR
;
122 int_ret
= bt_ctf_trace_add_clock_class(writer_trace
, writer_clock_class
);
124 BT_PUT(writer_clock_class
);
125 BT_LOGE_STR("Failed to add clock class.");
126 ret
= BT_COMPONENT_STATUS_ERROR
;
131 * Ownership transferred to the trace.
133 bt_put(writer_clock_class
);
136 ret
= BT_COMPONENT_STATUS_OK
;
143 struct bt_ctf_event_class
*ctf_copy_event_class(FILE *err
,
144 struct bt_ctf_event_class
*event_class
)
146 struct bt_ctf_event_class
*writer_event_class
= NULL
;
147 struct bt_ctf_field_type
*context
, *payload_type
;
151 enum bt_ctf_event_class_log_level log_level
;
154 name
= bt_ctf_event_class_get_name(event_class
);
156 writer_event_class
= bt_ctf_event_class_create(name
);
157 assert(writer_event_class
);
159 id
= bt_ctf_event_class_get_id(event_class
);
162 ret
= bt_ctf_event_class_set_id(writer_event_class
, id
);
164 BT_LOGE_STR("Failed to set event_class id.");
168 log_level
= bt_ctf_event_class_get_log_level(event_class
);
170 BT_LOGE_STR("Failed to get log_level.");
174 ret
= bt_ctf_event_class_set_log_level(writer_event_class
, log_level
);
176 BT_LOGE_STR("Failed to set log_level.");
180 emf_uri
= bt_ctf_event_class_get_emf_uri(event_class
);
182 ret
= bt_ctf_event_class_set_emf_uri(writer_event_class
,
185 BT_LOGE_STR("Failed to set emf uri.");
190 payload_type
= bt_ctf_event_class_get_payload_type(event_class
);
192 ret
= bt_ctf_event_class_set_payload_type(writer_event_class
,
195 BT_LOGE_STR("Failed to set payload type.");
198 BT_PUT(payload_type
);
201 context
= bt_ctf_event_class_get_context_type(event_class
);
203 ret
= bt_ctf_event_class_set_context_type(
204 writer_event_class
, context
);
207 BT_LOGE_STR("Failed to set context type.");
215 BT_PUT(writer_event_class
);
217 return writer_event_class
;
221 enum bt_component_status
ctf_copy_event_classes(FILE *err
,
222 struct bt_ctf_stream_class
*stream_class
,
223 struct bt_ctf_stream_class
*writer_stream_class
)
225 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
226 struct bt_ctf_event_class
*event_class
= NULL
, *writer_event_class
= NULL
;
229 count
= bt_ctf_stream_class_get_event_class_count(stream_class
);
232 for (i
= 0; i
< count
; i
++) {
235 event_class
= bt_ctf_stream_class_get_event_class_by_index(
239 if (i
< bt_ctf_stream_class_get_event_class_count(writer_stream_class
)) {
240 writer_event_class
= bt_ctf_stream_class_get_event_class_by_index(
241 writer_stream_class
, i
);
242 if (writer_event_class
) {
244 * If the writer_event_class already exists,
245 * just skip it. It can be used to resync the
246 * event_classes after a trace has become
249 BT_PUT(writer_event_class
);
255 writer_event_class
= ctf_copy_event_class(err
, event_class
);
256 if (!writer_event_class
) {
257 BT_LOGE_STR("Failed to copy event_class.");
258 ret
= BT_COMPONENT_STATUS_ERROR
;
262 int_ret
= bt_ctf_stream_class_add_event_class(writer_stream_class
,
265 BT_LOGE_STR("Failed to add event class.");
266 ret
= BT_COMPONENT_STATUS_ERROR
;
269 BT_PUT(writer_event_class
);
277 bt_put(writer_event_class
);
283 struct bt_ctf_stream_class
*ctf_copy_stream_class(FILE *err
,
284 struct bt_ctf_stream_class
*stream_class
,
285 struct bt_ctf_trace
*writer_trace
,
288 struct bt_ctf_field_type
*type
= NULL
;
289 struct bt_ctf_stream_class
*writer_stream_class
= NULL
;
291 const char *name
= bt_ctf_stream_class_get_name(stream_class
);
293 writer_stream_class
= bt_ctf_stream_class_create_empty(name
);
294 assert(writer_stream_class
);
296 type
= bt_ctf_stream_class_get_packet_context_type(stream_class
);
298 ret_int
= bt_ctf_stream_class_set_packet_context_type(
299 writer_stream_class
, type
);
301 BT_LOGE_STR("Failed to set packet_context type.");
307 type
= bt_ctf_stream_class_get_event_header_type(stream_class
);
309 ret_int
= bt_ctf_trace_get_clock_class_count(writer_trace
);
310 assert(ret_int
>= 0);
311 if (override_ts64
&& ret_int
> 0) {
312 struct bt_ctf_field_type
*new_event_header_type
;
314 new_event_header_type
= override_header_type(err
, type
,
316 if (!new_event_header_type
) {
317 BT_LOGE_STR("Failed to override header type.");
320 ret_int
= bt_ctf_stream_class_set_event_header_type(
321 writer_stream_class
, new_event_header_type
);
322 BT_PUT(new_event_header_type
);
324 BT_LOGE_STR("Failed to set event_header type.");
328 ret_int
= bt_ctf_stream_class_set_event_header_type(
329 writer_stream_class
, type
);
331 BT_LOGE_STR("Failed to set event_header type.");
338 type
= bt_ctf_stream_class_get_event_context_type(stream_class
);
340 ret_int
= bt_ctf_stream_class_set_event_context_type(
341 writer_stream_class
, type
);
343 BT_LOGE_STR("Failed to set event_contexttype.");
352 BT_PUT(writer_stream_class
);
355 return writer_stream_class
;
359 int ctf_stream_copy_packet_header(FILE *err
, struct bt_ctf_packet
*packet
,
360 struct bt_ctf_stream
*writer_stream
)
362 struct bt_ctf_field
*packet_header
= NULL
, *writer_packet_header
= NULL
;
365 packet_header
= bt_ctf_packet_get_header(packet
);
366 if (!packet_header
) {
370 writer_packet_header
= bt_ctf_field_copy(packet_header
);
371 if (!writer_packet_header
) {
372 BT_LOGE_STR("Failed to copy field from stream packet header.");
376 ret
= bt_ctf_stream_set_packet_header(writer_stream
,
377 writer_packet_header
);
379 BT_LOGE_STR("Failed to set stream packet header.");
388 bt_put(writer_packet_header
);
389 bt_put(packet_header
);
394 int ctf_packet_copy_header(FILE *err
, struct bt_ctf_packet
*packet
,
395 struct bt_ctf_packet
*writer_packet
)
397 struct bt_ctf_field
*packet_header
= NULL
, *writer_packet_header
= NULL
;
400 packet_header
= bt_ctf_packet_get_header(packet
);
401 if (!packet_header
) {
405 writer_packet_header
= bt_ctf_field_copy(packet_header
);
406 if (!writer_packet_header
) {
407 BT_LOGE_STR("Failed to copy field from packet header.");
411 ret
= bt_ctf_packet_set_header(writer_packet
, writer_packet_header
);
413 BT_LOGE_STR("Failed to set packet header.");
422 bt_put(packet_header
);
423 bt_put(writer_packet_header
);
428 int ctf_stream_copy_packet_context(FILE *err
, struct bt_ctf_packet
*packet
,
429 struct bt_ctf_stream
*writer_stream
)
431 struct bt_ctf_field
*packet_context
= NULL
, *writer_packet_context
= NULL
;
434 packet_context
= bt_ctf_packet_get_context(packet
);
435 if (!packet_context
) {
439 writer_packet_context
= bt_ctf_field_copy(packet_context
);
440 if (!writer_packet_context
) {
441 BT_LOGE_STR("Failed to copy field from stream packet context.");
445 ret
= bt_ctf_stream_set_packet_context(writer_stream
,
446 writer_packet_context
);
448 BT_LOGE_STR("Failed to set stream packet context.");
457 bt_put(packet_context
);
458 bt_put(writer_packet_context
);
463 int ctf_packet_copy_context(FILE *err
, struct bt_ctf_packet
*packet
,
464 struct bt_ctf_stream
*writer_stream
,
465 struct bt_ctf_packet
*writer_packet
)
467 struct bt_ctf_field
*packet_context
= NULL
, *writer_packet_context
= NULL
;
470 packet_context
= bt_ctf_packet_get_context(packet
);
471 if (!packet_context
) {
475 writer_packet_context
= bt_ctf_field_copy(packet_context
);
476 if (!writer_packet_context
) {
477 BT_LOGE_STR("Failed to copy field from packet context.");
481 ret
= bt_ctf_packet_set_context(writer_packet
, writer_packet_context
);
483 BT_LOGE_STR("Failed to set packet context.");
492 bt_put(writer_packet_context
);
493 bt_put(packet_context
);
498 int ctf_copy_event_header(FILE *err
, struct bt_ctf_event
*event
,
499 struct bt_ctf_event_class
*writer_event_class
,
500 struct bt_ctf_event
*writer_event
,
501 struct bt_ctf_field
*event_header
)
503 struct bt_ctf_clock_class
*clock_class
= NULL
, *writer_clock_class
= NULL
;
504 struct bt_ctf_clock_value
*clock_value
= NULL
, *writer_clock_value
= NULL
;
507 struct bt_ctf_field
*writer_event_header
= NULL
;
510 clock_class
= event_get_clock_class(err
, event
);
512 BT_LOGE_STR("Failed to get event clock_class.");
516 clock_value
= bt_ctf_event_get_clock_value(event
, clock_class
);
520 ret
= bt_ctf_clock_value_get_value(clock_value
, &value
);
523 BT_LOGE_STR("Failed to get clock value.");
527 writer_clock_class
= event_get_clock_class(err
, writer_event
);
528 if (!writer_clock_class
) {
529 BT_LOGE_STR("Failed to get event clock_class.");
533 writer_clock_value
= bt_ctf_clock_value_create(writer_clock_class
, value
);
534 BT_PUT(writer_clock_class
);
535 if (!writer_clock_value
) {
536 BT_LOGE_STR("Failed to create clock value.");
540 ret
= bt_ctf_event_set_clock_value(writer_event
, writer_clock_value
);
541 BT_PUT(writer_clock_value
);
543 BT_LOGE_STR("Failed to set clock value.");
547 writer_event_header
= bt_ctf_field_copy(event_header
);
548 if (!writer_event_header
) {
549 BT_LOGE_STR("Failed to copy event_header.");
553 ret
= bt_ctf_event_set_header(writer_event
, writer_event_header
);
554 BT_PUT(writer_event_header
);
556 BT_LOGE_STR("Failed to set event_header.");
571 struct bt_ctf_trace
*event_class_get_trace(FILE *err
,
572 struct bt_ctf_event_class
*event_class
)
574 struct bt_ctf_trace
*trace
= NULL
;
575 struct bt_ctf_stream_class
*stream_class
= NULL
;
577 stream_class
= bt_ctf_event_class_get_stream_class(event_class
);
578 assert(stream_class
);
580 trace
= bt_ctf_stream_class_get_trace(stream_class
);
583 bt_put(stream_class
);
588 struct bt_ctf_event
*ctf_copy_event(FILE *err
, struct bt_ctf_event
*event
,
589 struct bt_ctf_event_class
*writer_event_class
,
592 struct bt_ctf_event
*writer_event
= NULL
;
593 struct bt_ctf_field
*field
= NULL
, *copy_field
= NULL
;
594 struct bt_ctf_trace
*writer_trace
= NULL
;
597 writer_event
= bt_ctf_event_create(writer_event_class
);
599 BT_LOGE_STR("Failed to create event.");
603 writer_trace
= event_class_get_trace(err
, writer_event_class
);
605 BT_LOGE_STR("Failed to get trace from event_class.");
609 field
= bt_ctf_event_get_header(event
);
612 * If override_ts64, we override all integer fields mapped to a
613 * clock to a uint64_t field type, otherwise, we just copy it as
616 ret
= bt_ctf_trace_get_clock_class_count(writer_trace
);
619 if (override_ts64
&& ret
> 0) {
620 copy_field
= bt_ctf_event_get_header(writer_event
);
623 ret
= copy_override_field(err
, event
, writer_event
, field
,
626 BT_LOGE_STR("Failed to copy and override field.");
631 ret
= ctf_copy_event_header(err
, event
, writer_event_class
,
632 writer_event
, field
);
634 BT_LOGE_STR("Failed to copy event_header.");
641 /* Optional field, so it can fail silently. */
642 field
= bt_ctf_event_get_stream_event_context(event
);
644 copy_field
= bt_ctf_field_copy(field
);
646 BT_LOGE_STR("Failed to copy field.");
649 ret
= bt_ctf_event_set_stream_event_context(writer_event
,
652 BT_LOGE_STR("Failed to set stream_event_context.");
659 /* Optional field, so it can fail silently. */
660 field
= bt_ctf_event_get_event_context(event
);
662 copy_field
= bt_ctf_field_copy(field
);
664 BT_LOGE_STR("Failed to copy field.");
667 ret
= bt_ctf_event_set_event_context(writer_event
, copy_field
);
669 BT_LOGE_STR("Failed to set event_context.");
676 field
= bt_ctf_event_get_event_payload(event
);
678 copy_field
= bt_ctf_field_copy(field
);
680 BT_LOGE_STR("Failed to copy field.");
683 ret
= bt_ctf_event_set_event_payload(writer_event
, copy_field
);
685 BT_LOGE_STR("Failed to set event_payload.");
695 BT_PUT(writer_event
);
699 bt_put(writer_trace
);
704 enum bt_component_status
ctf_copy_trace(FILE *err
, struct bt_ctf_trace
*trace
,
705 struct bt_ctf_trace
*writer_trace
)
707 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
708 int field_count
, i
, int_ret
;
709 struct bt_ctf_field_type
*header_type
= NULL
;
710 enum bt_ctf_byte_order order
;
711 const char *trace_name
;
712 const unsigned char *trace_uuid
;
714 field_count
= bt_ctf_trace_get_environment_field_count(trace
);
715 for (i
= 0; i
< field_count
; i
++) {
718 struct bt_value
*value
= NULL
;
720 name
= bt_ctf_trace_get_environment_field_name_by_index(
724 value
= bt_ctf_trace_get_environment_field_value_by_index(
728 ret_int
= bt_ctf_trace_set_environment_field(writer_trace
,
732 BT_LOGE("Failed to set environment: field-name=\"%s\"",
734 ret
= BT_COMPONENT_STATUS_ERROR
;
739 order
= bt_ctf_trace_get_native_byte_order(trace
);
740 assert(order
!= BT_CTF_BYTE_ORDER_UNKNOWN
);
743 * Only explicitly set the writer trace's native byte order if
744 * the original trace has a specific one. Otherwise leave what
745 * the CTF writer object chooses, which is the machine's native
748 if (order
!= BT_CTF_BYTE_ORDER_UNSPECIFIED
) {
749 ret
= bt_ctf_trace_set_native_byte_order(writer_trace
, order
);
751 BT_LOGE_STR("Failed to set native byte order.");
752 ret
= BT_COMPONENT_STATUS_ERROR
;
757 header_type
= bt_ctf_trace_get_packet_header_type(trace
);
759 int_ret
= bt_ctf_trace_set_packet_header_type(writer_trace
, header_type
);
762 BT_LOGE_STR("Failed to set packet header type.");
763 ret
= BT_COMPONENT_STATUS_ERROR
;
768 trace_name
= bt_ctf_trace_get_name(trace
);
770 int_ret
= bt_ctf_trace_set_name(writer_trace
, trace_name
);
772 BT_LOGE_STR("Failed to set trace name.");
773 ret
= BT_COMPONENT_STATUS_ERROR
;
778 trace_uuid
= bt_ctf_trace_get_uuid(trace
);
780 int_ret
= bt_ctf_trace_set_uuid(writer_trace
, trace_uuid
);
782 BT_LOGE_STR("Failed to set trace UUID.");
783 ret
= BT_COMPONENT_STATUS_ERROR
;