2 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 #define BT_LOG_TAG "CTF-WRITER-STREAM"
25 #include <babeltrace/lib-logging-internal.h>
27 #include <babeltrace/ref.h>
28 #include <babeltrace/ctf-ir/event-class-internal.h>
29 #include <babeltrace/ctf-writer/writer-internal.h>
30 #include <babeltrace/ctf-writer/stream.h>
31 #include <babeltrace/ctf-writer/stream-internal.h>
32 #include <babeltrace/ctf-writer/stream-class-internal.h>
33 #include <babeltrace/ctf-writer/field-types.h>
34 #include <babeltrace/ctf-writer/fields-internal.h>
35 #include <babeltrace/ctf-writer/trace-internal.h>
36 #include <babeltrace/ctf-writer/event-internal.h>
37 #include <babeltrace/compiler-internal.h>
38 #include <babeltrace/assert-internal.h>
39 #include <babeltrace/assert-pre-internal.h>
45 void bt_ctf_stream_destroy(struct bt_object
*obj
);
48 int try_set_structure_field_integer(struct bt_ctf_field
*, char *, uint64_t);
51 int set_integer_field_value(struct bt_ctf_field
* field
, uint64_t value
)
54 struct bt_ctf_field_type
*field_type
= NULL
;
57 BT_LOGW_STR("Invalid parameter: field is NULL.");
62 field_type
= bt_ctf_field_get_type(field
);
63 BT_ASSERT(field_type
);
65 if (bt_ctf_field_type_get_type_id(field_type
) !=
66 BT_CTF_FIELD_TYPE_ID_INTEGER
) {
67 /* Not an integer and the value is unset, error. */
68 BT_LOGW("Invalid parameter: field's type is not an integer field type: "
69 "field-addr=%p, ft-addr=%p, ft-id=%s",
71 bt_common_field_type_id_string((int)
72 bt_ctf_field_type_get_type_id(field_type
)));
77 if (bt_ctf_field_type_integer_is_signed(field_type
)) {
78 ret
= bt_ctf_field_integer_signed_set_value(field
, (int64_t) value
);
80 /* Value is out of range, error. */
81 BT_LOGW("Cannot set signed integer field's value: "
82 "addr=%p, value=%" PRId64
,
83 field
, (int64_t) value
);
87 ret
= bt_ctf_field_integer_unsigned_set_value(field
, value
);
89 /* Value is out of range, error. */
90 BT_LOGW("Cannot set unsigned integer field's value: "
91 "addr=%p, value=%" PRIu64
,
102 int set_packet_header_magic(struct bt_ctf_stream
*stream
)
105 struct bt_ctf_field
*magic_field
= bt_ctf_field_structure_get_field_by_name(
106 stream
->packet_header
, "magic");
107 const uint32_t magic_value
= 0xc1fc1fc1;
112 /* No magic field found. Not an error, skip. */
113 BT_LOGV("No field named `magic` in packet header: skipping: "
114 "stream-addr=%p, stream-name=\"%s\"",
115 stream
, bt_ctf_stream_get_name(stream
));
119 ret
= bt_ctf_field_integer_unsigned_set_value(magic_field
,
120 (uint64_t) magic_value
);
123 BT_LOGW("Cannot set packet header field's `magic` integer field's value: "
124 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64
,
125 stream
, bt_ctf_stream_get_name(stream
),
126 magic_field
, (uint64_t) magic_value
);
128 BT_LOGV("Set packet header field's `magic` field's value: "
129 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64
,
130 stream
, bt_ctf_stream_get_name(stream
),
131 magic_field
, (uint64_t) magic_value
);
139 int set_packet_header_uuid(struct bt_ctf_stream
*stream
)
143 struct bt_ctf_trace
*trace
= NULL
;
144 struct bt_ctf_field
*uuid_field
= bt_ctf_field_structure_get_field_by_name(
145 stream
->packet_header
, "uuid");
150 /* No uuid field found. Not an error, skip. */
151 BT_LOGV("No field named `uuid` in packet header: skipping: "
152 "stream-addr=%p, stream-name=\"%s\"",
153 stream
, bt_ctf_stream_get_name(stream
));
157 trace
= (struct bt_ctf_trace
*) bt_object_get_parent(stream
);
158 for (i
= 0; i
< 16; i
++) {
159 struct bt_ctf_field
*uuid_element
=
160 bt_ctf_field_array_get_field(uuid_field
, i
);
162 ret
= bt_ctf_field_integer_unsigned_set_value(
163 uuid_element
, (uint64_t) trace
->common
.uuid
[i
]);
164 bt_put(uuid_element
);
166 BT_LOGW("Cannot set integer field's value (for `uuid` packet header field): "
167 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, "
168 "value=%" PRIu64
", index=%" PRId64
,
169 stream
, bt_ctf_stream_get_name(stream
),
170 uuid_element
, (uint64_t) trace
->common
.uuid
[i
], i
);
175 BT_LOGV("Set packet header field's `uuid` field's value: "
176 "stream-addr=%p, stream-name=\"%s\", field-addr=%p",
177 stream
, bt_ctf_stream_get_name(stream
), uuid_field
);
185 int set_packet_header_stream_id(struct bt_ctf_stream
*stream
)
189 struct bt_ctf_field
*stream_id_field
=
190 bt_ctf_field_structure_get_field_by_name(
191 stream
->packet_header
, "stream_id");
193 if (!stream_id_field
) {
194 /* No stream_id field found. Not an error, skip. */
195 BT_LOGV("No field named `stream_id` in packet header: skipping: "
196 "stream-addr=%p, stream-name=\"%s\"",
197 stream
, bt_ctf_stream_get_name(stream
));
201 stream_id
= stream
->common
.stream_class
->id
;
202 ret
= bt_ctf_field_integer_unsigned_set_value(stream_id_field
,
203 (uint64_t) stream_id
);
205 BT_LOGW("Cannot set packet header field's `stream_id` integer field's value: "
206 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64
,
207 stream
, bt_ctf_stream_get_name(stream
),
208 stream_id_field
, (uint64_t) stream_id
);
210 BT_LOGV("Set packet header field's `stream_id` field's value: "
211 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64
,
212 stream
, bt_ctf_stream_get_name(stream
),
213 stream_id_field
, (uint64_t) stream_id
);
217 bt_put(stream_id_field
);
222 int auto_populate_packet_header(struct bt_ctf_stream
*stream
)
226 if (!stream
->packet_header
) {
230 ret
= set_packet_header_magic(stream
);
232 BT_LOGW("Cannot set packet header's magic number field: "
233 "stream-addr=%p, stream-name=\"%s\"",
234 stream
, bt_ctf_stream_get_name(stream
));
238 ret
= set_packet_header_uuid(stream
);
240 BT_LOGW("Cannot set packet header's UUID field: "
241 "stream-addr=%p, stream-name=\"%s\"",
242 stream
, bt_ctf_stream_get_name(stream
));
246 ret
= set_packet_header_stream_id(stream
);
248 BT_LOGW("Cannot set packet header's stream class ID field: "
249 "stream-addr=%p, stream-name=\"%s\"",
250 stream
, bt_ctf_stream_get_name(stream
));
254 BT_LOGV("Automatically populated stream's packet header's known fields: "
255 "stream-addr=%p, stream-name=\"%s\"",
256 stream
, bt_ctf_stream_get_name(stream
));
263 int set_packet_context_packet_size(struct bt_ctf_stream
*stream
)
266 struct bt_ctf_field
*field
= bt_ctf_field_structure_get_field_by_name(
267 stream
->packet_context
, "packet_size");
272 /* No packet size field found. Not an error, skip. */
273 BT_LOGV("No field named `packet_size` in packet context: skipping: "
274 "stream-addr=%p, stream-name=\"%s\"",
275 stream
, bt_ctf_stream_get_name(stream
));
279 ret
= bt_ctf_field_integer_unsigned_set_value(field
,
280 stream
->pos
.packet_size
);
282 BT_LOGW("Cannot set packet context field's `packet_size` integer field's value: "
283 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64
,
284 stream
, bt_ctf_stream_get_name(stream
),
285 field
, stream
->pos
.packet_size
);
287 BT_LOGV("Set packet context field's `packet_size` field's value: "
288 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64
,
289 stream
, bt_ctf_stream_get_name(stream
),
290 field
, stream
->pos
.packet_size
);
299 int set_packet_context_content_size(struct bt_ctf_stream
*stream
)
302 struct bt_ctf_field
*field
= bt_ctf_field_structure_get_field_by_name(
303 stream
->packet_context
, "content_size");
308 /* No content size field found. Not an error, skip. */
309 BT_LOGV("No field named `content_size` in packet context: skipping: "
310 "stream-addr=%p, stream-name=\"%s\"",
311 stream
, bt_ctf_stream_get_name(stream
));
315 ret
= bt_ctf_field_integer_unsigned_set_value(field
,
318 BT_LOGW("Cannot set packet context field's `content_size` integer field's value: "
319 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRId64
,
320 stream
, bt_ctf_stream_get_name(stream
),
321 field
, stream
->pos
.offset
);
323 BT_LOGV("Set packet context field's `content_size` field's value: "
324 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRId64
,
325 stream
, bt_ctf_stream_get_name(stream
),
326 field
, stream
->pos
.offset
);
335 int set_packet_context_events_discarded(struct bt_ctf_stream
*stream
)
338 struct bt_ctf_field
*field
= bt_ctf_field_structure_get_field_by_name(
339 stream
->packet_context
, "events_discarded");
344 /* No discarded events count field found. Not an error, skip. */
345 BT_LOGV("No field named `events_discarded` in packet context: skipping: "
346 "stream-addr=%p, stream-name=\"%s\"",
347 stream
, bt_ctf_stream_get_name(stream
));
352 * If the field is set by the user, make sure that the value is
353 * greater than or equal to the stream's current count of
354 * discarded events. We do not allow wrapping here. If it's
355 * valid, update the stream's current count.
357 if (bt_ctf_field_is_set_recursive(field
)) {
360 ret
= bt_ctf_field_integer_unsigned_get_value(field
,
363 BT_LOGW("Cannot get packet context `events_discarded` field's unsigned value: "
364 "stream-addr=%p, stream-name=\"%s\", field-addr=%p",
365 stream
, bt_ctf_stream_get_name(stream
), field
);
369 if (user_val
< stream
->discarded_events
) {
370 BT_LOGW("Invalid packet context `events_discarded` field's unsigned value: "
371 "value is lesser than the stream's current discarded events count: "
372 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, "
373 "value=%" PRIu64
", "
374 "stream-discarded-events-count=%" PRIu64
,
375 stream
, bt_ctf_stream_get_name(stream
), field
,
376 user_val
, stream
->discarded_events
);
380 stream
->discarded_events
= user_val
;
382 ret
= bt_ctf_field_integer_unsigned_set_value(field
,
383 stream
->discarded_events
);
385 BT_LOGW("Cannot set packet context field's `events_discarded` integer field's value: "
386 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64
,
387 stream
, bt_ctf_stream_get_name(stream
),
388 field
, stream
->discarded_events
);
390 BT_LOGV("Set packet context field's `events_discarded` field's value: "
391 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64
,
392 stream
, bt_ctf_stream_get_name(stream
),
393 field
, stream
->discarded_events
);
403 void update_clock_value(uint64_t *val
, uint64_t new_val
,
404 unsigned int new_val_size
)
406 const uint64_t pow2
= 1ULL << new_val_size
;
407 const uint64_t mask
= pow2
- 1;
410 #ifdef BT_LOG_ENABLED_VERBOSE
411 uint64_t old_val
= *val
;
414 if (new_val_size
== 64) {
419 val_masked
= *val
& mask
;
421 if (new_val
< val_masked
) {
430 BT_LOGV("Updated clock value: old-val=%" PRIu64
", new-val=%" PRIu64
,
436 int visit_field_update_clock_value(struct bt_ctf_field
*field
, uint64_t *val
)
439 struct bt_field_common
*field_common
= (void *) field
;
445 switch (bt_ctf_field_get_type_id(field
)) {
446 case BT_CTF_FIELD_TYPE_ID_INTEGER
:
448 struct bt_ctf_clock_class
*cc
=
449 bt_ctf_field_type_integer_get_mapped_clock_class(
450 (void *) field_common
->type
);
459 val_size
= bt_ctf_field_type_integer_get_size(
460 (void *) field_common
->type
);
461 BT_ASSERT(val_size
>= 1);
463 if (bt_ctf_field_type_integer_is_signed(
464 (void *) field_common
->type
)) {
467 ret
= bt_ctf_field_integer_signed_get_value(field
, &ival
);
468 uval
= (uint64_t) ival
;
470 ret
= bt_ctf_field_integer_unsigned_get_value(field
, &uval
);
478 update_clock_value(val
, uval
, val_size
);
481 case BT_CTF_FIELD_TYPE_ID_ENUM
:
483 struct bt_ctf_field
*int_field
=
484 bt_ctf_field_enumeration_get_container(field
);
486 BT_ASSERT(int_field
);
487 ret
= visit_field_update_clock_value(int_field
, val
);
491 case BT_CTF_FIELD_TYPE_ID_ARRAY
:
494 int64_t len
= bt_ctf_field_type_array_get_length(
495 (void *) field_common
->type
);
499 for (i
= 0; i
< len
; i
++) {
500 struct bt_ctf_field
*elem_field
=
501 bt_ctf_field_array_get_field(field
, i
);
503 BT_ASSERT(elem_field
);
504 ret
= visit_field_update_clock_value(elem_field
, val
);
512 case BT_CTF_FIELD_TYPE_ID_SEQUENCE
:
515 int64_t len
= bt_field_common_sequence_get_int_length(
523 for (i
= 0; i
< len
; i
++) {
524 struct bt_ctf_field
*elem_field
=
525 bt_ctf_field_sequence_get_field(field
, i
);
527 BT_ASSERT(elem_field
);
528 ret
= visit_field_update_clock_value(elem_field
, val
);
536 case BT_CTF_FIELD_TYPE_ID_STRUCT
:
539 int64_t len
= bt_ctf_field_type_structure_get_field_count(
540 (void *) field_common
->type
);
544 for (i
= 0; i
< len
; i
++) {
545 struct bt_ctf_field
*member_field
=
546 bt_ctf_field_structure_get_field_by_index(field
, i
);
548 BT_ASSERT(member_field
);
549 ret
= visit_field_update_clock_value(member_field
, val
);
550 bt_put(member_field
);
557 case BT_CTF_FIELD_TYPE_ID_VARIANT
:
559 struct bt_ctf_field
*cur_field
=
560 bt_ctf_field_variant_get_current_field(field
);
567 ret
= visit_field_update_clock_value(cur_field
, val
);
579 int visit_event_update_clock_value(struct bt_ctf_event
*event
, uint64_t *val
)
582 struct bt_ctf_field
*field
;
584 field
= bt_ctf_event_get_header(event
);
585 ret
= visit_field_update_clock_value(field
, val
);
588 BT_LOGW_STR("Cannot automatically update clock value in "
593 field
= bt_ctf_event_get_stream_event_context(event
);
594 ret
= visit_field_update_clock_value(field
, val
);
597 BT_LOGW_STR("Cannot automatically update clock value in "
598 "event's stream event context.");
602 field
= bt_ctf_event_get_context(event
);
603 ret
= visit_field_update_clock_value(field
, val
);
606 BT_LOGW_STR("Cannot automatically update clock value in "
611 field
= bt_ctf_event_get_payload_field(event
);
612 ret
= visit_field_update_clock_value(field
, val
);
615 BT_LOGW_STR("Cannot automatically update clock value in "
625 int set_packet_context_timestamps(struct bt_ctf_stream
*stream
)
629 uint64_t cur_clock_value
;
630 uint64_t init_clock_value
= 0;
631 struct bt_ctf_field
*ts_begin_field
= bt_ctf_field_structure_get_field_by_name(
632 stream
->packet_context
, "timestamp_begin");
633 struct bt_ctf_field
*ts_end_field
= bt_ctf_field_structure_get_field_by_name(
634 stream
->packet_context
, "timestamp_end");
635 struct bt_field_common
*packet_context
=
636 (void *) stream
->packet_context
;
640 if (ts_begin_field
&& bt_ctf_field_is_set_recursive(ts_begin_field
)) {
641 /* Use provided `timestamp_begin` value as starting value */
642 ret
= bt_ctf_field_integer_unsigned_get_value(ts_begin_field
, &val
);
644 init_clock_value
= val
;
645 } else if (stream
->last_ts_end
!= -1ULL) {
646 /* Use last packet's ending timestamp as starting value */
647 init_clock_value
= stream
->last_ts_end
;
650 cur_clock_value
= init_clock_value
;
652 if (stream
->last_ts_end
!= -1ULL &&
653 cur_clock_value
< stream
->last_ts_end
) {
654 BT_LOGW("Packet's initial timestamp is less than previous "
655 "packet's final timestamp: "
656 "stream-addr=%p, stream-name=\"%s\", "
657 "cur-packet-ts-begin=%" PRIu64
", "
658 "prev-packet-ts-end=%" PRIu64
,
659 stream
, bt_ctf_stream_get_name(stream
),
660 cur_clock_value
, stream
->last_ts_end
);
666 * Visit all the packet context fields, followed by all the
667 * fields of all the events, in order, updating our current
668 * clock value as we visit.
670 * While visiting the packet context fields, do not consider
671 * `timestamp_begin` and `timestamp_end` because this function's
672 * purpose is to set them anyway. Also do not consider
673 * `packet_size`, `content_size`, `events_discarded`, and
674 * `packet_seq_num` if they are not set because those are
675 * autopopulating fields.
677 len
= bt_ctf_field_type_structure_get_field_count(
678 (void *) packet_context
->type
);
681 for (i
= 0; i
< len
; i
++) {
682 const char *member_name
;
683 struct bt_ctf_field
*member_field
;
685 ret
= bt_ctf_field_type_structure_get_field_by_index(
686 (void *) packet_context
->type
, &member_name
, NULL
, i
);
689 if (strcmp(member_name
, "timestamp_begin") == 0 ||
690 strcmp(member_name
, "timestamp_end") == 0) {
694 member_field
= bt_ctf_field_structure_get_field_by_index(
695 stream
->packet_context
, i
);
696 BT_ASSERT(member_field
);
698 if (strcmp(member_name
, "packet_size") == 0 &&
699 !bt_ctf_field_is_set_recursive(member_field
)) {
700 bt_put(member_field
);
704 if (strcmp(member_name
, "content_size") == 0 &&
705 !bt_ctf_field_is_set_recursive(member_field
)) {
706 bt_put(member_field
);
710 if (strcmp(member_name
, "events_discarded") == 0 &&
711 !bt_ctf_field_is_set_recursive(member_field
)) {
712 bt_put(member_field
);
716 if (strcmp(member_name
, "packet_seq_num") == 0 &&
717 !bt_ctf_field_is_set_recursive(member_field
)) {
718 bt_put(member_field
);
722 ret
= visit_field_update_clock_value(member_field
,
724 bt_put(member_field
);
726 BT_LOGW("Cannot automatically update clock value "
727 "in stream's packet context: "
728 "stream-addr=%p, stream-name=\"%s\", "
730 stream
, bt_ctf_stream_get_name(stream
),
736 for (i
= 0; i
< stream
->events
->len
; i
++) {
737 struct bt_ctf_event
*event
= g_ptr_array_index(stream
->events
, i
);
740 ret
= visit_event_update_clock_value(event
, &cur_clock_value
);
742 BT_LOGW("Cannot automatically update clock value "
743 "in stream's packet context: "
744 "stream-addr=%p, stream-name=\"%s\", "
745 "index=%" PRIu64
", event-addr=%p, "
746 "event-class-id=%" PRId64
", "
747 "event-class-name=\"%s\"",
748 stream
, bt_ctf_stream_get_name(stream
),
750 bt_event_class_common_get_id(event
->common
.class),
751 bt_event_class_common_get_name(event
->common
.class));
757 * Everything is visited, thus the current clock value
758 * corresponds to the ending timestamp. Validate this value
759 * against the provided value of `timestamp_end`, if any,
762 if (ts_end_field
&& bt_ctf_field_is_set_recursive(ts_end_field
)) {
763 ret
= bt_ctf_field_integer_unsigned_get_value(ts_end_field
, &val
);
766 if (val
< cur_clock_value
) {
767 BT_LOGW("Packet's final timestamp is less than "
768 "computed packet's final timestamp: "
769 "stream-addr=%p, stream-name=\"%s\", "
770 "cur-packet-ts-end=%" PRIu64
", "
771 "computed-packet-ts-end=%" PRIu64
,
772 stream
, bt_ctf_stream_get_name(stream
),
773 val
, cur_clock_value
);
778 stream
->last_ts_end
= val
;
781 if (ts_end_field
&& !bt_ctf_field_is_set_recursive(ts_end_field
)) {
782 ret
= set_integer_field_value(ts_end_field
, cur_clock_value
);
784 stream
->last_ts_end
= cur_clock_value
;
788 stream
->last_ts_end
= cur_clock_value
;
791 /* Set `timestamp_begin` field to initial clock value */
792 if (ts_begin_field
&& !bt_ctf_field_is_set_recursive(ts_begin_field
)) {
793 ret
= set_integer_field_value(ts_begin_field
, init_clock_value
);
798 bt_put(ts_begin_field
);
799 bt_put(ts_end_field
);
804 int auto_populate_packet_context(struct bt_ctf_stream
*stream
, bool set_ts
)
808 if (!stream
->packet_context
) {
812 ret
= set_packet_context_packet_size(stream
);
814 BT_LOGW("Cannot set packet context's packet size field: "
815 "stream-addr=%p, stream-name=\"%s\"",
816 stream
, bt_ctf_stream_get_name(stream
));
820 ret
= set_packet_context_content_size(stream
);
822 BT_LOGW("Cannot set packet context's content size field: "
823 "stream-addr=%p, stream-name=\"%s\"",
824 stream
, bt_ctf_stream_get_name(stream
));
829 ret
= set_packet_context_timestamps(stream
);
831 BT_LOGW("Cannot set packet context's timestamp fields: "
832 "stream-addr=%p, stream-name=\"%s\"",
833 stream
, bt_ctf_stream_get_name(stream
));
838 ret
= set_packet_context_events_discarded(stream
);
840 BT_LOGW("Cannot set packet context's discarded events count field: "
841 "stream-addr=%p, stream-name=\"%s\"",
842 stream
, bt_ctf_stream_get_name(stream
));
846 BT_LOGV("Automatically populated stream's packet context's known fields: "
847 "stream-addr=%p, stream-name=\"%s\"",
848 stream
, bt_ctf_stream_get_name(stream
));
855 void release_event(struct bt_ctf_event
*event
)
857 if (bt_object_get_ref_count(event
)) {
859 * The event is being orphaned, but it must guarantee the
860 * existence of its event class for the duration of its
863 bt_get(event
->common
.class);
864 BT_PUT(event
->common
.base
.parent
);
866 bt_object_release(event
);
871 int create_stream_file(struct bt_ctf_writer
*writer
,
872 struct bt_ctf_stream
*stream
)
875 GString
*filename
= g_string_new(NULL
);
876 int64_t stream_class_id
;
877 char *file_path
= NULL
;
879 BT_LOGD("Creating stream file: writer-addr=%p, stream-addr=%p, "
880 "stream-name=\"%s\", stream-class-addr=%p, stream-class-name=\"%s\"",
881 writer
, stream
, bt_ctf_stream_get_name(stream
),
882 stream
->common
.stream_class
,
883 stream
->common
.stream_class
->name
->str
);
885 if (stream
->common
.name
&& stream
->common
.name
->len
> 0) {
886 /* Use stream name's base name as prefix */
887 gchar
*basename
= g_path_get_basename(stream
->common
.name
->str
);
891 if (strcmp(basename
, G_DIR_SEPARATOR_S
) == 0) {
892 g_string_assign(filename
, "stream");
894 g_string_assign(filename
, basename
);
901 if (stream
->common
.stream_class
->name
&&
902 stream
->common
.stream_class
->name
->len
> 0) {
903 /* Use stream class name's base name as prefix */
906 stream
->common
.stream_class
->name
->str
);
910 if (strcmp(basename
, G_DIR_SEPARATOR_S
) == 0) {
911 g_string_assign(filename
, "stream");
913 g_string_assign(filename
, basename
);
920 /* Default to using `stream-` as prefix */
921 g_string_assign(filename
, "stream");
924 stream_class_id
= bt_stream_class_common_get_id(stream
->common
.stream_class
);
925 BT_ASSERT(stream_class_id
>= 0);
926 BT_ASSERT(stream
->common
.id
>= 0);
927 g_string_append_printf(filename
, "-%" PRId64
"-%" PRId64
,
928 stream_class_id
, stream
->common
.id
);
930 file_path
= g_build_filename(writer
->path
->str
, filename
->str
, NULL
);
931 if (file_path
== NULL
) {
937 O_RDWR
| O_CREAT
| O_TRUNC
,
938 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
);
941 BT_LOGW_ERRNO("Failed to open stream file for writing",
942 ": file_path=\"%s\", filename=\"%s\", ret=%d",
943 file_path
, filename
->str
, fd
);
947 BT_LOGD("Created stream file for writing: "
948 "stream-addr=%p, stream-name=\"%s\", "
949 "filename=\"%s\", fd=%d", stream
, bt_ctf_stream_get_name(stream
),
953 g_string_free(filename
, TRUE
);
958 void set_stream_fd(struct bt_ctf_stream
*stream
, int fd
)
960 (void) bt_ctf_stream_pos_init(&stream
->pos
, fd
, O_RDWR
);
965 struct bt_ctf_stream
*bt_ctf_stream_create_with_id(
966 struct bt_ctf_stream_class
*stream_class
,
967 const char *name
, uint64_t id
)
971 struct bt_ctf_stream
*stream
= NULL
;
972 struct bt_ctf_trace
*trace
= NULL
;
973 struct bt_ctf_writer
*writer
= NULL
;
975 BT_LOGD("Creating CTF writer stream object: stream-class-addr=%p, "
976 "stream-class-name=\"%s\", stream-name=\"%s\", "
977 "stream-id=%" PRIu64
,
978 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
980 stream
= g_new0(struct bt_ctf_stream
, 1);
982 BT_LOGE_STR("Failed to allocate one stream.");
987 id
= stream_class
->next_stream_id
;
990 ret
= bt_stream_common_initialize(BT_TO_COMMON(stream
),
991 BT_TO_COMMON(stream_class
), name
, id
, bt_ctf_stream_destroy
);
993 /* bt_stream_common_initialize() logs errors */
997 trace
= BT_FROM_COMMON(bt_stream_class_common_borrow_trace(
998 BT_TO_COMMON(stream_class
)));
1000 BT_LOGW("Invalid parameter: cannot create stream from a stream class which is not part of trace: "
1001 "stream-class-addr=%p, stream-class-name=\"%s\", "
1002 "stream-name=\"%s\"",
1003 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
1008 stream
->pos
.fd
= -1;
1009 writer
= (struct bt_ctf_writer
*) bt_object_get_parent(trace
);
1010 stream
->last_ts_end
= -1ULL;
1011 BT_LOGD("CTF writer stream object belongs writer's trace: "
1012 "writer-addr=%p", writer
);
1015 if (stream_class
->common
.packet_context_field_type
) {
1016 BT_LOGD("Creating stream's packet context field: "
1018 stream_class
->common
.packet_context_field_type
);
1019 stream
->packet_context
= bt_ctf_field_create(
1020 (void *) stream_class
->common
.packet_context_field_type
);
1021 if (!stream
->packet_context
) {
1022 BT_LOGW_STR("Cannot create stream's packet context field.");
1026 /* Initialize events_discarded */
1027 ret
= try_set_structure_field_integer(
1028 stream
->packet_context
, "events_discarded", 0);
1030 BT_LOGW("Cannot set `events_discarded` field in packet context: "
1031 "ret=%d, packet-context-field-addr=%p",
1032 ret
, stream
->packet_context
);
1037 stream
->events
= g_ptr_array_new_with_free_func(
1038 (GDestroyNotify
) release_event
);
1039 if (!stream
->events
) {
1040 BT_LOGE_STR("Failed to allocate a GPtrArray.");
1044 if (trace
->common
.packet_header_field_type
) {
1045 BT_LOGD("Creating stream's packet header field: "
1046 "ft-addr=%p", trace
->common
.packet_header_field_type
);
1047 stream
->packet_header
=
1048 bt_ctf_field_create(
1049 (void *) trace
->common
.packet_header_field_type
);
1050 if (!stream
->packet_header
) {
1051 BT_LOGW_STR("Cannot create stream's packet header field.");
1057 * Attempt to populate the default trace packet header fields
1058 * (magic, uuid and stream_id). This will _not_ fail shall the
1059 * fields not be found or be of an incompatible type; they will
1060 * simply not be populated automatically. The user will have to
1061 * make sure to set the trace packet header fields himself
1064 ret
= auto_populate_packet_header(stream
);
1066 BT_LOGW_STR("Cannot automatically populate the stream's packet header.");
1070 /* Create file associated with this stream */
1071 fd
= create_stream_file(writer
, stream
);
1073 BT_LOGW_STR("Cannot create stream file.");
1077 set_stream_fd(stream
, fd
);
1079 /* Freeze the writer */
1080 BT_LOGD_STR("Freezing stream's CTF writer.");
1081 bt_ctf_writer_freeze(writer
);
1083 /* Add this stream to the trace's streams */
1084 g_ptr_array_add(trace
->common
.streams
, stream
);
1085 stream_class
->next_stream_id
++;
1086 BT_LOGD("Created stream object: addr=%p", stream
);
1097 struct bt_ctf_stream
*bt_ctf_stream_create(
1098 struct bt_ctf_stream_class
*stream_class
,
1099 const char *name
, uint64_t id_param
)
1101 return bt_ctf_stream_create_with_id(stream_class
,
1105 int bt_ctf_stream_get_discarded_events_count(
1106 struct bt_ctf_stream
*stream
, uint64_t *count
)
1111 BT_LOGW_STR("Invalid parameter: stream is NULL.");
1117 BT_LOGW_STR("Invalid parameter: count is NULL.");
1122 if (stream
->pos
.fd
< 0) {
1123 BT_LOGW("Invalid parameter: stream is not a CTF writer stream: "
1124 "stream-addr=%p, stream-name=\"%s\"",
1125 stream
, bt_ctf_stream_get_name(stream
));
1130 *count
= (uint64_t) stream
->discarded_events
;
1137 int set_packet_context_events_discarded_field(struct bt_ctf_stream
*stream
,
1141 struct bt_ctf_field
*events_discarded_field
= NULL
;
1143 if (!stream
->packet_context
) {
1147 events_discarded_field
= bt_ctf_field_structure_get_field_by_name(
1148 stream
->packet_context
, "events_discarded");
1149 if (!events_discarded_field
) {
1153 ret
= bt_ctf_field_integer_unsigned_set_value(
1154 events_discarded_field
, count
);
1156 BT_LOGW("Cannot set packet context's `events_discarded` field: "
1157 "field-addr=%p, value=%" PRIu64
,
1158 events_discarded_field
, count
);
1163 bt_put(events_discarded_field
);
1167 void bt_ctf_stream_append_discarded_events(struct bt_ctf_stream
*stream
,
1168 uint64_t event_count
)
1172 struct bt_ctf_field
*events_discarded_field
= NULL
;
1175 BT_LOGW_STR("Invalid parameter: stream is NULL.");
1179 BT_LOGV("Appending discarded events to stream: "
1180 "stream-addr=%p, stream-name=\"%s\", append-count=%" PRIu64
,
1181 stream
, bt_ctf_stream_get_name(stream
), event_count
);
1183 if (!stream
->packet_context
) {
1184 BT_LOGW_STR("Invalid parameter: stream has no packet context field.");
1188 if (stream
->pos
.fd
< 0) {
1189 BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
1193 events_discarded_field
= bt_ctf_field_structure_get_field_by_name(
1194 stream
->packet_context
, "events_discarded");
1195 if (!events_discarded_field
) {
1196 BT_LOGW_STR("No field named `events_discarded` in stream's packet context.");
1200 new_count
= stream
->discarded_events
+ event_count
;
1201 if (new_count
< stream
->discarded_events
) {
1202 BT_LOGW("New discarded events count is less than the stream's current discarded events count: "
1203 "cur-count=%" PRIu64
", new-count=%" PRIu64
,
1204 stream
->discarded_events
, new_count
);
1208 ret
= set_packet_context_events_discarded_field(stream
, new_count
);
1210 /* set_packet_context_events_discarded_field() logs errors */
1214 stream
->discarded_events
= new_count
;
1215 BT_LOGV("Appended discarded events to stream: "
1216 "stream-addr=%p, stream-name=\"%s\", append-count=%" PRIu64
,
1217 stream
, bt_ctf_stream_get_name(stream
), event_count
);
1220 bt_put(events_discarded_field
);
1223 static int auto_populate_event_header(struct bt_ctf_stream
*stream
,
1224 struct bt_ctf_event
*event
)
1227 struct bt_ctf_field
*id_field
= NULL
, *timestamp_field
= NULL
;
1228 struct bt_ctf_clock_class
*mapped_clock_class
= NULL
;
1229 struct bt_ctf_stream_class
*stream_class
=
1230 BT_FROM_COMMON(bt_stream_common_borrow_class(
1231 BT_TO_COMMON(stream
)));
1232 int64_t event_class_id
;
1236 if (!event
->common
.header_field
) {
1240 if (event
->common
.frozen
) {
1241 BT_LOGW_STR("Cannot populate event header field: event is frozen.");
1246 BT_LOGV("Automatically populating event's header field: "
1247 "stream-addr=%p, stream-name=\"%s\", event-addr=%p",
1248 stream
, bt_ctf_stream_get_name(stream
), event
);
1250 id_field
= bt_ctf_field_structure_get_field_by_name(
1251 (void *) event
->common
.header_field
, "id");
1252 event_class_id
= bt_event_class_common_get_id(event
->common
.class);
1253 BT_ASSERT(event_class_id
>= 0);
1255 if (id_field
&& bt_ctf_field_get_type_id(id_field
) == BT_CTF_FIELD_TYPE_ID_INTEGER
) {
1256 ret
= set_integer_field_value(id_field
, event_class_id
);
1258 BT_LOGW("Cannot set event header's `id` field's value: "
1259 "addr=%p, value=%" PRIu64
, id_field
,
1266 * The conditions to automatically set the timestamp are:
1268 * 1. The event header field "timestamp" exists and is an
1270 * 2. This stream's class has a registered clock (set with
1271 * bt_ctf_stream_class_set_clock()).
1272 * 3. The "timestamp" field is not set.
1274 timestamp_field
= bt_ctf_field_structure_get_field_by_name(
1275 (void *) event
->common
.header_field
, "timestamp");
1276 if (timestamp_field
&& stream_class
->clock
&&
1277 bt_ctf_field_get_type_id(id_field
) == BT_CTF_FIELD_TYPE_ID_INTEGER
&&
1278 !bt_ctf_field_is_set_recursive(timestamp_field
)) {
1279 mapped_clock_class
=
1280 bt_ctf_field_type_integer_get_mapped_clock_class(
1281 (void *) ((struct bt_field_common
*) timestamp_field
)->type
);
1282 if (mapped_clock_class
) {
1285 BT_ASSERT(mapped_clock_class
==
1286 stream_class
->clock
->clock_class
);
1287 ret
= bt_ctf_clock_get_value(
1288 stream_class
->clock
,
1290 BT_ASSERT(ret
== 0);
1291 ret
= set_integer_field_value(timestamp_field
,
1294 BT_LOGW("Cannot set event header's `timestamp` field's value: "
1295 "addr=%p, value=%" PRIu64
,
1296 timestamp_field
, timestamp
);
1302 BT_LOGV("Automatically populated event's header field: "
1303 "stream-addr=%p, stream-name=\"%s\", event-addr=%p",
1304 stream
, bt_ctf_stream_get_name(stream
), event
);
1308 bt_put(timestamp_field
);
1309 bt_put(mapped_clock_class
);
1313 int bt_ctf_stream_append_event(struct bt_ctf_stream
*stream
,
1314 struct bt_ctf_event
*event
)
1319 BT_LOGW_STR("Invalid parameter: stream is NULL.");
1325 BT_LOGW_STR("Invalid parameter: event is NULL.");
1330 if (stream
->pos
.fd
< 0) {
1331 BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
1336 BT_LOGV("Appending event to stream: "
1337 "stream-addr=%p, stream-name=\"%s\", event-addr=%p, "
1338 "event-class-name=\"%s\", event-class-id=%" PRId64
,
1339 stream
, bt_ctf_stream_get_name(stream
), event
,
1340 bt_event_class_common_get_name(
1341 bt_event_common_borrow_class(BT_TO_COMMON(event
))),
1342 bt_event_class_common_get_id(
1343 bt_event_common_borrow_class(BT_TO_COMMON(event
))));
1346 * The event is not supposed to have a parent stream at this
1347 * point. The only other way an event can have a parent stream
1348 * is if it was assigned when setting a packet to the event,
1349 * in which case the packet's stream is not a writer stream,
1350 * and thus the user is trying to append an event which belongs
1351 * to another stream.
1353 if (event
->common
.base
.parent
) {
1358 bt_object_set_parent(event
, stream
);
1359 BT_LOGV_STR("Automatically populating the header of the event to append.");
1360 ret
= auto_populate_event_header(stream
, event
);
1362 /* auto_populate_event_header() reports errors */
1366 /* Make sure the various scopes of the event are set */
1367 BT_LOGV_STR("Validating event to append.");
1368 ret
= bt_event_common_validate(BT_TO_COMMON(event
));
1373 /* Save the new event and freeze it */
1374 BT_LOGV_STR("Freezing the event to append.");
1375 bt_event_common_freeze(BT_TO_COMMON(event
));
1376 g_ptr_array_add(stream
->events
, event
);
1379 * Event had to hold a reference to its event class as long as it wasn't
1380 * part of the same trace hierarchy. From now on, the event and its
1381 * class share the same lifetime guarantees and the reference is no
1384 BT_LOGV_STR("Putting the event's class.");
1385 bt_put(event
->common
.class);
1386 BT_LOGV("Appended event to stream: "
1387 "stream-addr=%p, stream-name=\"%s\", event-addr=%p, "
1388 "event-class-name=\"%s\", event-class-id=%" PRId64
,
1389 stream
, bt_ctf_stream_get_name(stream
), event
,
1390 bt_event_class_common_get_name(
1391 bt_event_common_borrow_class(BT_TO_COMMON(event
))),
1392 bt_event_class_common_get_id(
1393 bt_event_common_borrow_class(BT_TO_COMMON(event
))));
1400 * Orphan the event; we were not successful in associating it to
1403 bt_object_set_parent(event
, NULL
);
1408 struct bt_ctf_field
*bt_ctf_stream_get_packet_context(struct bt_ctf_stream
*stream
)
1410 struct bt_ctf_field
*packet_context
= NULL
;
1413 BT_LOGW_STR("Invalid parameter: stream is NULL.");
1417 if (stream
->pos
.fd
< 0) {
1418 BT_LOGW("Invalid parameter: stream is not a CTF writer stream: "
1419 "stream-addr=%p, stream-name=\"%s\"", stream
,
1420 bt_ctf_stream_get_name(stream
));
1424 packet_context
= stream
->packet_context
;
1425 if (packet_context
) {
1426 bt_get(packet_context
);
1429 return packet_context
;
1432 int bt_ctf_stream_set_packet_context(struct bt_ctf_stream
*stream
,
1433 struct bt_ctf_field
*field
)
1436 struct bt_ctf_field_type
*field_type
;
1439 BT_LOGW_STR("Invalid parameter: stream is NULL.");
1444 if (stream
->pos
.fd
< 0) {
1445 BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
1450 field_type
= bt_ctf_field_get_type(field
);
1451 if (bt_field_type_common_compare((void *) field_type
,
1452 stream
->common
.stream_class
->packet_context_field_type
)) {
1453 BT_LOGW("Invalid parameter: packet context's field type is different from the stream's packet context field type: "
1454 "stream-addr=%p, stream-name=\"%s\", "
1455 "packet-context-field-addr=%p, "
1456 "packet-context-ft-addr=%p",
1457 stream
, bt_ctf_stream_get_name(stream
),
1464 bt_put(stream
->packet_context
);
1465 stream
->packet_context
= bt_get(field
);
1466 BT_LOGV("Set stream's packet context field: "
1467 "stream-addr=%p, stream-name=\"%s\", "
1468 "packet-context-field-addr=%p",
1469 stream
, bt_ctf_stream_get_name(stream
), field
);
1474 struct bt_ctf_field
*bt_ctf_stream_get_packet_header(struct bt_ctf_stream
*stream
)
1476 struct bt_ctf_field
*packet_header
= NULL
;
1479 BT_LOGW_STR("Invalid parameter: stream is NULL.");
1483 if (stream
->pos
.fd
< 0) {
1484 BT_LOGW("Invalid parameter: stream is not a CTF writer stream: "
1485 "stream-addr=%p, stream-name=\"%s\"", stream
,
1486 bt_ctf_stream_get_name(stream
));
1490 packet_header
= stream
->packet_header
;
1491 if (packet_header
) {
1492 bt_get(packet_header
);
1495 return packet_header
;
1498 int bt_ctf_stream_set_packet_header(struct bt_ctf_stream
*stream
,
1499 struct bt_ctf_field
*field
)
1502 struct bt_ctf_trace
*trace
= NULL
;
1503 struct bt_ctf_field_type
*field_type
= NULL
;
1506 BT_LOGW_STR("Invalid parameter: stream is NULL.");
1511 if (stream
->pos
.fd
< 0) {
1512 BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
1517 trace
= (struct bt_ctf_trace
*) bt_object_get_parent(stream
);
1520 if (trace
->common
.packet_header_field_type
) {
1521 BT_LOGW("Invalid parameter: setting no packet header but packet header field type is not NULL: "
1522 "stream-addr=%p, stream-name=\"%s\", "
1523 "packet-header-field-addr=%p, "
1524 "expected-ft-addr=%p",
1525 stream
, bt_ctf_stream_get_name(stream
),
1526 field
, trace
->common
.packet_header_field_type
);
1531 goto skip_validation
;
1534 field_type
= bt_ctf_field_get_type(field
);
1535 BT_ASSERT(field_type
);
1537 if (bt_field_type_common_compare((void *) field_type
,
1538 trace
->common
.packet_header_field_type
)) {
1539 BT_LOGW("Invalid parameter: packet header's field type is different from the stream's packet header field type: "
1540 "stream-addr=%p, stream-name=\"%s\", "
1541 "packet-header-field-addr=%p, "
1542 "packet-header-ft-addr=%p",
1543 stream
, bt_ctf_stream_get_name(stream
),
1550 bt_put(stream
->packet_header
);
1551 stream
->packet_header
= bt_get(field
);
1552 BT_LOGV("Set stream's packet header field: "
1553 "stream-addr=%p, stream-name=\"%s\", "
1554 "packet-header-field-addr=%p",
1555 stream
, bt_ctf_stream_get_name(stream
), field
);
1563 void reset_structure_field(struct bt_ctf_field
*structure
, const char *name
)
1565 struct bt_ctf_field
*member
;
1567 member
= bt_ctf_field_structure_get_field_by_name(structure
, name
);
1569 (void) bt_field_common_reset_recursive((void *) member
);
1574 int bt_ctf_stream_flush(struct bt_ctf_stream
*stream
)
1578 struct bt_ctf_stream_pos packet_context_pos
;
1579 struct bt_ctf_trace
*trace
;
1580 enum bt_ctf_byte_order native_byte_order
;
1581 bool has_packet_size
= false;
1584 BT_LOGW_STR("Invalid parameter: stream is NULL.");
1589 if (stream
->pos
.fd
< 0) {
1590 BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
1595 if (stream
->packet_context
) {
1596 struct bt_ctf_field
*packet_size_field
;
1598 packet_size_field
= bt_ctf_field_structure_get_field_by_name(
1599 stream
->packet_context
, "packet_size");
1600 has_packet_size
= (packet_size_field
!= NULL
);
1601 bt_put(packet_size_field
);
1604 if (stream
->flushed_packet_count
== 1) {
1605 if (!stream
->packet_context
) {
1606 BT_LOGW_STR("Cannot flush a stream which has no packet context field more than once.");
1611 if (!has_packet_size
) {
1612 BT_LOGW_STR("Cannot flush a stream which has no packet context's `packet_size` field more than once.");
1618 BT_LOGV("Flushing stream's current packet: stream-addr=%p, "
1619 "stream-name=\"%s\", packet-index=%u", stream
,
1620 bt_ctf_stream_get_name(stream
), stream
->flushed_packet_count
);
1621 trace
= BT_FROM_COMMON(bt_stream_class_common_borrow_trace(
1622 stream
->common
.stream_class
));
1624 native_byte_order
= bt_ctf_trace_get_native_byte_order(trace
);
1626 ret
= auto_populate_packet_header(stream
);
1628 BT_LOGW_STR("Cannot automatically populate the stream's packet header field.");
1633 ret
= auto_populate_packet_context(stream
, true);
1635 BT_LOGW_STR("Cannot automatically populate the stream's packet context field.");
1640 /* mmap the next packet */
1641 BT_LOGV("Seeking to the next packet: pos-offset=%" PRId64
,
1642 stream
->pos
.offset
);
1643 bt_ctf_stream_pos_packet_seek(&stream
->pos
, 0, SEEK_CUR
);
1644 BT_ASSERT(stream
->pos
.packet_size
% 8 == 0);
1646 if (stream
->packet_header
) {
1647 BT_LOGV_STR("Serializing packet header field.");
1648 ret
= bt_ctf_field_serialize_recursive(stream
->packet_header
,
1649 &stream
->pos
, native_byte_order
);
1651 BT_LOGW("Cannot serialize stream's packet header field: "
1652 "field-addr=%p", stream
->packet_header
);
1657 if (stream
->packet_context
) {
1658 /* Write packet context */
1659 memcpy(&packet_context_pos
, &stream
->pos
,
1660 sizeof(packet_context_pos
));
1661 BT_LOGV_STR("Serializing packet context field.");
1662 ret
= bt_ctf_field_serialize_recursive(stream
->packet_context
,
1663 &stream
->pos
, native_byte_order
);
1665 BT_LOGW("Cannot serialize stream's packet context field: "
1666 "field-addr=%p", stream
->packet_context
);
1671 BT_LOGV("Serializing events: count=%u", stream
->events
->len
);
1673 for (i
= 0; i
< stream
->events
->len
; i
++) {
1674 struct bt_ctf_event
*event
= g_ptr_array_index(
1676 struct bt_ctf_event_class
*event_class
=
1677 BT_FROM_COMMON(bt_event_common_borrow_class(
1678 BT_TO_COMMON(event
)));
1680 BT_LOGV("Serializing event: index=%zu, event-addr=%p, "
1681 "event-class-name=\"%s\", event-class-id=%" PRId64
", "
1682 "pos-offset=%" PRId64
", packet-size=%" PRIu64
,
1683 i
, event
, bt_ctf_event_class_get_name(event_class
),
1684 bt_ctf_event_class_get_id(event_class
),
1685 stream
->pos
.offset
, stream
->pos
.packet_size
);
1687 /* Write event header */
1688 if (event
->common
.header_field
) {
1689 BT_LOGV_STR("Serializing event's header field.");
1690 ret
= bt_ctf_field_serialize_recursive(
1691 (void *) event
->common
.header_field
,
1692 &stream
->pos
, native_byte_order
);
1694 BT_LOGW("Cannot serialize event's header field: "
1696 event
->common
.header_field
);
1701 /* Write stream event context */
1702 if (event
->common
.stream_event_context_field
) {
1703 BT_LOGV_STR("Serializing event's stream event context field.");
1704 ret
= bt_ctf_field_serialize_recursive(
1705 (void *) event
->common
.stream_event_context_field
,
1706 &stream
->pos
, native_byte_order
);
1708 BT_LOGW("Cannot serialize event's stream event context field: "
1710 event
->common
.stream_event_context_field
);
1715 /* Write event content */
1716 ret
= bt_ctf_event_serialize(event
,
1717 &stream
->pos
, native_byte_order
);
1719 /* bt_ctf_event_serialize() logs errors */
1724 if (!has_packet_size
&& stream
->pos
.offset
% 8 != 0) {
1725 BT_LOGW("Stream's packet context field type has no `packet_size` field, "
1726 "but current content size is not a multiple of 8 bits: "
1727 "content-size=%" PRId64
", "
1728 "packet-size=%" PRIu64
,
1730 stream
->pos
.packet_size
);
1735 BT_ASSERT(stream
->pos
.packet_size
% 8 == 0);
1738 * Remove extra padding bytes.
1740 stream
->pos
.packet_size
= (stream
->pos
.offset
+ 7) & ~7;
1742 if (stream
->packet_context
) {
1744 * The whole packet is serialized at this point. Make sure that,
1745 * if `packet_size` is missing, the current content size is
1746 * equal to the current packet size.
1748 struct bt_ctf_field
*field
= bt_ctf_field_structure_get_field_by_name(
1749 stream
->packet_context
, "content_size");
1753 if (stream
->pos
.offset
!= stream
->pos
.packet_size
) {
1754 BT_LOGW("Stream's packet context's `content_size` field is missing, "
1755 "but current packet's content size is not equal to its packet size: "
1756 "content-size=%" PRId64
", "
1757 "packet-size=%" PRIu64
,
1759 stream
->pos
.packet_size
);
1766 * Overwrite the packet context now that the stream
1767 * position's packet and content sizes have the correct
1770 * Copy base_mma as the packet may have been remapped
1771 * (e.g. when a packet is resized).
1773 packet_context_pos
.base_mma
= stream
->pos
.base_mma
;
1774 ret
= auto_populate_packet_context(stream
, false);
1776 BT_LOGW_STR("Cannot automatically populate the stream's packet context field.");
1781 BT_LOGV("Rewriting (serializing) packet context field.");
1782 ret
= bt_ctf_field_serialize_recursive(stream
->packet_context
,
1783 &packet_context_pos
, native_byte_order
);
1785 BT_LOGW("Cannot serialize stream's packet context field: "
1786 "field-addr=%p", stream
->packet_context
);
1791 g_ptr_array_set_size(stream
->events
, 0);
1792 stream
->flushed_packet_count
++;
1793 stream
->size
+= stream
->pos
.packet_size
/ CHAR_BIT
;
1796 /* Reset automatically-set fields. */
1797 if (stream
->packet_context
) {
1798 reset_structure_field(stream
->packet_context
, "timestamp_begin");
1799 reset_structure_field(stream
->packet_context
, "timestamp_end");
1800 reset_structure_field(stream
->packet_context
, "packet_size");
1801 reset_structure_field(stream
->packet_context
, "content_size");
1802 reset_structure_field(stream
->packet_context
, "events_discarded");
1807 * We failed to write the packet. Its size is therefore set to 0
1808 * to ensure the next mapping is done in the same place rather
1809 * than advancing by "stream->pos.packet_size", which would
1810 * leave a corrupted packet in the trace.
1812 stream
->pos
.packet_size
= 0;
1814 BT_LOGV("Flushed stream's current packet: content-size=%" PRId64
", "
1815 "packet-size=%" PRIu64
,
1816 stream
->pos
.offset
, stream
->pos
.packet_size
);
1824 void bt_ctf_stream_destroy(struct bt_object
*obj
)
1826 struct bt_ctf_stream
*stream
= (void *) obj
;
1828 BT_LOGD("Destroying CTF writer stream object: addr=%p, name=\"%s\"",
1829 stream
, bt_ctf_stream_get_name(stream
));
1831 bt_stream_common_finalize(BT_TO_COMMON(stream
));
1832 (void) bt_ctf_stream_pos_fini(&stream
->pos
);
1834 if (stream
->pos
.fd
>= 0) {
1838 * Truncate the file's size to the minimum required to fit the
1839 * last packet as we might have grown it too much on the last
1843 ret
= ftruncate(stream
->pos
.fd
, stream
->size
);
1844 } while (ret
== -1 && errno
== EINTR
);
1846 BT_LOGE_ERRNO("Failed to truncate stream file",
1847 ": ret=%d, size=%" PRIu64
,
1848 ret
, (uint64_t) stream
->size
);
1851 if (close(stream
->pos
.fd
)) {
1852 BT_LOGE_ERRNO("Failed to close stream file",
1857 if (stream
->events
) {
1858 BT_LOGD_STR("Putting events.");
1859 g_ptr_array_free(stream
->events
, TRUE
);
1862 BT_LOGD_STR("Putting packet header field.");
1863 bt_put(stream
->packet_header
);
1864 BT_LOGD_STR("Putting packet context field.");
1865 bt_put(stream
->packet_context
);
1870 int _set_structure_field_integer(struct bt_ctf_field
*structure
, char *name
,
1871 uint64_t value
, bt_bool force
)
1874 struct bt_ctf_field_type
*field_type
= NULL
;
1875 struct bt_ctf_field
*integer
;
1877 BT_ASSERT(structure
);
1880 integer
= bt_ctf_field_structure_get_field_by_name(structure
, name
);
1882 /* Field not found, not an error. */
1883 BT_LOGV("Field not found: struct-field-addr=%p, "
1884 "name=\"%s\", force=%d", structure
, name
, force
);
1888 /* Make sure the payload has not already been set. */
1889 if (!force
&& bt_ctf_field_is_set_recursive(integer
)) {
1890 /* Payload already set, not an error */
1891 BT_LOGV("Field's payload is already set: struct-field-addr=%p, "
1892 "name=\"%s\", force=%d", structure
, name
, force
);
1896 field_type
= bt_ctf_field_get_type(integer
);
1897 BT_ASSERT(field_type
);
1898 if (bt_ctf_field_type_get_type_id(field_type
) != BT_CTF_FIELD_TYPE_ID_INTEGER
) {
1900 * The user most likely meant for us to populate this field
1901 * automatically. However, we can only do this if the field
1902 * is an integer. Return an error.
1904 BT_LOGW("Invalid parameter: field's type is not an integer field type: "
1905 "field-addr=%p, ft-addr=%p, ft-id=%s",
1906 integer
, field_type
,
1907 bt_common_field_type_id_string((int)
1908 bt_ctf_field_type_get_type_id(field_type
)));
1913 if (bt_ctf_field_type_integer_is_signed(field_type
)) {
1914 ret
= bt_ctf_field_integer_signed_set_value(integer
,
1917 ret
= bt_ctf_field_integer_unsigned_set_value(integer
, value
);
1919 ret
= !ret
? 1 : ret
;
1927 * Returns the following codes:
1928 * 1 if the field was found and set,
1929 * 0 if nothing was done (field not found, or was already set),
1930 * <0 if an error was encoutered
1933 int try_set_structure_field_integer(struct bt_ctf_field
*structure
, char *name
,
1936 return _set_structure_field_integer(structure
, name
, value
, BT_FALSE
);
1939 struct bt_ctf_stream_class
*bt_ctf_stream_get_class(
1940 struct bt_ctf_stream
*stream
)
1942 return BT_FROM_COMMON(bt_stream_common_get_class(BT_TO_COMMON(stream
)));
1945 const char *bt_ctf_stream_get_name(struct bt_ctf_stream
*stream
)
1947 return bt_stream_common_get_name(BT_TO_COMMON(stream
));
1950 int64_t bt_ctf_stream_get_id(struct bt_ctf_stream
*stream
)
1952 return bt_stream_common_get_id(BT_TO_COMMON(stream
));