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"
37 int bt_ctf_stream_class_common_initialize(struct bt_ctf_stream_class_common
*stream_class
,
38 const char *name
, bt_ctf_object_release_func release_func
)
40 BT_LOGD("Initializing common stream class object: name=\"%s\"", name
);
42 bt_ctf_object_init_shared_with_parent(&stream_class
->base
, release_func
);
43 stream_class
->name
= g_string_new(name
);
44 stream_class
->event_classes
= g_ptr_array_new_with_free_func(
45 (GDestroyNotify
) bt_ctf_object_try_spec_release
);
46 if (!stream_class
->event_classes
) {
47 BT_LOGE_STR("Failed to allocate a GPtrArray.");
51 stream_class
->event_classes_ht
= g_hash_table_new_full(g_int64_hash
,
52 g_int64_equal
, g_free
, NULL
);
53 if (!stream_class
->event_classes_ht
) {
54 BT_LOGE_STR("Failed to allocate a GHashTable.");
58 BT_LOGD("Initialized common stream class object: addr=%p, name=\"%s\"",
66 void bt_ctf_stream_class_common_finalize(struct bt_ctf_stream_class_common
*stream_class
)
68 BT_LOGD("Finalizing common stream class: addr=%p, name=\"%s\", id=%" PRId64
,
69 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
70 bt_ctf_stream_class_common_get_id(stream_class
));
71 bt_ctf_object_put_ref(stream_class
->clock_class
);
73 if (stream_class
->event_classes_ht
) {
74 g_hash_table_destroy(stream_class
->event_classes_ht
);
76 if (stream_class
->event_classes
) {
77 BT_LOGD_STR("Destroying event classes.");
78 g_ptr_array_free(stream_class
->event_classes
, TRUE
);
81 if (stream_class
->name
) {
82 g_string_free(stream_class
->name
, TRUE
);
85 BT_LOGD_STR("Putting event header field type.");
86 bt_ctf_object_put_ref(stream_class
->event_header_field_type
);
87 BT_LOGD_STR("Putting packet context field type.");
88 bt_ctf_object_put_ref(stream_class
->packet_context_field_type
);
89 BT_LOGD_STR("Putting event context field type.");
90 bt_ctf_object_put_ref(stream_class
->event_context_field_type
);
94 void event_class_exists(gpointer element
, gpointer query
)
96 struct bt_ctf_event_class_common
*event_class_a
= element
;
97 struct bt_ctf_search_query
*search_query
= query
;
98 struct bt_ctf_event_class_common
*event_class_b
= search_query
->value
;
101 if (search_query
->value
== element
) {
102 search_query
->found
= 1;
107 * Two event classes cannot share the same ID in a given
110 id_a
= bt_ctf_event_class_common_get_id(event_class_a
);
111 id_b
= bt_ctf_event_class_common_get_id(event_class_b
);
113 if (id_a
< 0 || id_b
< 0) {
114 /* at least one ID is not set: will be automatically set later */
119 BT_LOGW("Event class with this ID already exists in the stream class: "
120 "id=%" PRId64
", name=\"%s\"",
121 id_a
, bt_ctf_event_class_common_get_name(event_class_a
));
122 search_query
->found
= 1;
130 int bt_ctf_stream_class_common_add_event_class(
131 struct bt_ctf_stream_class_common
*stream_class
,
132 struct bt_ctf_event_class_common
*event_class
,
133 bt_ctf_validation_flag_copy_field_type_func copy_field_type_func
)
136 int64_t *event_id
= NULL
;
137 struct bt_ctf_trace_common
*trace
= NULL
;
138 struct bt_ctf_stream_class_common
*old_stream_class
= NULL
;
139 struct bt_ctf_validation_output validation_output
= { 0 };
140 struct bt_ctf_field_type_common
*packet_header_type
= NULL
;
141 struct bt_ctf_field_type_common
*packet_context_type
= NULL
;
142 struct bt_ctf_field_type_common
*event_header_type
= NULL
;
143 struct bt_ctf_field_type_common
*stream_event_ctx_type
= NULL
;
144 struct bt_ctf_field_type_common
*event_context_type
= NULL
;
145 struct bt_ctf_field_type_common
*event_payload_type
= NULL
;
146 const enum bt_ctf_validation_flag validation_flags
=
147 BT_CTF_VALIDATION_FLAG_EVENT
;
148 struct bt_ctf_clock_class
*expected_clock_class
= NULL
;
149 struct bt_ctf_search_query query
= { .value
= event_class
, .found
= 0 };
151 BT_ASSERT_DBG(copy_field_type_func
);
153 if (!stream_class
|| !event_class
) {
154 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
155 "stream-class-addr=%p, event-class-addr=%p",
156 stream_class
, event_class
);
161 BT_LOGD("Adding event class to stream class: "
162 "stream-class-addr=%p, stream-class-name=\"%s\", "
163 "stream-class-id=%" PRId64
", event-class-addr=%p, "
164 "event-class-name=\"%s\", event-class-id=%" PRId64
,
165 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
166 bt_ctf_stream_class_common_get_id(stream_class
),
168 bt_ctf_event_class_common_get_name(event_class
),
169 bt_ctf_event_class_common_get_id(event_class
));
170 trace
= bt_ctf_stream_class_common_borrow_trace(stream_class
);
172 if (stream_class
->frozen
) {
174 * We only check that the event class to be added has a
175 * single class which matches the stream class's
176 * expected clock class if the stream class is frozen.
177 * If it's not, then this event class is added "as is"
178 * and the validation will be performed when calling
179 * either bt_ctf_trace_add_stream_class() or
180 * bt_ctf_event_create(). This is because the stream class's
181 * field types (packet context, event header, event
182 * context) could change before the next call to one of
183 * those two functions.
185 expected_clock_class
= bt_ctf_object_get_ref(stream_class
->clock_class
);
188 * At this point, `expected_clock_class` can be NULL,
189 * and bt_ctf_event_class_validate_single_clock_class()
192 ret
= bt_ctf_event_class_common_validate_single_clock_class(
193 event_class
, &expected_clock_class
);
195 BT_LOGW("Event class contains a field type which is not "
196 "recursively mapped to its stream class's "
197 "expected clock class: "
198 "stream-class-addr=%p, "
199 "stream-class-id=%" PRId64
", "
200 "stream-class-name=\"%s\", "
201 "expected-clock-class-addr=%p, "
202 "expected-clock-class-name=\"%s\"",
204 bt_ctf_stream_class_common_get_id(stream_class
),
205 bt_ctf_stream_class_common_get_name(stream_class
),
206 expected_clock_class
,
207 expected_clock_class
?
208 bt_ctf_clock_class_get_name(expected_clock_class
) :
214 event_id
= g_new(int64_t, 1);
216 BT_LOGE_STR("Failed to allocate one int64_t.");
221 /* Check for duplicate event classes */
222 g_ptr_array_foreach(stream_class
->event_classes
, event_class_exists
,
225 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
230 old_stream_class
= bt_ctf_event_class_common_borrow_stream_class(event_class
);
231 if (old_stream_class
) {
232 /* Event class is already associated to a stream class. */
233 BT_LOGW("Event class is already part of another stream class: "
234 "event-class-stream-class-addr=%p, "
235 "event-class-stream-class-name=\"%s\", "
236 "event-class-stream-class-id=%" PRId64
,
238 bt_ctf_stream_class_common_get_name(old_stream_class
),
239 bt_ctf_stream_class_common_get_id(old_stream_class
));
246 * If the stream class is associated with a trace, then
247 * both those objects are frozen. Also, this event class
248 * is about to be frozen.
250 * Therefore the event class must be validated here.
251 * The trace and stream class should be valid at this
254 BT_ASSERT_DBG(trace
->valid
);
255 BT_ASSERT_DBG(stream_class
->valid
);
257 bt_ctf_trace_common_borrow_packet_header_field_type(trace
);
258 packet_context_type
=
259 bt_ctf_stream_class_common_borrow_packet_context_field_type(
262 bt_ctf_stream_class_common_borrow_event_header_field_type(
264 stream_event_ctx_type
=
265 bt_ctf_stream_class_common_borrow_event_context_field_type(
268 bt_ctf_event_class_common_borrow_context_field_type(
271 bt_ctf_event_class_common_borrow_payload_field_type(
273 ret
= bt_ctf_validate_class_types(
274 trace
->environment
, packet_header_type
,
275 packet_context_type
, event_header_type
,
276 stream_event_ctx_type
, event_context_type
,
277 event_payload_type
, trace
->valid
,
278 stream_class
->valid
, event_class
->valid
,
279 &validation_output
, validation_flags
,
280 copy_field_type_func
);
284 * This means something went wrong during the
285 * validation process, not that the objects are
288 BT_LOGE("Failed to validate event class: ret=%d", ret
);
292 if ((validation_output
.valid_flags
& validation_flags
) !=
294 /* Invalid event class */
295 BT_LOGW("Invalid trace, stream class, or event class: "
297 validation_output
.valid_flags
);
303 /* Only set an event ID if none was explicitly set before */
304 *event_id
= bt_ctf_event_class_common_get_id(event_class
);
306 BT_LOGT("Event class has no ID: automatically setting it: "
307 "id=%" PRId64
, stream_class
->next_event_id
);
309 if (bt_ctf_event_class_common_set_id(event_class
,
310 stream_class
->next_event_id
)) {
311 BT_LOGE("Cannot set event class's ID: id=%" PRId64
,
312 stream_class
->next_event_id
);
316 stream_class
->next_event_id
++;
317 *event_id
= stream_class
->next_event_id
;
320 bt_ctf_object_set_parent(&event_class
->base
, &stream_class
->base
);
324 * At this point we know that the function will be
325 * successful. Therefore we can replace the event
326 * class's field types with what's in the validation
327 * output structure and mark this event class as valid.
329 bt_ctf_validation_replace_types(NULL
, NULL
, event_class
,
330 &validation_output
, validation_flags
);
331 event_class
->valid
= 1;
334 * Put what was not moved in
335 * bt_ctf_validation_replace_types().
337 bt_ctf_validation_output_put_types(&validation_output
);
340 /* Add to the event classes of the stream class */
341 g_ptr_array_add(stream_class
->event_classes
, event_class
);
342 g_hash_table_insert(stream_class
->event_classes_ht
, event_id
,
346 /* Freeze the event class */
347 bt_ctf_event_class_common_freeze(event_class
);
350 * It is safe to set the stream class's unique clock class
351 * now if the stream class is frozen.
353 if (stream_class
->frozen
&& expected_clock_class
) {
354 BT_ASSERT_DBG(!stream_class
->clock_class
||
355 stream_class
->clock_class
== expected_clock_class
);
356 BT_CTF_OBJECT_MOVE_REF(stream_class
->clock_class
, expected_clock_class
);
359 BT_LOGD("Added event class to stream class: "
360 "stream-class-addr=%p, stream-class-name=\"%s\", "
361 "stream-class-id=%" PRId64
", event-class-addr=%p, "
362 "event-class-name=\"%s\", event-class-id=%" PRId64
,
363 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
364 bt_ctf_stream_class_common_get_id(stream_class
),
366 bt_ctf_event_class_common_get_name(event_class
),
367 bt_ctf_event_class_common_get_id(event_class
));
370 bt_ctf_validation_output_put_types(&validation_output
);
371 bt_ctf_object_put_ref(expected_clock_class
);
377 int64_t get_event_class_count(void *element
)
379 return bt_ctf_stream_class_get_event_class_count(
380 (struct bt_ctf_stream_class
*) element
);
384 void *get_event_class(void *element
, int i
)
386 return bt_ctf_stream_class_get_event_class_by_index(
387 (struct bt_ctf_stream_class
*) element
, i
);
391 int visit_event_class(void *object
, bt_ctf_visitor visitor
,void *data
)
393 struct bt_ctf_visitor_object obj
= {
395 .type
= BT_CTF_VISITOR_OBJECT_TYPE_EVENT_CLASS
398 return visitor(&obj
, data
);
401 int bt_ctf_stream_class_common_visit(struct bt_ctf_stream_class_common
*stream_class
,
402 bt_ctf_visitor visitor
, void *data
)
405 struct bt_ctf_visitor_object obj
= {
406 .object
= stream_class
,
407 .type
= BT_CTF_VISITOR_OBJECT_TYPE_STREAM_CLASS
410 if (!stream_class
|| !visitor
) {
411 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
412 "stream-class-addr=%p, visitor=%p",
413 stream_class
, visitor
);
418 ret
= bt_ctf_visitor_helper(&obj
, get_event_class_count
,
420 visit_event_class
, visitor
, data
);
421 BT_LOGT("bt_ctf_visitor_helper() returned: ret=%d", ret
);
427 int bt_ctf_stream_class_visit(struct bt_ctf_stream_class
*stream_class
,
428 bt_ctf_visitor visitor
, void *data
)
430 return bt_ctf_stream_class_common_visit(BT_CTF_FROM_COMMON(stream_class
),
434 void bt_ctf_stream_class_common_freeze(struct bt_ctf_stream_class_common
*stream_class
)
436 if (!stream_class
|| stream_class
->frozen
) {
440 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64
,
441 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
442 bt_ctf_stream_class_common_get_id(stream_class
));
443 stream_class
->frozen
= 1;
444 bt_ctf_field_type_common_freeze(stream_class
->event_header_field_type
);
445 bt_ctf_field_type_common_freeze(stream_class
->packet_context_field_type
);
446 bt_ctf_field_type_common_freeze(stream_class
->event_context_field_type
);
447 bt_ctf_clock_class_freeze(stream_class
->clock_class
);
450 int bt_ctf_stream_class_common_validate_single_clock_class(
451 struct bt_ctf_stream_class_common
*stream_class
,
452 struct bt_ctf_clock_class
**expected_clock_class
)
457 BT_ASSERT_DBG(stream_class
);
458 BT_ASSERT_DBG(expected_clock_class
);
459 ret
= bt_ctf_field_type_common_validate_single_clock_class(
460 stream_class
->packet_context_field_type
,
461 expected_clock_class
);
463 BT_LOGW("Stream class's packet context field type "
464 "is not recursively mapped to the "
465 "expected clock class: "
466 "stream-class-addr=%p, "
467 "stream-class-name=\"%s\", "
468 "stream-class-id=%" PRId64
", "
471 bt_ctf_stream_class_common_get_name(stream_class
),
473 stream_class
->packet_context_field_type
);
477 ret
= bt_ctf_field_type_common_validate_single_clock_class(
478 stream_class
->event_header_field_type
,
479 expected_clock_class
);
481 BT_LOGW("Stream class's event header field type "
482 "is not recursively mapped to the "
483 "expected clock class: "
484 "stream-class-addr=%p, "
485 "stream-class-name=\"%s\", "
486 "stream-class-id=%" PRId64
", "
489 bt_ctf_stream_class_common_get_name(stream_class
),
491 stream_class
->event_header_field_type
);
495 ret
= bt_ctf_field_type_common_validate_single_clock_class(
496 stream_class
->event_context_field_type
,
497 expected_clock_class
);
499 BT_LOGW("Stream class's event context field type "
500 "is not recursively mapped to the "
501 "expected clock class: "
502 "stream-class-addr=%p, "
503 "stream-class-name=\"%s\", "
504 "stream-class-id=%" PRId64
", "
507 bt_ctf_stream_class_common_get_name(stream_class
),
509 stream_class
->event_context_field_type
);
513 for (i
= 0; i
< stream_class
->event_classes
->len
; i
++) {
514 struct bt_ctf_event_class_common
*event_class
=
515 g_ptr_array_index(stream_class
->event_classes
, i
);
517 BT_ASSERT_DBG(event_class
);
518 ret
= bt_ctf_event_class_common_validate_single_clock_class(
519 event_class
, expected_clock_class
);
521 BT_LOGW("Stream class's event class contains a "
522 "field type which is not recursively mapped to "
523 "the expected clock class: "
524 "stream-class-addr=%p, "
525 "stream-class-name=\"%s\", "
526 "stream-class-id=%" PRId64
,
528 bt_ctf_stream_class_common_get_name(stream_class
),
539 int init_event_header(struct bt_ctf_stream_class
*stream_class
)
542 struct bt_ctf_field_type
*event_header_type
=
543 bt_ctf_field_type_structure_create();
544 struct bt_ctf_field_type
*_uint32_t
=
545 get_field_type(FIELD_TYPE_ALIAS_UINT32_T
);
546 struct bt_ctf_field_type
*_uint64_t
=
547 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
549 if (!event_header_type
) {
550 BT_LOGE_STR("Cannot create empty structure field type.");
555 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
558 BT_LOGE_STR("Cannot add `id` field to event header field type.");
562 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
563 _uint64_t
, "timestamp");
565 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
569 bt_ctf_object_put_ref(stream_class
->common
.event_header_field_type
);
570 stream_class
->common
.event_header_field_type
=
571 (void *) event_header_type
;
572 event_header_type
= NULL
;
576 bt_ctf_object_put_ref(event_header_type
);
579 bt_ctf_object_put_ref(_uint32_t
);
580 bt_ctf_object_put_ref(_uint64_t
);
585 int init_packet_context(struct bt_ctf_stream_class
*stream_class
)
588 struct bt_ctf_field_type
*packet_context_type
=
589 bt_ctf_field_type_structure_create();
590 struct bt_ctf_field_type
*_uint64_t
=
591 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
592 struct bt_ctf_field_type
*ts_begin_end_uint64_t
= NULL
;
594 if (!packet_context_type
) {
595 BT_LOGE_STR("Cannot create empty structure field type.");
600 ts_begin_end_uint64_t
= bt_ctf_field_type_copy(_uint64_t
);
601 if (!ts_begin_end_uint64_t
) {
602 BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
608 * We create a stream packet context as proposed in the CTF
611 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
612 ts_begin_end_uint64_t
, "timestamp_begin");
614 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
618 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
619 ts_begin_end_uint64_t
, "timestamp_end");
621 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
625 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
626 _uint64_t
, "content_size");
628 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
632 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
633 _uint64_t
, "packet_size");
635 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
639 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
640 _uint64_t
, "events_discarded");
642 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
646 bt_ctf_object_put_ref(stream_class
->common
.packet_context_field_type
);
647 stream_class
->common
.packet_context_field_type
=
648 (void *) packet_context_type
;
649 packet_context_type
= NULL
;
653 bt_ctf_object_put_ref(packet_context_type
);
657 bt_ctf_object_put_ref(_uint64_t
);
658 bt_ctf_object_put_ref(ts_begin_end_uint64_t
);
663 void bt_ctf_stream_class_destroy(struct bt_ctf_object
*obj
)
665 struct bt_ctf_stream_class
*stream_class
;
667 stream_class
= (void *) obj
;
668 BT_LOGD("Destroying CTF writer stream class: addr=%p, name=\"%s\", id=%" PRId64
,
669 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
670 bt_ctf_stream_class_get_id(stream_class
));
671 bt_ctf_stream_class_common_finalize(BT_CTF_TO_COMMON(stream_class
));
672 bt_ctf_object_put_ref(stream_class
->clock
);
673 g_free(stream_class
);
677 struct bt_ctf_stream_class
*bt_ctf_stream_class_create(const char *name
)
679 struct bt_ctf_stream_class
*stream_class
;
682 BT_LOGD("Creating CTF writer stream class object: name=\"%s\"", name
);
683 stream_class
= g_new0(struct bt_ctf_stream_class
, 1);
685 BT_LOGE_STR("Failed to allocate one CTF writer stream class.");
689 ret
= bt_ctf_stream_class_common_initialize(BT_CTF_TO_COMMON(stream_class
),
690 name
, bt_ctf_stream_class_destroy
);
692 /* bt_ctf_stream_class_common_initialize() logs errors */
696 ret
= init_event_header(stream_class
);
698 BT_LOGE_STR("Cannot initialize stream class's event header field type.");
702 ret
= init_packet_context(stream_class
);
704 BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
708 BT_LOGD("Created CTF writer stream class object: addr=%p, name=\"%s\"",
713 BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_class
);
718 int try_map_clock_class(struct bt_ctf_stream_class
*stream_class
,
719 struct bt_ctf_field_type
*parent_ft
, const char *field_name
)
721 struct bt_ctf_clock_class
*mapped_clock_class
= NULL
;
723 struct bt_ctf_field_type
*ft
=
724 bt_ctf_field_type_structure_get_field_type_by_name(parent_ft
,
727 BT_ASSERT_DBG(stream_class
->clock
);
730 /* Field does not exist: not an error */
734 BT_ASSERT_DBG(((struct bt_ctf_field_type_common
*) ft
)->id
==
735 BT_CTF_FIELD_TYPE_ID_INTEGER
);
737 bt_ctf_field_type_integer_get_mapped_clock_class(ft
);
738 if (!mapped_clock_class
) {
739 struct bt_ctf_field_type
*ft_copy
;
741 if (!stream_class
->clock
) {
742 BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
743 "stream-class-addr=%p, stream-class-name=\"%s\", "
744 "stream-class-id=%" PRId64
", ft-addr=%p",
746 bt_ctf_stream_class_get_name(stream_class
),
747 bt_ctf_stream_class_get_id(stream_class
), ft
);
752 ft_copy
= bt_ctf_field_type_copy(ft
);
754 BT_LOGE("Failed to copy integer field type: ft-addr=%p",
760 ret
= bt_ctf_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
761 (void *) ft_copy
, stream_class
->clock
->clock_class
);
762 BT_ASSERT_DBG(ret
== 0);
764 ret
= bt_ctf_field_type_common_structure_replace_field(
765 (void *) parent_ft
, field_name
, (void *) ft_copy
);
766 bt_ctf_object_put_ref(ft_copy
);
767 BT_LOGT("Automatically mapped field type to stream class's clock class: "
768 "stream-class-addr=%p, stream-class-name=\"%s\", "
769 "stream-class-id=%" PRId64
", ft-addr=%p, "
772 bt_ctf_stream_class_get_name(stream_class
),
773 bt_ctf_stream_class_get_id(stream_class
), ft
, ft_copy
);
777 bt_ctf_object_put_ref(ft
);
778 bt_ctf_object_put_ref(mapped_clock_class
);
782 int bt_ctf_stream_class_map_clock_class(
783 struct bt_ctf_stream_class
*stream_class
,
784 struct bt_ctf_field_type
*packet_context_type
,
785 struct bt_ctf_field_type
*event_header_type
)
789 BT_ASSERT_DBG(stream_class
);
791 if (!stream_class
->clock
) {
792 /* No clock class to map to */
796 if (packet_context_type
) {
797 if (try_map_clock_class(stream_class
, packet_context_type
,
798 "timestamp_begin")) {
799 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
804 if (try_map_clock_class(stream_class
, packet_context_type
,
806 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
812 if (event_header_type
) {
813 if (try_map_clock_class(stream_class
, event_header_type
,
815 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
826 struct bt_ctf_clock
*bt_ctf_stream_class_get_clock(
827 struct bt_ctf_stream_class
*stream_class
)
829 struct bt_ctf_clock
*clock
= NULL
;
832 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
836 if (!stream_class
->clock
) {
837 BT_LOGT("Stream class has no clock: "
838 "addr=%p, name=\"%s\", id=%" PRId64
,
840 bt_ctf_stream_class_get_name(stream_class
),
841 bt_ctf_stream_class_get_id(stream_class
));
845 clock
= bt_ctf_object_get_ref(stream_class
->clock
);
852 int bt_ctf_stream_class_set_clock(
853 struct bt_ctf_stream_class
*stream_class
,
854 struct bt_ctf_clock
*clock
)
858 if (!stream_class
|| !clock
) {
859 BT_LOGW("Invalid parameter: stream class or clock is NULL: "
860 "stream-class-addr=%p, clock-addr=%p",
861 stream_class
, clock
);
866 if (stream_class
->common
.frozen
) {
867 BT_LOGW("Invalid parameter: stream class is frozen: "
868 "addr=%p, name=\"%s\", id=%" PRId64
,
870 bt_ctf_stream_class_get_name(stream_class
),
871 bt_ctf_stream_class_get_id(stream_class
));
876 /* Replace the current clock of this stream class. */
877 bt_ctf_object_put_ref(stream_class
->clock
);
878 stream_class
->clock
= bt_ctf_object_get_ref(clock
);
879 BT_LOGT("Set stream class's clock: "
880 "addr=%p, name=\"%s\", id=%" PRId64
", "
881 "clock-addr=%p, clock-name=\"%s\"",
883 bt_ctf_stream_class_get_name(stream_class
),
884 bt_ctf_stream_class_get_id(stream_class
),
886 bt_ctf_clock_get_name(stream_class
->clock
));
892 int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class
*stream_class
,
893 struct metadata_context
*context
)
897 struct bt_ctf_trace
*trace
;
898 struct bt_ctf_field_type
*packet_header_type
= NULL
;
900 BT_LOGD("Serializing stream class's metadata: "
901 "stream-class-addr=%p, stream-class-name=\"%s\", "
902 "stream-class-id=%" PRId64
", metadata-context-addr=%p",
904 bt_ctf_stream_class_get_name(stream_class
),
905 bt_ctf_stream_class_get_id(stream_class
), context
);
906 g_string_assign(context
->field_name
, "");
907 context
->current_indentation_level
= 1;
908 if (!stream_class
->common
.id_set
) {
909 BT_LOGW_STR("Stream class's ID is not set.");
914 g_string_append(context
->string
, "stream {\n");
917 * The reference to the trace is only borrowed since the
918 * serialization of the stream class might have been triggered
919 * by the trace's destruction. In such a case, the trace's
920 * reference count would, unexpectedly, go through the sequence
921 * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
924 trace
= BT_CTF_FROM_COMMON(bt_ctf_stream_class_common_borrow_trace(
925 BT_CTF_TO_COMMON(stream_class
)));
926 BT_ASSERT_DBG(trace
);
927 packet_header_type
= bt_ctf_trace_get_packet_header_field_type(trace
);
929 if (packet_header_type
) {
930 struct bt_ctf_field_type
*stream_id_type
;
933 bt_ctf_field_type_structure_get_field_type_by_name(
934 packet_header_type
, "stream_id");
935 if (stream_id_type
) {
937 * Only set the stream's id if the trace's packet header
938 * contains a stream_id field. This field is only
939 * needed if the trace contains only one stream
942 g_string_append_printf(context
->string
,
943 "\tid = %" PRId64
";\n",
944 stream_class
->common
.id
);
946 bt_ctf_object_put_ref(stream_id_type
);
948 if (stream_class
->common
.event_header_field_type
) {
949 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
950 g_string_append(context
->string
, "\tevent.header := ");
951 ret
= bt_ctf_field_type_serialize_recursive(
952 (void *) stream_class
->common
.event_header_field_type
,
955 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
959 g_string_append(context
->string
, ";");
963 if (stream_class
->common
.packet_context_field_type
) {
964 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
965 g_string_append(context
->string
, "\n\n\tpacket.context := ");
966 ret
= bt_ctf_field_type_serialize_recursive(
967 (void *) stream_class
->common
.packet_context_field_type
,
970 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
974 g_string_append(context
->string
, ";");
977 if (stream_class
->common
.event_context_field_type
) {
978 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
979 g_string_append(context
->string
, "\n\n\tevent.context := ");
980 ret
= bt_ctf_field_type_serialize_recursive(
981 (void *) stream_class
->common
.event_context_field_type
,
984 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
988 g_string_append(context
->string
, ";");
991 g_string_append(context
->string
, "\n};\n\n");
993 for (i
= 0; i
< stream_class
->common
.event_classes
->len
; i
++) {
994 struct bt_ctf_event_class
*event_class
=
995 stream_class
->common
.event_classes
->pdata
[i
];
997 ret
= bt_ctf_event_class_serialize(event_class
, context
);
999 BT_LOGW("Cannot serialize event class's metadata: "
1000 "event-class-addr=%p, event-class-name=\"%s\", "
1001 "event-class-id=%" PRId64
,
1003 bt_ctf_event_class_get_name(event_class
),
1004 bt_ctf_event_class_get_id(event_class
));
1010 bt_ctf_object_put_ref(packet_header_type
);
1011 context
->current_indentation_level
= 0;
1016 struct bt_ctf_trace
*bt_ctf_stream_class_get_trace(
1017 struct bt_ctf_stream_class
*stream_class
)
1019 return bt_ctf_object_get_ref(bt_ctf_stream_class_common_borrow_trace(
1020 BT_CTF_TO_COMMON(stream_class
)));
1024 const char *bt_ctf_stream_class_get_name(
1025 struct bt_ctf_stream_class
*stream_class
)
1027 return bt_ctf_stream_class_common_get_name(BT_CTF_TO_COMMON(stream_class
));
1031 int bt_ctf_stream_class_set_name(
1032 struct bt_ctf_stream_class
*stream_class
, const char *name
)
1034 return bt_ctf_stream_class_common_set_name(BT_CTF_TO_COMMON(stream_class
),
1039 int64_t bt_ctf_stream_class_get_id(
1040 struct bt_ctf_stream_class
*stream_class
)
1042 return bt_ctf_stream_class_common_get_id(BT_CTF_TO_COMMON(stream_class
));
1046 int bt_ctf_stream_class_set_id(
1047 struct bt_ctf_stream_class
*stream_class
, uint64_t id
)
1049 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
)));
1062 int bt_ctf_stream_class_set_packet_context_type(
1063 struct bt_ctf_stream_class
*stream_class
,
1064 struct bt_ctf_field_type
*packet_context_type
)
1066 return bt_ctf_stream_class_common_set_packet_context_field_type(
1067 BT_CTF_TO_COMMON(stream_class
), (void *) packet_context_type
);
1071 struct bt_ctf_field_type
*
1072 bt_ctf_stream_class_get_event_header_type(
1073 struct bt_ctf_stream_class
*stream_class
)
1075 return bt_ctf_object_get_ref(
1076 bt_ctf_stream_class_common_borrow_event_header_field_type(
1077 BT_CTF_TO_COMMON(stream_class
)));
1081 int bt_ctf_stream_class_set_event_header_type(
1082 struct bt_ctf_stream_class
*stream_class
,
1083 struct bt_ctf_field_type
*event_header_type
)
1085 return bt_ctf_stream_class_common_set_event_header_field_type(
1086 BT_CTF_TO_COMMON(stream_class
), (void *) event_header_type
);
1090 struct bt_ctf_field_type
*
1091 bt_ctf_stream_class_get_event_context_type(
1092 struct bt_ctf_stream_class
*stream_class
)
1094 return bt_ctf_object_get_ref(
1095 bt_ctf_stream_class_common_borrow_event_context_field_type(
1096 BT_CTF_TO_COMMON(stream_class
)));
1100 int bt_ctf_stream_class_set_event_context_type(
1101 struct bt_ctf_stream_class
*stream_class
,
1102 struct bt_ctf_field_type
*event_context_type
)
1104 return bt_ctf_stream_class_common_set_event_context_field_type(
1105 BT_CTF_TO_COMMON(stream_class
), (void *) event_context_type
);
1109 int64_t bt_ctf_stream_class_get_event_class_count(
1110 struct bt_ctf_stream_class
*stream_class
)
1112 return bt_ctf_stream_class_common_get_event_class_count(
1113 BT_CTF_TO_COMMON(stream_class
));
1117 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_index(
1118 struct bt_ctf_stream_class
*stream_class
, uint64_t index
)
1120 return bt_ctf_object_get_ref(
1121 bt_ctf_stream_class_common_borrow_event_class_by_index(
1122 BT_CTF_TO_COMMON(stream_class
), index
));
1126 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_id(
1127 struct bt_ctf_stream_class
*stream_class
, uint64_t id
)
1129 return bt_ctf_object_get_ref(
1130 bt_ctf_stream_class_common_borrow_event_class_by_id(
1131 BT_CTF_TO_COMMON(stream_class
), id
));
1135 int bt_ctf_stream_class_add_event_class(
1136 struct bt_ctf_stream_class
*stream_class
,
1137 struct bt_ctf_event_class
*event_class
)
1139 return bt_ctf_stream_class_common_add_event_class(
1140 BT_CTF_TO_COMMON(stream_class
), BT_CTF_TO_COMMON(event_class
),
1141 (bt_ctf_validation_flag_copy_field_type_func
) bt_ctf_field_type_copy
);