2 * SPDX-License-Identifier: MIT
4 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
8 #define BT_LOG_TAG "CTF-WRITER/STREAM-CLASS"
14 #include <babeltrace2-ctf-writer/event.h>
15 #include <babeltrace2-ctf-writer/object.h>
16 #include <babeltrace2-ctf-writer/trace.h>
17 #include <babeltrace2-ctf-writer/utils.h>
19 #include "common/align.h"
20 #include "common/assert.h"
21 #include "compat/compiler.h"
22 #include "compat/endian.h"
24 #include "assert-pre.h"
25 #include "clock-class.h"
26 #include "event-class.h"
29 #include "field-types.h"
30 #include "field-wrapper.h"
31 #include "stream-class.h"
33 #include "validation.h"
38 int bt_ctf_stream_class_common_initialize(struct bt_ctf_stream_class_common
*stream_class
,
39 const char *name
, bt_ctf_object_release_func release_func
)
41 BT_LOGD("Initializing common stream class object: name=\"%s\"", name
);
43 bt_ctf_object_init_shared_with_parent(&stream_class
->base
, release_func
);
44 stream_class
->name
= g_string_new(name
);
45 stream_class
->event_classes
= g_ptr_array_new_with_free_func(
46 (GDestroyNotify
) bt_ctf_object_try_spec_release
);
47 if (!stream_class
->event_classes
) {
48 BT_LOGE_STR("Failed to allocate a GPtrArray.");
52 stream_class
->event_classes_ht
= g_hash_table_new_full(g_int64_hash
,
53 g_int64_equal
, g_free
, NULL
);
54 if (!stream_class
->event_classes_ht
) {
55 BT_LOGE_STR("Failed to allocate a GHashTable.");
59 BT_LOGD("Initialized common stream class object: addr=%p, name=\"%s\"",
68 void bt_ctf_stream_class_common_finalize(struct bt_ctf_stream_class_common
*stream_class
)
70 BT_LOGD("Finalizing common stream class: addr=%p, name=\"%s\", id=%" PRId64
,
71 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
72 bt_ctf_stream_class_common_get_id(stream_class
));
73 bt_ctf_object_put_ref(stream_class
->clock_class
);
75 if (stream_class
->event_classes_ht
) {
76 g_hash_table_destroy(stream_class
->event_classes_ht
);
78 if (stream_class
->event_classes
) {
79 BT_LOGD_STR("Destroying event classes.");
80 g_ptr_array_free(stream_class
->event_classes
, TRUE
);
83 if (stream_class
->name
) {
84 g_string_free(stream_class
->name
, TRUE
);
87 BT_LOGD_STR("Putting event header field type.");
88 bt_ctf_object_put_ref(stream_class
->event_header_field_type
);
89 BT_LOGD_STR("Putting packet context field type.");
90 bt_ctf_object_put_ref(stream_class
->packet_context_field_type
);
91 BT_LOGD_STR("Putting event context field type.");
92 bt_ctf_object_put_ref(stream_class
->event_context_field_type
);
96 void event_class_exists(gpointer element
, gpointer query
)
98 struct bt_ctf_event_class_common
*event_class_a
= element
;
99 struct bt_ctf_search_query
*search_query
= query
;
100 struct bt_ctf_event_class_common
*event_class_b
= search_query
->value
;
103 if (search_query
->value
== element
) {
104 search_query
->found
= 1;
109 * Two event classes cannot share the same ID in a given
112 id_a
= bt_ctf_event_class_common_get_id(event_class_a
);
113 id_b
= bt_ctf_event_class_common_get_id(event_class_b
);
115 if (id_a
< 0 || id_b
< 0) {
116 /* at least one ID is not set: will be automatically set later */
121 BT_LOGW("Event class with this ID already exists in the stream class: "
122 "id=%" PRId64
", name=\"%s\"",
123 id_a
, bt_ctf_event_class_common_get_name(event_class_a
));
124 search_query
->found
= 1;
133 int bt_ctf_stream_class_common_add_event_class(
134 struct bt_ctf_stream_class_common
*stream_class
,
135 struct bt_ctf_event_class_common
*event_class
,
136 bt_ctf_validation_flag_copy_field_type_func copy_field_type_func
)
139 int64_t *event_id
= NULL
;
140 struct bt_ctf_trace_common
*trace
= NULL
;
141 struct bt_ctf_stream_class_common
*old_stream_class
= NULL
;
142 struct bt_ctf_validation_output validation_output
= { 0 };
143 struct bt_ctf_field_type_common
*packet_header_type
= NULL
;
144 struct bt_ctf_field_type_common
*packet_context_type
= NULL
;
145 struct bt_ctf_field_type_common
*event_header_type
= NULL
;
146 struct bt_ctf_field_type_common
*stream_event_ctx_type
= NULL
;
147 struct bt_ctf_field_type_common
*event_context_type
= NULL
;
148 struct bt_ctf_field_type_common
*event_payload_type
= NULL
;
149 const enum bt_ctf_validation_flag validation_flags
=
150 BT_CTF_VALIDATION_FLAG_EVENT
;
151 struct bt_ctf_clock_class
*expected_clock_class
= NULL
;
152 struct bt_ctf_search_query query
= { .value
= event_class
, .found
= 0 };
154 BT_ASSERT_DBG(copy_field_type_func
);
156 if (!stream_class
|| !event_class
) {
157 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
158 "stream-class-addr=%p, event-class-addr=%p",
159 stream_class
, event_class
);
164 BT_LOGD("Adding event class to stream class: "
165 "stream-class-addr=%p, stream-class-name=\"%s\", "
166 "stream-class-id=%" PRId64
", event-class-addr=%p, "
167 "event-class-name=\"%s\", event-class-id=%" PRId64
,
168 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
169 bt_ctf_stream_class_common_get_id(stream_class
),
171 bt_ctf_event_class_common_get_name(event_class
),
172 bt_ctf_event_class_common_get_id(event_class
));
173 trace
= bt_ctf_stream_class_common_borrow_trace(stream_class
);
175 if (stream_class
->frozen
) {
177 * We only check that the event class to be added has a
178 * single class which matches the stream class's
179 * expected clock class if the stream class is frozen.
180 * If it's not, then this event class is added "as is"
181 * and the validation will be performed when calling
182 * either bt_ctf_trace_add_stream_class() or
183 * bt_ctf_event_create(). This is because the stream class's
184 * field types (packet context, event header, event
185 * context) could change before the next call to one of
186 * those two functions.
188 expected_clock_class
= bt_ctf_object_get_ref(stream_class
->clock_class
);
191 * At this point, `expected_clock_class` can be NULL,
192 * and bt_ctf_event_class_validate_single_clock_class()
195 ret
= bt_ctf_event_class_common_validate_single_clock_class(
196 event_class
, &expected_clock_class
);
198 BT_LOGW("Event class contains a field type which is not "
199 "recursively mapped to its stream class's "
200 "expected clock class: "
201 "stream-class-addr=%p, "
202 "stream-class-id=%" PRId64
", "
203 "stream-class-name=\"%s\", "
204 "expected-clock-class-addr=%p, "
205 "expected-clock-class-name=\"%s\"",
207 bt_ctf_stream_class_common_get_id(stream_class
),
208 bt_ctf_stream_class_common_get_name(stream_class
),
209 expected_clock_class
,
210 expected_clock_class
?
211 bt_ctf_clock_class_get_name(expected_clock_class
) :
217 event_id
= g_new(int64_t, 1);
219 BT_LOGE_STR("Failed to allocate one int64_t.");
224 /* Check for duplicate event classes */
225 g_ptr_array_foreach(stream_class
->event_classes
, event_class_exists
,
228 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
233 old_stream_class
= bt_ctf_event_class_common_borrow_stream_class(event_class
);
234 if (old_stream_class
) {
235 /* Event class is already associated to a stream class. */
236 BT_LOGW("Event class is already part of another stream class: "
237 "event-class-stream-class-addr=%p, "
238 "event-class-stream-class-name=\"%s\", "
239 "event-class-stream-class-id=%" PRId64
,
241 bt_ctf_stream_class_common_get_name(old_stream_class
),
242 bt_ctf_stream_class_common_get_id(old_stream_class
));
249 * If the stream class is associated with a trace, then
250 * both those objects are frozen. Also, this event class
251 * is about to be frozen.
253 * Therefore the event class must be validated here.
254 * The trace and stream class should be valid at this
257 BT_ASSERT_DBG(trace
->valid
);
258 BT_ASSERT_DBG(stream_class
->valid
);
260 bt_ctf_trace_common_borrow_packet_header_field_type(trace
);
261 packet_context_type
=
262 bt_ctf_stream_class_common_borrow_packet_context_field_type(
265 bt_ctf_stream_class_common_borrow_event_header_field_type(
267 stream_event_ctx_type
=
268 bt_ctf_stream_class_common_borrow_event_context_field_type(
271 bt_ctf_event_class_common_borrow_context_field_type(
274 bt_ctf_event_class_common_borrow_payload_field_type(
276 ret
= bt_ctf_validate_class_types(
277 trace
->environment
, packet_header_type
,
278 packet_context_type
, event_header_type
,
279 stream_event_ctx_type
, event_context_type
,
280 event_payload_type
, trace
->valid
,
281 stream_class
->valid
, event_class
->valid
,
282 &validation_output
, validation_flags
,
283 copy_field_type_func
);
287 * This means something went wrong during the
288 * validation process, not that the objects are
291 BT_LOGE("Failed to validate event class: ret=%d", ret
);
295 if ((validation_output
.valid_flags
& validation_flags
) !=
297 /* Invalid event class */
298 BT_LOGW("Invalid trace, stream class, or event class: "
300 validation_output
.valid_flags
);
306 /* Only set an event ID if none was explicitly set before */
307 *event_id
= bt_ctf_event_class_common_get_id(event_class
);
309 BT_LOGT("Event class has no ID: automatically setting it: "
310 "id=%" PRId64
, stream_class
->next_event_id
);
312 if (bt_ctf_event_class_common_set_id(event_class
,
313 stream_class
->next_event_id
)) {
314 BT_LOGE("Cannot set event class's ID: id=%" PRId64
,
315 stream_class
->next_event_id
);
319 stream_class
->next_event_id
++;
320 *event_id
= stream_class
->next_event_id
;
323 bt_ctf_object_set_parent(&event_class
->base
, &stream_class
->base
);
327 * At this point we know that the function will be
328 * successful. Therefore we can replace the event
329 * class's field types with what's in the validation
330 * output structure and mark this event class as valid.
332 bt_ctf_validation_replace_types(NULL
, NULL
, event_class
,
333 &validation_output
, validation_flags
);
334 event_class
->valid
= 1;
337 * Put what was not moved in
338 * bt_ctf_validation_replace_types().
340 bt_ctf_validation_output_put_types(&validation_output
);
343 /* Add to the event classes of the stream class */
344 g_ptr_array_add(stream_class
->event_classes
, event_class
);
345 g_hash_table_insert(stream_class
->event_classes_ht
, event_id
,
349 /* Freeze the event class */
350 bt_ctf_event_class_common_freeze(event_class
);
353 * It is safe to set the stream class's unique clock class
354 * now if the stream class is frozen.
356 if (stream_class
->frozen
&& expected_clock_class
) {
357 BT_ASSERT_DBG(!stream_class
->clock_class
||
358 stream_class
->clock_class
== expected_clock_class
);
359 BT_CTF_OBJECT_MOVE_REF(stream_class
->clock_class
, expected_clock_class
);
362 BT_LOGD("Added event class to stream class: "
363 "stream-class-addr=%p, stream-class-name=\"%s\", "
364 "stream-class-id=%" PRId64
", event-class-addr=%p, "
365 "event-class-name=\"%s\", event-class-id=%" PRId64
,
366 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
367 bt_ctf_stream_class_common_get_id(stream_class
),
369 bt_ctf_event_class_common_get_name(event_class
),
370 bt_ctf_event_class_common_get_id(event_class
));
373 bt_ctf_validation_output_put_types(&validation_output
);
374 bt_ctf_object_put_ref(expected_clock_class
);
380 int64_t get_event_class_count(void *element
)
382 return bt_ctf_stream_class_get_event_class_count(
383 (struct bt_ctf_stream_class
*) element
);
387 void *get_event_class(void *element
, int i
)
389 return bt_ctf_stream_class_get_event_class_by_index(
390 (struct bt_ctf_stream_class
*) element
, i
);
394 int visit_event_class(void *object
, bt_ctf_visitor visitor
,void *data
)
396 struct bt_ctf_visitor_object obj
= {
398 .type
= BT_CTF_VISITOR_OBJECT_TYPE_EVENT_CLASS
401 return visitor(&obj
, data
);
405 int bt_ctf_stream_class_common_visit(struct bt_ctf_stream_class_common
*stream_class
,
406 bt_ctf_visitor visitor
, void *data
)
409 struct bt_ctf_visitor_object obj
= {
410 .object
= stream_class
,
411 .type
= BT_CTF_VISITOR_OBJECT_TYPE_STREAM_CLASS
414 if (!stream_class
|| !visitor
) {
415 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
416 "stream-class-addr=%p, visitor=%p",
417 stream_class
, visitor
);
422 ret
= bt_ctf_visitor_helper(&obj
, get_event_class_count
,
424 visit_event_class
, visitor
, data
);
425 BT_LOGT("bt_ctf_visitor_helper() returned: ret=%d", ret
);
432 int bt_ctf_stream_class_visit(struct bt_ctf_stream_class
*stream_class
,
433 bt_ctf_visitor visitor
, void *data
)
435 return bt_ctf_stream_class_common_visit(BT_CTF_FROM_COMMON(stream_class
),
440 void bt_ctf_stream_class_common_freeze(struct bt_ctf_stream_class_common
*stream_class
)
442 if (!stream_class
|| stream_class
->frozen
) {
446 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64
,
447 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
448 bt_ctf_stream_class_common_get_id(stream_class
));
449 stream_class
->frozen
= 1;
450 bt_ctf_field_type_common_freeze(stream_class
->event_header_field_type
);
451 bt_ctf_field_type_common_freeze(stream_class
->packet_context_field_type
);
452 bt_ctf_field_type_common_freeze(stream_class
->event_context_field_type
);
453 bt_ctf_clock_class_freeze(stream_class
->clock_class
);
457 int bt_ctf_stream_class_common_validate_single_clock_class(
458 struct bt_ctf_stream_class_common
*stream_class
,
459 struct bt_ctf_clock_class
**expected_clock_class
)
464 BT_ASSERT_DBG(stream_class
);
465 BT_ASSERT_DBG(expected_clock_class
);
466 ret
= bt_ctf_field_type_common_validate_single_clock_class(
467 stream_class
->packet_context_field_type
,
468 expected_clock_class
);
470 BT_LOGW("Stream class's packet context field type "
471 "is not recursively mapped to the "
472 "expected clock class: "
473 "stream-class-addr=%p, "
474 "stream-class-name=\"%s\", "
475 "stream-class-id=%" PRId64
", "
478 bt_ctf_stream_class_common_get_name(stream_class
),
480 stream_class
->packet_context_field_type
);
484 ret
= bt_ctf_field_type_common_validate_single_clock_class(
485 stream_class
->event_header_field_type
,
486 expected_clock_class
);
488 BT_LOGW("Stream class's event header field type "
489 "is not recursively mapped to the "
490 "expected clock class: "
491 "stream-class-addr=%p, "
492 "stream-class-name=\"%s\", "
493 "stream-class-id=%" PRId64
", "
496 bt_ctf_stream_class_common_get_name(stream_class
),
498 stream_class
->event_header_field_type
);
502 ret
= bt_ctf_field_type_common_validate_single_clock_class(
503 stream_class
->event_context_field_type
,
504 expected_clock_class
);
506 BT_LOGW("Stream class's event context field type "
507 "is not recursively mapped to the "
508 "expected clock class: "
509 "stream-class-addr=%p, "
510 "stream-class-name=\"%s\", "
511 "stream-class-id=%" PRId64
", "
514 bt_ctf_stream_class_common_get_name(stream_class
),
516 stream_class
->event_context_field_type
);
520 for (i
= 0; i
< stream_class
->event_classes
->len
; i
++) {
521 struct bt_ctf_event_class_common
*event_class
=
522 g_ptr_array_index(stream_class
->event_classes
, i
);
524 BT_ASSERT_DBG(event_class
);
525 ret
= bt_ctf_event_class_common_validate_single_clock_class(
526 event_class
, expected_clock_class
);
528 BT_LOGW("Stream class's event class contains a "
529 "field type which is not recursively mapped to "
530 "the expected clock class: "
531 "stream-class-addr=%p, "
532 "stream-class-name=\"%s\", "
533 "stream-class-id=%" PRId64
,
535 bt_ctf_stream_class_common_get_name(stream_class
),
546 int init_event_header(struct bt_ctf_stream_class
*stream_class
)
549 struct bt_ctf_field_type
*event_header_type
=
550 bt_ctf_field_type_structure_create();
551 struct bt_ctf_field_type
*_uint32_t
=
552 get_field_type(FIELD_TYPE_ALIAS_UINT32_T
);
553 struct bt_ctf_field_type
*_uint64_t
=
554 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
556 if (!event_header_type
) {
557 BT_LOGE_STR("Cannot create empty structure field type.");
562 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
565 BT_LOGE_STR("Cannot add `id` field to event header field type.");
569 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
570 _uint64_t
, "timestamp");
572 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
576 bt_ctf_object_put_ref(stream_class
->common
.event_header_field_type
);
577 stream_class
->common
.event_header_field_type
=
578 (void *) event_header_type
;
579 event_header_type
= NULL
;
583 bt_ctf_object_put_ref(event_header_type
);
586 bt_ctf_object_put_ref(_uint32_t
);
587 bt_ctf_object_put_ref(_uint64_t
);
592 int init_packet_context(struct bt_ctf_stream_class
*stream_class
)
595 struct bt_ctf_field_type
*packet_context_type
=
596 bt_ctf_field_type_structure_create();
597 struct bt_ctf_field_type
*_uint64_t
=
598 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
599 struct bt_ctf_field_type
*ts_begin_end_uint64_t
= NULL
;
601 if (!packet_context_type
) {
602 BT_LOGE_STR("Cannot create empty structure field type.");
607 ts_begin_end_uint64_t
= bt_ctf_field_type_copy(_uint64_t
);
608 if (!ts_begin_end_uint64_t
) {
609 BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
615 * We create a stream packet context as proposed in the CTF
618 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
619 ts_begin_end_uint64_t
, "timestamp_begin");
621 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
625 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
626 ts_begin_end_uint64_t
, "timestamp_end");
628 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
632 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
633 _uint64_t
, "content_size");
635 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
639 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
640 _uint64_t
, "packet_size");
642 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
646 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
647 _uint64_t
, "events_discarded");
649 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
653 bt_ctf_object_put_ref(stream_class
->common
.packet_context_field_type
);
654 stream_class
->common
.packet_context_field_type
=
655 (void *) packet_context_type
;
656 packet_context_type
= NULL
;
660 bt_ctf_object_put_ref(packet_context_type
);
664 bt_ctf_object_put_ref(_uint64_t
);
665 bt_ctf_object_put_ref(ts_begin_end_uint64_t
);
670 void bt_ctf_stream_class_destroy(struct bt_ctf_object
*obj
)
672 struct bt_ctf_stream_class
*stream_class
;
674 stream_class
= (void *) obj
;
675 BT_LOGD("Destroying CTF writer stream class: addr=%p, name=\"%s\", id=%" PRId64
,
676 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
677 bt_ctf_stream_class_get_id(stream_class
));
678 bt_ctf_stream_class_common_finalize(BT_CTF_TO_COMMON(stream_class
));
679 bt_ctf_object_put_ref(stream_class
->clock
);
680 g_free(stream_class
);
683 struct bt_ctf_stream_class
*bt_ctf_stream_class_create(const char *name
)
685 struct bt_ctf_stream_class
*stream_class
;
688 BT_LOGD("Creating CTF writer stream class object: name=\"%s\"", name
);
689 stream_class
= g_new0(struct bt_ctf_stream_class
, 1);
691 BT_LOGE_STR("Failed to allocate one CTF writer stream class.");
695 ret
= bt_ctf_stream_class_common_initialize(BT_CTF_TO_COMMON(stream_class
),
696 name
, bt_ctf_stream_class_destroy
);
698 /* bt_ctf_stream_class_common_initialize() logs errors */
702 ret
= init_event_header(stream_class
);
704 BT_LOGE_STR("Cannot initialize stream class's event header field type.");
708 ret
= init_packet_context(stream_class
);
710 BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
714 BT_LOGD("Created CTF writer stream class object: addr=%p, name=\"%s\"",
719 BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_class
);
724 int try_map_clock_class(struct bt_ctf_stream_class
*stream_class
,
725 struct bt_ctf_field_type
*parent_ft
, const char *field_name
)
727 struct bt_ctf_clock_class
*mapped_clock_class
= NULL
;
729 struct bt_ctf_field_type
*ft
=
730 bt_ctf_field_type_structure_get_field_type_by_name(parent_ft
,
733 BT_ASSERT_DBG(stream_class
->clock
);
736 /* Field does not exist: not an error */
740 BT_ASSERT_DBG(((struct bt_ctf_field_type_common
*) ft
)->id
==
741 BT_CTF_FIELD_TYPE_ID_INTEGER
);
743 bt_ctf_field_type_integer_get_mapped_clock_class(ft
);
744 if (!mapped_clock_class
) {
745 struct bt_ctf_field_type
*ft_copy
;
747 if (!stream_class
->clock
) {
748 BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
749 "stream-class-addr=%p, stream-class-name=\"%s\", "
750 "stream-class-id=%" PRId64
", ft-addr=%p",
752 bt_ctf_stream_class_get_name(stream_class
),
753 bt_ctf_stream_class_get_id(stream_class
), ft
);
758 ft_copy
= bt_ctf_field_type_copy(ft
);
760 BT_LOGE("Failed to copy integer field type: ft-addr=%p",
766 ret
= bt_ctf_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
767 (void *) ft_copy
, stream_class
->clock
->clock_class
);
768 BT_ASSERT_DBG(ret
== 0);
770 ret
= bt_ctf_field_type_common_structure_replace_field(
771 (void *) parent_ft
, field_name
, (void *) ft_copy
);
772 bt_ctf_object_put_ref(ft_copy
);
773 BT_LOGT("Automatically mapped field type to stream class's clock class: "
774 "stream-class-addr=%p, stream-class-name=\"%s\", "
775 "stream-class-id=%" PRId64
", ft-addr=%p, "
778 bt_ctf_stream_class_get_name(stream_class
),
779 bt_ctf_stream_class_get_id(stream_class
), ft
, ft_copy
);
783 bt_ctf_object_put_ref(ft
);
784 bt_ctf_object_put_ref(mapped_clock_class
);
789 int bt_ctf_stream_class_map_clock_class(
790 struct bt_ctf_stream_class
*stream_class
,
791 struct bt_ctf_field_type
*packet_context_type
,
792 struct bt_ctf_field_type
*event_header_type
)
796 BT_ASSERT_DBG(stream_class
);
798 if (!stream_class
->clock
) {
799 /* No clock class to map to */
803 if (packet_context_type
) {
804 if (try_map_clock_class(stream_class
, packet_context_type
,
805 "timestamp_begin")) {
806 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
811 if (try_map_clock_class(stream_class
, packet_context_type
,
813 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
819 if (event_header_type
) {
820 if (try_map_clock_class(stream_class
, event_header_type
,
822 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
832 struct bt_ctf_clock
*bt_ctf_stream_class_get_clock(
833 struct bt_ctf_stream_class
*stream_class
)
835 struct bt_ctf_clock
*clock
= NULL
;
838 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
842 if (!stream_class
->clock
) {
843 BT_LOGT("Stream class has no clock: "
844 "addr=%p, name=\"%s\", id=%" PRId64
,
846 bt_ctf_stream_class_get_name(stream_class
),
847 bt_ctf_stream_class_get_id(stream_class
));
851 clock
= bt_ctf_object_get_ref(stream_class
->clock
);
857 int bt_ctf_stream_class_set_clock(
858 struct bt_ctf_stream_class
*stream_class
,
859 struct bt_ctf_clock
*clock
)
863 if (!stream_class
|| !clock
) {
864 BT_LOGW("Invalid parameter: stream class or clock is NULL: "
865 "stream-class-addr=%p, clock-addr=%p",
866 stream_class
, clock
);
871 if (stream_class
->common
.frozen
) {
872 BT_LOGW("Invalid parameter: stream class is frozen: "
873 "addr=%p, name=\"%s\", id=%" PRId64
,
875 bt_ctf_stream_class_get_name(stream_class
),
876 bt_ctf_stream_class_get_id(stream_class
));
881 /* Replace the current clock of this stream class. */
882 bt_ctf_object_put_ref(stream_class
->clock
);
883 stream_class
->clock
= bt_ctf_object_get_ref(clock
);
884 BT_LOGT("Set stream class's clock: "
885 "addr=%p, name=\"%s\", id=%" PRId64
", "
886 "clock-addr=%p, clock-name=\"%s\"",
888 bt_ctf_stream_class_get_name(stream_class
),
889 bt_ctf_stream_class_get_id(stream_class
),
891 bt_ctf_clock_get_name(stream_class
->clock
));
898 int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class
*stream_class
,
899 struct metadata_context
*context
)
903 struct bt_ctf_trace
*trace
;
904 struct bt_ctf_field_type
*packet_header_type
= NULL
;
906 BT_LOGD("Serializing stream class's metadata: "
907 "stream-class-addr=%p, stream-class-name=\"%s\", "
908 "stream-class-id=%" PRId64
", metadata-context-addr=%p",
910 bt_ctf_stream_class_get_name(stream_class
),
911 bt_ctf_stream_class_get_id(stream_class
), context
);
912 g_string_assign(context
->field_name
, "");
913 context
->current_indentation_level
= 1;
914 if (!stream_class
->common
.id_set
) {
915 BT_LOGW_STR("Stream class's ID is not set.");
920 g_string_append(context
->string
, "stream {\n");
923 * The reference to the trace is only borrowed since the
924 * serialization of the stream class might have been triggered
925 * by the trace's destruction. In such a case, the trace's
926 * reference count would, unexepectedly, go through the sequence
927 * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
930 trace
= BT_CTF_FROM_COMMON(bt_ctf_stream_class_common_borrow_trace(
931 BT_CTF_TO_COMMON(stream_class
)));
932 BT_ASSERT_DBG(trace
);
933 packet_header_type
= bt_ctf_trace_get_packet_header_field_type(trace
);
935 if (packet_header_type
) {
936 struct bt_ctf_field_type
*stream_id_type
;
939 bt_ctf_field_type_structure_get_field_type_by_name(
940 packet_header_type
, "stream_id");
941 if (stream_id_type
) {
943 * Only set the stream's id if the trace's packet header
944 * contains a stream_id field. This field is only
945 * needed if the trace contains only one stream
948 g_string_append_printf(context
->string
,
949 "\tid = %" PRId64
";\n",
950 stream_class
->common
.id
);
952 bt_ctf_object_put_ref(stream_id_type
);
954 if (stream_class
->common
.event_header_field_type
) {
955 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
956 g_string_append(context
->string
, "\tevent.header := ");
957 ret
= bt_ctf_field_type_serialize_recursive(
958 (void *) stream_class
->common
.event_header_field_type
,
961 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
965 g_string_append(context
->string
, ";");
969 if (stream_class
->common
.packet_context_field_type
) {
970 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
971 g_string_append(context
->string
, "\n\n\tpacket.context := ");
972 ret
= bt_ctf_field_type_serialize_recursive(
973 (void *) stream_class
->common
.packet_context_field_type
,
976 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
980 g_string_append(context
->string
, ";");
983 if (stream_class
->common
.event_context_field_type
) {
984 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
985 g_string_append(context
->string
, "\n\n\tevent.context := ");
986 ret
= bt_ctf_field_type_serialize_recursive(
987 (void *) stream_class
->common
.event_context_field_type
,
990 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
994 g_string_append(context
->string
, ";");
997 g_string_append(context
->string
, "\n};\n\n");
999 for (i
= 0; i
< stream_class
->common
.event_classes
->len
; i
++) {
1000 struct bt_ctf_event_class
*event_class
=
1001 stream_class
->common
.event_classes
->pdata
[i
];
1003 ret
= bt_ctf_event_class_serialize(event_class
, context
);
1005 BT_LOGW("Cannot serialize event class's metadata: "
1006 "event-class-addr=%p, event-class-name=\"%s\", "
1007 "event-class-id=%" PRId64
,
1009 bt_ctf_event_class_get_name(event_class
),
1010 bt_ctf_event_class_get_id(event_class
));
1016 bt_ctf_object_put_ref(packet_header_type
);
1017 context
->current_indentation_level
= 0;
1021 struct bt_ctf_trace
*bt_ctf_stream_class_get_trace(
1022 struct bt_ctf_stream_class
*stream_class
)
1024 return bt_ctf_object_get_ref(bt_ctf_stream_class_common_borrow_trace(
1025 BT_CTF_TO_COMMON(stream_class
)));
1028 const char *bt_ctf_stream_class_get_name(
1029 struct bt_ctf_stream_class
*stream_class
)
1031 return bt_ctf_stream_class_common_get_name(BT_CTF_TO_COMMON(stream_class
));
1034 int bt_ctf_stream_class_set_name(
1035 struct bt_ctf_stream_class
*stream_class
, const char *name
)
1037 return bt_ctf_stream_class_common_set_name(BT_CTF_TO_COMMON(stream_class
),
1041 int64_t bt_ctf_stream_class_get_id(
1042 struct bt_ctf_stream_class
*stream_class
)
1044 return bt_ctf_stream_class_common_get_id(BT_CTF_TO_COMMON(stream_class
));
1047 int bt_ctf_stream_class_set_id(
1048 struct bt_ctf_stream_class
*stream_class
, uint64_t id
)
1050 return bt_ctf_stream_class_common_set_id(BT_CTF_TO_COMMON(stream_class
), id
);
1053 struct bt_ctf_field_type
*bt_ctf_stream_class_get_packet_context_type(
1054 struct bt_ctf_stream_class
*stream_class
)
1056 return bt_ctf_object_get_ref(
1057 bt_ctf_stream_class_common_borrow_packet_context_field_type(
1058 BT_CTF_TO_COMMON(stream_class
)));
1061 int bt_ctf_stream_class_set_packet_context_type(
1062 struct bt_ctf_stream_class
*stream_class
,
1063 struct bt_ctf_field_type
*packet_context_type
)
1065 return bt_ctf_stream_class_common_set_packet_context_field_type(
1066 BT_CTF_TO_COMMON(stream_class
), (void *) packet_context_type
);
1069 struct bt_ctf_field_type
*
1070 bt_ctf_stream_class_get_event_header_type(
1071 struct bt_ctf_stream_class
*stream_class
)
1073 return bt_ctf_object_get_ref(
1074 bt_ctf_stream_class_common_borrow_event_header_field_type(
1075 BT_CTF_TO_COMMON(stream_class
)));
1078 int bt_ctf_stream_class_set_event_header_type(
1079 struct bt_ctf_stream_class
*stream_class
,
1080 struct bt_ctf_field_type
*event_header_type
)
1082 return bt_ctf_stream_class_common_set_event_header_field_type(
1083 BT_CTF_TO_COMMON(stream_class
), (void *) event_header_type
);
1086 struct bt_ctf_field_type
*
1087 bt_ctf_stream_class_get_event_context_type(
1088 struct bt_ctf_stream_class
*stream_class
)
1090 return bt_ctf_object_get_ref(
1091 bt_ctf_stream_class_common_borrow_event_context_field_type(
1092 BT_CTF_TO_COMMON(stream_class
)));
1095 int bt_ctf_stream_class_set_event_context_type(
1096 struct bt_ctf_stream_class
*stream_class
,
1097 struct bt_ctf_field_type
*event_context_type
)
1099 return bt_ctf_stream_class_common_set_event_context_field_type(
1100 BT_CTF_TO_COMMON(stream_class
), (void *) event_context_type
);
1103 int64_t bt_ctf_stream_class_get_event_class_count(
1104 struct bt_ctf_stream_class
*stream_class
)
1106 return bt_ctf_stream_class_common_get_event_class_count(
1107 BT_CTF_TO_COMMON(stream_class
));
1110 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_index(
1111 struct bt_ctf_stream_class
*stream_class
, uint64_t index
)
1113 return bt_ctf_object_get_ref(
1114 bt_ctf_stream_class_common_borrow_event_class_by_index(
1115 BT_CTF_TO_COMMON(stream_class
), index
));
1118 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_id(
1119 struct bt_ctf_stream_class
*stream_class
, uint64_t id
)
1121 return bt_ctf_object_get_ref(
1122 bt_ctf_stream_class_common_borrow_event_class_by_id(
1123 BT_CTF_TO_COMMON(stream_class
), id
));
1126 int bt_ctf_stream_class_add_event_class(
1127 struct bt_ctf_stream_class
*stream_class
,
1128 struct bt_ctf_event_class
*event_class
)
1130 return bt_ctf_stream_class_common_add_event_class(
1131 BT_CTF_TO_COMMON(stream_class
), BT_CTF_TO_COMMON(event_class
),
1132 (bt_ctf_validation_flag_copy_field_type_func
) bt_ctf_field_type_copy
);