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-CLASS"
31 #include <babeltrace2-ctf-writer/event.h>
32 #include <babeltrace2-ctf-writer/object.h>
33 #include <babeltrace2-ctf-writer/trace.h>
34 #include <babeltrace2-ctf-writer/utils.h>
36 #include "common/align.h"
37 #include "common/assert.h"
38 #include "compat/compiler.h"
39 #include "compat/endian.h"
41 #include "assert-pre.h"
42 #include "clock-class.h"
43 #include "event-class.h"
46 #include "field-types.h"
47 #include "field-wrapper.h"
48 #include "stream-class.h"
50 #include "validation.h"
55 int bt_ctf_stream_class_common_initialize(struct bt_ctf_stream_class_common
*stream_class
,
56 const char *name
, bt_ctf_object_release_func release_func
)
58 BT_LOGD("Initializing common stream class object: name=\"%s\"", name
);
60 bt_ctf_object_init_shared_with_parent(&stream_class
->base
, release_func
);
61 stream_class
->name
= g_string_new(name
);
62 stream_class
->event_classes
= g_ptr_array_new_with_free_func(
63 (GDestroyNotify
) bt_ctf_object_try_spec_release
);
64 if (!stream_class
->event_classes
) {
65 BT_LOGE_STR("Failed to allocate a GPtrArray.");
69 stream_class
->event_classes_ht
= g_hash_table_new_full(g_int64_hash
,
70 g_int64_equal
, g_free
, NULL
);
71 if (!stream_class
->event_classes_ht
) {
72 BT_LOGE_STR("Failed to allocate a GHashTable.");
76 BT_LOGD("Initialized common stream class object: addr=%p, name=\"%s\"",
85 void bt_ctf_stream_class_common_finalize(struct bt_ctf_stream_class_common
*stream_class
)
87 BT_LOGD("Finalizing common stream class: addr=%p, name=\"%s\", id=%" PRId64
,
88 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
89 bt_ctf_stream_class_common_get_id(stream_class
));
90 bt_ctf_object_put_ref(stream_class
->clock_class
);
92 if (stream_class
->event_classes_ht
) {
93 g_hash_table_destroy(stream_class
->event_classes_ht
);
95 if (stream_class
->event_classes
) {
96 BT_LOGD_STR("Destroying event classes.");
97 g_ptr_array_free(stream_class
->event_classes
, TRUE
);
100 if (stream_class
->name
) {
101 g_string_free(stream_class
->name
, TRUE
);
104 BT_LOGD_STR("Putting event header field type.");
105 bt_ctf_object_put_ref(stream_class
->event_header_field_type
);
106 BT_LOGD_STR("Putting packet context field type.");
107 bt_ctf_object_put_ref(stream_class
->packet_context_field_type
);
108 BT_LOGD_STR("Putting event context field type.");
109 bt_ctf_object_put_ref(stream_class
->event_context_field_type
);
113 void event_class_exists(gpointer element
, gpointer query
)
115 struct bt_ctf_event_class_common
*event_class_a
= element
;
116 struct bt_ctf_search_query
*search_query
= query
;
117 struct bt_ctf_event_class_common
*event_class_b
= search_query
->value
;
120 if (search_query
->value
== element
) {
121 search_query
->found
= 1;
126 * Two event classes cannot share the same ID in a given
129 id_a
= bt_ctf_event_class_common_get_id(event_class_a
);
130 id_b
= bt_ctf_event_class_common_get_id(event_class_b
);
132 if (id_a
< 0 || id_b
< 0) {
133 /* at least one ID is not set: will be automatically set later */
138 BT_LOGW("Event class with this ID already exists in the stream class: "
139 "id=%" PRId64
", name=\"%s\"",
140 id_a
, bt_ctf_event_class_common_get_name(event_class_a
));
141 search_query
->found
= 1;
150 int bt_ctf_stream_class_common_add_event_class(
151 struct bt_ctf_stream_class_common
*stream_class
,
152 struct bt_ctf_event_class_common
*event_class
,
153 bt_ctf_validation_flag_copy_field_type_func copy_field_type_func
)
156 int64_t *event_id
= NULL
;
157 struct bt_ctf_trace_common
*trace
= NULL
;
158 struct bt_ctf_stream_class_common
*old_stream_class
= NULL
;
159 struct bt_ctf_validation_output validation_output
= { 0 };
160 struct bt_ctf_field_type_common
*packet_header_type
= NULL
;
161 struct bt_ctf_field_type_common
*packet_context_type
= NULL
;
162 struct bt_ctf_field_type_common
*event_header_type
= NULL
;
163 struct bt_ctf_field_type_common
*stream_event_ctx_type
= NULL
;
164 struct bt_ctf_field_type_common
*event_context_type
= NULL
;
165 struct bt_ctf_field_type_common
*event_payload_type
= NULL
;
166 const enum bt_ctf_validation_flag validation_flags
=
167 BT_CTF_VALIDATION_FLAG_EVENT
;
168 struct bt_ctf_clock_class
*expected_clock_class
= NULL
;
170 BT_ASSERT(copy_field_type_func
);
172 if (!stream_class
|| !event_class
) {
173 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
174 "stream-class-addr=%p, event-class-addr=%p",
175 stream_class
, event_class
);
180 BT_LOGD("Adding event class to stream class: "
181 "stream-class-addr=%p, stream-class-name=\"%s\", "
182 "stream-class-id=%" PRId64
", event-class-addr=%p, "
183 "event-class-name=\"%s\", event-class-id=%" PRId64
,
184 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
185 bt_ctf_stream_class_common_get_id(stream_class
),
187 bt_ctf_event_class_common_get_name(event_class
),
188 bt_ctf_event_class_common_get_id(event_class
));
189 trace
= bt_ctf_stream_class_common_borrow_trace(stream_class
);
191 if (stream_class
->frozen
) {
193 * We only check that the event class to be added has a
194 * single class which matches the stream class's
195 * expected clock class if the stream class is frozen.
196 * If it's not, then this event class is added "as is"
197 * and the validation will be performed when calling
198 * either bt_ctf_trace_add_stream_class() or
199 * bt_ctf_event_create(). This is because the stream class's
200 * field types (packet context, event header, event
201 * context) could change before the next call to one of
202 * those two functions.
204 expected_clock_class
= bt_ctf_object_get_ref(stream_class
->clock_class
);
207 * At this point, `expected_clock_class` can be NULL,
208 * and bt_ctf_event_class_validate_single_clock_class()
211 ret
= bt_ctf_event_class_common_validate_single_clock_class(
212 event_class
, &expected_clock_class
);
214 BT_LOGW("Event class contains a field type which is not "
215 "recursively mapped to its stream class's "
216 "expected clock class: "
217 "stream-class-addr=%p, "
218 "stream-class-id=%" PRId64
", "
219 "stream-class-name=\"%s\", "
220 "expected-clock-class-addr=%p, "
221 "expected-clock-class-name=\"%s\"",
223 bt_ctf_stream_class_common_get_id(stream_class
),
224 bt_ctf_stream_class_common_get_name(stream_class
),
225 expected_clock_class
,
226 expected_clock_class
?
227 bt_ctf_clock_class_get_name(expected_clock_class
) :
233 event_id
= g_new(int64_t, 1);
235 BT_LOGE_STR("Failed to allocate one int64_t.");
240 /* Check for duplicate event classes */
241 struct bt_ctf_search_query query
= { .value
= event_class
, .found
= 0 };
242 g_ptr_array_foreach(stream_class
->event_classes
, event_class_exists
,
245 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
250 old_stream_class
= bt_ctf_event_class_common_borrow_stream_class(event_class
);
251 if (old_stream_class
) {
252 /* Event class is already associated to a stream class. */
253 BT_LOGW("Event class is already part of another stream class: "
254 "event-class-stream-class-addr=%p, "
255 "event-class-stream-class-name=\"%s\", "
256 "event-class-stream-class-id=%" PRId64
,
258 bt_ctf_stream_class_common_get_name(old_stream_class
),
259 bt_ctf_stream_class_common_get_id(old_stream_class
));
266 * If the stream class is associated with a trace, then
267 * both those objects are frozen. Also, this event class
268 * is about to be frozen.
270 * Therefore the event class must be validated here.
271 * The trace and stream class should be valid at this
274 BT_ASSERT(trace
->valid
);
275 BT_ASSERT(stream_class
->valid
);
277 bt_ctf_trace_common_borrow_packet_header_field_type(trace
);
278 packet_context_type
=
279 bt_ctf_stream_class_common_borrow_packet_context_field_type(
282 bt_ctf_stream_class_common_borrow_event_header_field_type(
284 stream_event_ctx_type
=
285 bt_ctf_stream_class_common_borrow_event_context_field_type(
288 bt_ctf_event_class_common_borrow_context_field_type(
291 bt_ctf_event_class_common_borrow_payload_field_type(
293 ret
= bt_ctf_validate_class_types(
294 trace
->environment
, packet_header_type
,
295 packet_context_type
, event_header_type
,
296 stream_event_ctx_type
, event_context_type
,
297 event_payload_type
, trace
->valid
,
298 stream_class
->valid
, event_class
->valid
,
299 &validation_output
, validation_flags
,
300 copy_field_type_func
);
304 * This means something went wrong during the
305 * validation process, not that the objects are
308 BT_LOGE("Failed to validate event class: ret=%d", ret
);
312 if ((validation_output
.valid_flags
& validation_flags
) !=
314 /* Invalid event class */
315 BT_LOGW("Invalid trace, stream class, or event class: "
317 validation_output
.valid_flags
);
323 /* Only set an event ID if none was explicitly set before */
324 *event_id
= bt_ctf_event_class_common_get_id(event_class
);
326 BT_LOGT("Event class has no ID: automatically setting it: "
327 "id=%" PRId64
, stream_class
->next_event_id
);
329 if (bt_ctf_event_class_common_set_id(event_class
,
330 stream_class
->next_event_id
)) {
331 BT_LOGE("Cannot set event class's ID: id=%" PRId64
,
332 stream_class
->next_event_id
);
336 stream_class
->next_event_id
++;
337 *event_id
= stream_class
->next_event_id
;
340 bt_ctf_object_set_parent(&event_class
->base
, &stream_class
->base
);
344 * At this point we know that the function will be
345 * successful. Therefore we can replace the event
346 * class's field types with what's in the validation
347 * output structure and mark this event class as valid.
349 bt_ctf_validation_replace_types(NULL
, NULL
, event_class
,
350 &validation_output
, validation_flags
);
351 event_class
->valid
= 1;
354 * Put what was not moved in
355 * bt_ctf_validation_replace_types().
357 bt_ctf_validation_output_put_types(&validation_output
);
360 /* Add to the event classes of the stream class */
361 g_ptr_array_add(stream_class
->event_classes
, event_class
);
362 g_hash_table_insert(stream_class
->event_classes_ht
, event_id
,
366 /* Freeze the event class */
367 bt_ctf_event_class_common_freeze(event_class
);
370 * It is safe to set the stream class's unique clock class
371 * now if the stream class is frozen.
373 if (stream_class
->frozen
&& expected_clock_class
) {
374 BT_ASSERT(!stream_class
->clock_class
||
375 stream_class
->clock_class
== expected_clock_class
);
376 BT_CTF_OBJECT_MOVE_REF(stream_class
->clock_class
, expected_clock_class
);
379 BT_LOGD("Added event class to stream class: "
380 "stream-class-addr=%p, stream-class-name=\"%s\", "
381 "stream-class-id=%" PRId64
", event-class-addr=%p, "
382 "event-class-name=\"%s\", event-class-id=%" PRId64
,
383 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
384 bt_ctf_stream_class_common_get_id(stream_class
),
386 bt_ctf_event_class_common_get_name(event_class
),
387 bt_ctf_event_class_common_get_id(event_class
));
390 bt_ctf_validation_output_put_types(&validation_output
);
391 bt_ctf_object_put_ref(expected_clock_class
);
397 int64_t get_event_class_count(void *element
)
399 return bt_ctf_stream_class_get_event_class_count(
400 (struct bt_ctf_stream_class
*) element
);
404 void *get_event_class(void *element
, int i
)
406 return bt_ctf_stream_class_get_event_class_by_index(
407 (struct bt_ctf_stream_class
*) element
, i
);
411 int visit_event_class(void *object
, bt_ctf_visitor visitor
,void *data
)
413 struct bt_ctf_visitor_object obj
= {
415 .type
= BT_CTF_VISITOR_OBJECT_TYPE_EVENT_CLASS
418 return visitor(&obj
, data
);
422 int bt_ctf_stream_class_common_visit(struct bt_ctf_stream_class_common
*stream_class
,
423 bt_ctf_visitor visitor
, void *data
)
426 struct bt_ctf_visitor_object obj
= {
427 .object
= stream_class
,
428 .type
= BT_CTF_VISITOR_OBJECT_TYPE_STREAM_CLASS
431 if (!stream_class
|| !visitor
) {
432 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
433 "stream-class-addr=%p, visitor=%p",
434 stream_class
, visitor
);
439 ret
= bt_ctf_visitor_helper(&obj
, get_event_class_count
,
441 visit_event_class
, visitor
, data
);
442 BT_LOGT("bt_ctf_visitor_helper() returned: ret=%d", ret
);
449 int bt_ctf_stream_class_visit(struct bt_ctf_stream_class
*stream_class
,
450 bt_ctf_visitor visitor
, void *data
)
452 return bt_ctf_stream_class_common_visit(BT_CTF_FROM_COMMON(stream_class
),
457 void bt_ctf_stream_class_common_freeze(struct bt_ctf_stream_class_common
*stream_class
)
459 if (!stream_class
|| stream_class
->frozen
) {
463 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64
,
464 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
465 bt_ctf_stream_class_common_get_id(stream_class
));
466 stream_class
->frozen
= 1;
467 bt_ctf_field_type_common_freeze(stream_class
->event_header_field_type
);
468 bt_ctf_field_type_common_freeze(stream_class
->packet_context_field_type
);
469 bt_ctf_field_type_common_freeze(stream_class
->event_context_field_type
);
470 bt_ctf_clock_class_freeze(stream_class
->clock_class
);
474 int bt_ctf_stream_class_common_validate_single_clock_class(
475 struct bt_ctf_stream_class_common
*stream_class
,
476 struct bt_ctf_clock_class
**expected_clock_class
)
481 BT_ASSERT(stream_class
);
482 BT_ASSERT(expected_clock_class
);
483 ret
= bt_ctf_field_type_common_validate_single_clock_class(
484 stream_class
->packet_context_field_type
,
485 expected_clock_class
);
487 BT_LOGW("Stream class's packet context field type "
488 "is not recursively mapped to the "
489 "expected clock class: "
490 "stream-class-addr=%p, "
491 "stream-class-name=\"%s\", "
492 "stream-class-id=%" PRId64
", "
495 bt_ctf_stream_class_common_get_name(stream_class
),
497 stream_class
->packet_context_field_type
);
501 ret
= bt_ctf_field_type_common_validate_single_clock_class(
502 stream_class
->event_header_field_type
,
503 expected_clock_class
);
505 BT_LOGW("Stream class's event header field type "
506 "is not recursively mapped to the "
507 "expected clock class: "
508 "stream-class-addr=%p, "
509 "stream-class-name=\"%s\", "
510 "stream-class-id=%" PRId64
", "
513 bt_ctf_stream_class_common_get_name(stream_class
),
515 stream_class
->event_header_field_type
);
519 ret
= bt_ctf_field_type_common_validate_single_clock_class(
520 stream_class
->event_context_field_type
,
521 expected_clock_class
);
523 BT_LOGW("Stream class's event context field type "
524 "is not recursively mapped to the "
525 "expected clock class: "
526 "stream-class-addr=%p, "
527 "stream-class-name=\"%s\", "
528 "stream-class-id=%" PRId64
", "
531 bt_ctf_stream_class_common_get_name(stream_class
),
533 stream_class
->event_context_field_type
);
537 for (i
= 0; i
< stream_class
->event_classes
->len
; i
++) {
538 struct bt_ctf_event_class_common
*event_class
=
539 g_ptr_array_index(stream_class
->event_classes
, i
);
541 BT_ASSERT(event_class
);
542 ret
= bt_ctf_event_class_common_validate_single_clock_class(
543 event_class
, expected_clock_class
);
545 BT_LOGW("Stream class's event class contains a "
546 "field type which is not recursively mapped to "
547 "the expected clock class: "
548 "stream-class-addr=%p, "
549 "stream-class-name=\"%s\", "
550 "stream-class-id=%" PRId64
,
552 bt_ctf_stream_class_common_get_name(stream_class
),
563 int init_event_header(struct bt_ctf_stream_class
*stream_class
)
566 struct bt_ctf_field_type
*event_header_type
=
567 bt_ctf_field_type_structure_create();
568 struct bt_ctf_field_type
*_uint32_t
=
569 get_field_type(FIELD_TYPE_ALIAS_UINT32_T
);
570 struct bt_ctf_field_type
*_uint64_t
=
571 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
573 if (!event_header_type
) {
574 BT_LOGE_STR("Cannot create empty structure field type.");
579 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
582 BT_LOGE_STR("Cannot add `id` field to event header field type.");
586 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
587 _uint64_t
, "timestamp");
589 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
593 bt_ctf_object_put_ref(stream_class
->common
.event_header_field_type
);
594 stream_class
->common
.event_header_field_type
=
595 (void *) event_header_type
;
596 event_header_type
= NULL
;
600 bt_ctf_object_put_ref(event_header_type
);
603 bt_ctf_object_put_ref(_uint32_t
);
604 bt_ctf_object_put_ref(_uint64_t
);
609 int init_packet_context(struct bt_ctf_stream_class
*stream_class
)
612 struct bt_ctf_field_type
*packet_context_type
=
613 bt_ctf_field_type_structure_create();
614 struct bt_ctf_field_type
*_uint64_t
=
615 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
616 struct bt_ctf_field_type
*ts_begin_end_uint64_t
= NULL
;
618 if (!packet_context_type
) {
619 BT_LOGE_STR("Cannot create empty structure field type.");
624 ts_begin_end_uint64_t
= bt_ctf_field_type_copy(_uint64_t
);
625 if (!ts_begin_end_uint64_t
) {
626 BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
632 * We create a stream packet context as proposed in the CTF
635 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
636 ts_begin_end_uint64_t
, "timestamp_begin");
638 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
642 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
643 ts_begin_end_uint64_t
, "timestamp_end");
645 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
649 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
650 _uint64_t
, "content_size");
652 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
656 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
657 _uint64_t
, "packet_size");
659 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
663 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
664 _uint64_t
, "events_discarded");
666 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
670 bt_ctf_object_put_ref(stream_class
->common
.packet_context_field_type
);
671 stream_class
->common
.packet_context_field_type
=
672 (void *) packet_context_type
;
673 packet_context_type
= NULL
;
677 bt_ctf_object_put_ref(packet_context_type
);
681 bt_ctf_object_put_ref(_uint64_t
);
682 bt_ctf_object_put_ref(ts_begin_end_uint64_t
);
687 void bt_ctf_stream_class_destroy(struct bt_ctf_object
*obj
)
689 struct bt_ctf_stream_class
*stream_class
;
691 stream_class
= (void *) obj
;
692 BT_LOGD("Destroying CTF writer stream class: addr=%p, name=\"%s\", id=%" PRId64
,
693 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
694 bt_ctf_stream_class_get_id(stream_class
));
695 bt_ctf_stream_class_common_finalize(BT_CTF_TO_COMMON(stream_class
));
696 bt_ctf_object_put_ref(stream_class
->clock
);
697 g_free(stream_class
);
700 struct bt_ctf_stream_class
*bt_ctf_stream_class_create(const char *name
)
702 struct bt_ctf_stream_class
*stream_class
;
705 BT_LOGD("Creating CTF writer stream class object: name=\"%s\"", name
);
706 stream_class
= g_new0(struct bt_ctf_stream_class
, 1);
708 BT_LOGE_STR("Failed to allocate one CTF writer stream class.");
712 ret
= bt_ctf_stream_class_common_initialize(BT_CTF_TO_COMMON(stream_class
),
713 name
, bt_ctf_stream_class_destroy
);
715 /* bt_ctf_stream_class_common_initialize() logs errors */
719 ret
= init_event_header(stream_class
);
721 BT_LOGE_STR("Cannot initialize stream class's event header field type.");
725 ret
= init_packet_context(stream_class
);
727 BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
731 BT_LOGD("Created CTF writer stream class object: addr=%p, name=\"%s\"",
736 BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_class
);
741 int try_map_clock_class(struct bt_ctf_stream_class
*stream_class
,
742 struct bt_ctf_field_type
*parent_ft
, const char *field_name
)
744 struct bt_ctf_clock_class
*mapped_clock_class
= NULL
;
746 struct bt_ctf_field_type
*ft
=
747 bt_ctf_field_type_structure_get_field_type_by_name(parent_ft
,
750 BT_ASSERT(stream_class
->clock
);
753 /* Field does not exist: not an error */
757 BT_ASSERT(((struct bt_ctf_field_type_common
*) ft
)->id
==
758 BT_CTF_FIELD_TYPE_ID_INTEGER
);
760 bt_ctf_field_type_integer_get_mapped_clock_class(ft
);
761 if (!mapped_clock_class
) {
762 struct bt_ctf_field_type
*ft_copy
;
764 if (!stream_class
->clock
) {
765 BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
766 "stream-class-addr=%p, stream-class-name=\"%s\", "
767 "stream-class-id=%" PRId64
", ft-addr=%p",
769 bt_ctf_stream_class_get_name(stream_class
),
770 bt_ctf_stream_class_get_id(stream_class
), ft
);
775 ft_copy
= bt_ctf_field_type_copy(ft
);
777 BT_LOGE("Failed to copy integer field type: ft-addr=%p",
781 ret
= bt_ctf_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
782 (void *) ft_copy
, stream_class
->clock
->clock_class
);
785 ret
= bt_ctf_field_type_common_structure_replace_field(
786 (void *) parent_ft
, field_name
, (void *) ft_copy
);
787 bt_ctf_object_put_ref(ft_copy
);
788 BT_LOGT("Automatically mapped field type to stream class's clock class: "
789 "stream-class-addr=%p, stream-class-name=\"%s\", "
790 "stream-class-id=%" PRId64
", ft-addr=%p, "
793 bt_ctf_stream_class_get_name(stream_class
),
794 bt_ctf_stream_class_get_id(stream_class
), ft
, ft_copy
);
798 bt_ctf_object_put_ref(ft
);
799 bt_ctf_object_put_ref(mapped_clock_class
);
804 int bt_ctf_stream_class_map_clock_class(
805 struct bt_ctf_stream_class
*stream_class
,
806 struct bt_ctf_field_type
*packet_context_type
,
807 struct bt_ctf_field_type
*event_header_type
)
811 BT_ASSERT(stream_class
);
813 if (!stream_class
->clock
) {
814 /* No clock class to map to */
818 if (packet_context_type
) {
819 if (try_map_clock_class(stream_class
, packet_context_type
,
820 "timestamp_begin")) {
821 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
826 if (try_map_clock_class(stream_class
, packet_context_type
,
828 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
834 if (event_header_type
) {
835 if (try_map_clock_class(stream_class
, event_header_type
,
837 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
847 struct bt_ctf_clock
*bt_ctf_stream_class_get_clock(
848 struct bt_ctf_stream_class
*stream_class
)
850 struct bt_ctf_clock
*clock
= NULL
;
853 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
857 if (!stream_class
->clock
) {
858 BT_LOGT("Stream class has no clock: "
859 "addr=%p, name=\"%s\", id=%" PRId64
,
861 bt_ctf_stream_class_get_name(stream_class
),
862 bt_ctf_stream_class_get_id(stream_class
));
866 clock
= bt_ctf_object_get_ref(stream_class
->clock
);
872 int bt_ctf_stream_class_set_clock(
873 struct bt_ctf_stream_class
*stream_class
,
874 struct bt_ctf_clock
*clock
)
878 if (!stream_class
|| !clock
) {
879 BT_LOGW("Invalid parameter: stream class or clock is NULL: "
880 "stream-class-addr=%p, clock-addr=%p",
881 stream_class
, clock
);
886 if (stream_class
->common
.frozen
) {
887 BT_LOGW("Invalid parameter: stream class is frozen: "
888 "addr=%p, name=\"%s\", id=%" PRId64
,
890 bt_ctf_stream_class_get_name(stream_class
),
891 bt_ctf_stream_class_get_id(stream_class
));
896 /* Replace the current clock of this stream class. */
897 bt_ctf_object_put_ref(stream_class
->clock
);
898 stream_class
->clock
= bt_ctf_object_get_ref(clock
);
899 BT_LOGT("Set stream class's clock: "
900 "addr=%p, name=\"%s\", id=%" PRId64
", "
901 "clock-addr=%p, clock-name=\"%s\"",
903 bt_ctf_stream_class_get_name(stream_class
),
904 bt_ctf_stream_class_get_id(stream_class
),
906 bt_ctf_clock_get_name(stream_class
->clock
));
913 int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class
*stream_class
,
914 struct metadata_context
*context
)
918 struct bt_ctf_trace
*trace
;
919 struct bt_ctf_field_type
*packet_header_type
= NULL
;
921 BT_LOGD("Serializing stream class's metadata: "
922 "stream-class-addr=%p, stream-class-name=\"%s\", "
923 "stream-class-id=%" PRId64
", metadata-context-addr=%p",
925 bt_ctf_stream_class_get_name(stream_class
),
926 bt_ctf_stream_class_get_id(stream_class
), context
);
927 g_string_assign(context
->field_name
, "");
928 context
->current_indentation_level
= 1;
929 if (!stream_class
->common
.id_set
) {
930 BT_LOGW_STR("Stream class's ID is not set.");
935 g_string_append(context
->string
, "stream {\n");
938 * The reference to the trace is only borrowed since the
939 * serialization of the stream class might have been triggered
940 * by the trace's destruction. In such a case, the trace's
941 * reference count would, unexepectedly, go through the sequence
942 * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
945 trace
= BT_CTF_FROM_COMMON(bt_ctf_stream_class_common_borrow_trace(
946 BT_CTF_TO_COMMON(stream_class
)));
948 packet_header_type
= bt_ctf_trace_get_packet_header_field_type(trace
);
950 if (packet_header_type
) {
951 struct bt_ctf_field_type
*stream_id_type
;
954 bt_ctf_field_type_structure_get_field_type_by_name(
955 packet_header_type
, "stream_id");
956 if (stream_id_type
) {
958 * Only set the stream's id if the trace's packet header
959 * contains a stream_id field. This field is only
960 * needed if the trace contains only one stream
963 g_string_append_printf(context
->string
,
964 "\tid = %" PRId64
";\n",
965 stream_class
->common
.id
);
967 bt_ctf_object_put_ref(stream_id_type
);
969 if (stream_class
->common
.event_header_field_type
) {
970 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
971 g_string_append(context
->string
, "\tevent.header := ");
972 ret
= bt_ctf_field_type_serialize_recursive(
973 (void *) stream_class
->common
.event_header_field_type
,
976 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
980 g_string_append(context
->string
, ";");
984 if (stream_class
->common
.packet_context_field_type
) {
985 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
986 g_string_append(context
->string
, "\n\n\tpacket.context := ");
987 ret
= bt_ctf_field_type_serialize_recursive(
988 (void *) stream_class
->common
.packet_context_field_type
,
991 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
995 g_string_append(context
->string
, ";");
998 if (stream_class
->common
.event_context_field_type
) {
999 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
1000 g_string_append(context
->string
, "\n\n\tevent.context := ");
1001 ret
= bt_ctf_field_type_serialize_recursive(
1002 (void *) stream_class
->common
.event_context_field_type
,
1005 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
1009 g_string_append(context
->string
, ";");
1012 g_string_append(context
->string
, "\n};\n\n");
1014 for (i
= 0; i
< stream_class
->common
.event_classes
->len
; i
++) {
1015 struct bt_ctf_event_class
*event_class
=
1016 stream_class
->common
.event_classes
->pdata
[i
];
1018 ret
= bt_ctf_event_class_serialize(event_class
, context
);
1020 BT_LOGW("Cannot serialize event class's metadata: "
1021 "event-class-addr=%p, event-class-name=\"%s\", "
1022 "event-class-id=%" PRId64
,
1024 bt_ctf_event_class_get_name(event_class
),
1025 bt_ctf_event_class_get_id(event_class
));
1031 bt_ctf_object_put_ref(packet_header_type
);
1032 context
->current_indentation_level
= 0;
1036 struct bt_ctf_trace
*bt_ctf_stream_class_get_trace(
1037 struct bt_ctf_stream_class
*stream_class
)
1039 return bt_ctf_object_get_ref(bt_ctf_stream_class_common_borrow_trace(
1040 BT_CTF_TO_COMMON(stream_class
)));
1043 const char *bt_ctf_stream_class_get_name(
1044 struct bt_ctf_stream_class
*stream_class
)
1046 return bt_ctf_stream_class_common_get_name(BT_CTF_TO_COMMON(stream_class
));
1049 int bt_ctf_stream_class_set_name(
1050 struct bt_ctf_stream_class
*stream_class
, const char *name
)
1052 return bt_ctf_stream_class_common_set_name(BT_CTF_TO_COMMON(stream_class
),
1056 int64_t bt_ctf_stream_class_get_id(
1057 struct bt_ctf_stream_class
*stream_class
)
1059 return bt_ctf_stream_class_common_get_id(BT_CTF_TO_COMMON(stream_class
));
1062 int bt_ctf_stream_class_set_id(
1063 struct bt_ctf_stream_class
*stream_class
, uint64_t id
)
1065 return bt_ctf_stream_class_common_set_id(BT_CTF_TO_COMMON(stream_class
), id
);
1068 struct bt_ctf_field_type
*bt_ctf_stream_class_get_packet_context_type(
1069 struct bt_ctf_stream_class
*stream_class
)
1071 return bt_ctf_object_get_ref(
1072 bt_ctf_stream_class_common_borrow_packet_context_field_type(
1073 BT_CTF_TO_COMMON(stream_class
)));
1076 int bt_ctf_stream_class_set_packet_context_type(
1077 struct bt_ctf_stream_class
*stream_class
,
1078 struct bt_ctf_field_type
*packet_context_type
)
1080 return bt_ctf_stream_class_common_set_packet_context_field_type(
1081 BT_CTF_TO_COMMON(stream_class
), (void *) packet_context_type
);
1084 struct bt_ctf_field_type
*
1085 bt_ctf_stream_class_get_event_header_type(
1086 struct bt_ctf_stream_class
*stream_class
)
1088 return bt_ctf_object_get_ref(
1089 bt_ctf_stream_class_common_borrow_event_header_field_type(
1090 BT_CTF_TO_COMMON(stream_class
)));
1093 int bt_ctf_stream_class_set_event_header_type(
1094 struct bt_ctf_stream_class
*stream_class
,
1095 struct bt_ctf_field_type
*event_header_type
)
1097 return bt_ctf_stream_class_common_set_event_header_field_type(
1098 BT_CTF_TO_COMMON(stream_class
), (void *) event_header_type
);
1101 struct bt_ctf_field_type
*
1102 bt_ctf_stream_class_get_event_context_type(
1103 struct bt_ctf_stream_class
*stream_class
)
1105 return bt_ctf_object_get_ref(
1106 bt_ctf_stream_class_common_borrow_event_context_field_type(
1107 BT_CTF_TO_COMMON(stream_class
)));
1110 int bt_ctf_stream_class_set_event_context_type(
1111 struct bt_ctf_stream_class
*stream_class
,
1112 struct bt_ctf_field_type
*event_context_type
)
1114 return bt_ctf_stream_class_common_set_event_context_field_type(
1115 BT_CTF_TO_COMMON(stream_class
), (void *) event_context_type
);
1118 int64_t bt_ctf_stream_class_get_event_class_count(
1119 struct bt_ctf_stream_class
*stream_class
)
1121 return bt_ctf_stream_class_common_get_event_class_count(
1122 BT_CTF_TO_COMMON(stream_class
));
1125 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_index(
1126 struct bt_ctf_stream_class
*stream_class
, uint64_t index
)
1128 return bt_ctf_object_get_ref(
1129 bt_ctf_stream_class_common_borrow_event_class_by_index(
1130 BT_CTF_TO_COMMON(stream_class
), index
));
1133 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_id(
1134 struct bt_ctf_stream_class
*stream_class
, uint64_t id
)
1136 return bt_ctf_object_get_ref(
1137 bt_ctf_stream_class_common_borrow_event_class_by_id(
1138 BT_CTF_TO_COMMON(stream_class
), id
));
1141 int bt_ctf_stream_class_add_event_class(
1142 struct bt_ctf_stream_class
*stream_class
,
1143 struct bt_ctf_event_class
*event_class
)
1145 return bt_ctf_stream_class_common_add_event_class(
1146 BT_CTF_TO_COMMON(stream_class
), BT_CTF_TO_COMMON(event_class
),
1147 (bt_ctf_validation_flag_copy_field_type_func
) bt_ctf_field_type_copy
);