4 * Babeltrace CTF IR - Stream Class
6 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 #define BT_LOG_TAG "STREAM-CLASS"
30 #include <babeltrace/lib-logging-internal.h>
32 #include <babeltrace/assert-pre-internal.h>
33 #include <babeltrace/ctf-ir/clock-class-internal.h>
34 #include <babeltrace/ctf-ir/event-class-internal.h>
35 #include <babeltrace/ctf-ir/field-types-internal.h>
36 #include <babeltrace/ctf-ir/fields-internal.h>
37 #include <babeltrace/ctf-ir/stream-class-internal.h>
38 #include <babeltrace/ctf-ir/validation-internal.h>
39 #include <babeltrace/ctf-ir/visitor-internal.h>
40 #include <babeltrace/ctf-ir/utils.h>
41 #include <babeltrace/ctf-ir/utils-internal.h>
42 #include <babeltrace/ctf-ir/field-wrapper-internal.h>
43 #include <babeltrace/ref.h>
44 #include <babeltrace/compiler-internal.h>
45 #include <babeltrace/align-internal.h>
46 #include <babeltrace/endian-internal.h>
47 #include <babeltrace/assert-internal.h>
53 int bt_stream_class_initialize(struct bt_stream_class
*stream_class
,
54 const char *name
, bt_object_release_func release_func
)
56 BT_LOGD("Initializing stream class object: name=\"%s\"", name
);
58 bt_object_init_shared_with_parent(&stream_class
->base
, release_func
);
59 stream_class
->name
= g_string_new(name
);
60 stream_class
->event_classes
= g_ptr_array_new_with_free_func(
61 (GDestroyNotify
) bt_object_try_spec_release
);
62 if (!stream_class
->event_classes
) {
63 BT_LOGE_STR("Failed to allocate a GPtrArray.");
67 stream_class
->event_classes_ht
= g_hash_table_new_full(g_int64_hash
,
68 g_int64_equal
, g_free
, NULL
);
69 if (!stream_class
->event_classes_ht
) {
70 BT_LOGE_STR("Failed to allocate a GHashTable.");
74 BT_LOGD("Initialized stream class object: addr=%p, name=\"%s\"",
83 void bt_stream_class_destroy(struct bt_object
*obj
)
85 struct bt_stream_class
*stream_class
= (void *) obj
;
87 BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64
,
88 stream_class
, bt_stream_class_get_name(stream_class
),
89 bt_stream_class_get_id(stream_class
));
90 bt_put(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_put(stream_class
->event_header_field_type
);
106 BT_LOGD_STR("Putting packet context field type.");
107 bt_put(stream_class
->packet_context_field_type
);
108 BT_LOGD_STR("Putting event context field type.");
109 bt_put(stream_class
->event_context_field_type
);
110 bt_object_pool_finalize(&stream_class
->event_header_field_pool
);
111 bt_object_pool_finalize(&stream_class
->packet_context_field_pool
);
112 g_free(stream_class
);
116 void free_field_wrapper(struct bt_field_wrapper
*field_wrapper
,
117 struct bt_stream_class
*stream_class
)
119 bt_field_wrapper_destroy((void *) field_wrapper
);
122 struct bt_stream_class
*bt_stream_class_create(const char *name
)
124 struct bt_stream_class
*stream_class
= NULL
;
127 BT_LOGD("Creating stream class object: name=\"%s\"", name
);
128 stream_class
= g_new0(struct bt_stream_class
, 1);
130 BT_LOGE_STR("Failed to allocate one stream class.");
134 ret
= bt_stream_class_initialize(stream_class
, name
,
135 bt_stream_class_destroy
);
137 /* bt_stream_class_initialize() logs errors */
141 ret
= bt_object_pool_initialize(&stream_class
->event_header_field_pool
,
142 (bt_object_pool_new_object_func
) bt_field_wrapper_new
,
143 (bt_object_pool_destroy_object_func
) free_field_wrapper
,
146 BT_LOGE("Failed to initialize event header field pool: ret=%d",
151 ret
= bt_object_pool_initialize(&stream_class
->packet_context_field_pool
,
152 (bt_object_pool_new_object_func
) bt_field_wrapper_new
,
153 (bt_object_pool_destroy_object_func
) free_field_wrapper
,
156 BT_LOGE("Failed to initialize packet context field pool: ret=%d",
161 BT_LOGD("Created stream class object: addr=%p, name=\"%s\"",
166 bt_put(stream_class
);
170 struct bt_event_header_field
*bt_stream_class_create_event_header_field(
171 struct bt_stream_class
*stream_class
)
173 struct bt_field_wrapper
*field_wrapper
;
175 BT_ASSERT_PRE_NON_NULL(stream_class
, "Stream class");
176 BT_ASSERT_PRE(stream_class
->frozen
,
177 "Stream class is not part of a trace: %!+S", stream_class
);
178 BT_ASSERT_PRE(stream_class
->event_header_field_type
,
179 "Stream class has no event header field type: %!+S",
181 field_wrapper
= bt_field_wrapper_create(
182 &stream_class
->event_header_field_pool
,
183 (void *) stream_class
->event_header_field_type
);
184 if (!field_wrapper
) {
185 BT_LIB_LOGE("Cannot allocate one event header field from stream class: "
186 "%![sc-]+S", stream_class
);
190 BT_ASSERT(field_wrapper
->field
);
195 bt_field_wrapper_destroy(field_wrapper
);
196 field_wrapper
= NULL
;
200 return (void *) field_wrapper
;
203 struct bt_packet_context_field
*bt_stream_class_create_packet_context_field(
204 struct bt_stream_class
*stream_class
)
206 struct bt_field_wrapper
*field_wrapper
;
208 BT_ASSERT_PRE_NON_NULL(stream_class
, "Stream class");
209 BT_ASSERT_PRE(stream_class
->frozen
,
210 "Stream class is not part of a trace: %!+S", stream_class
);
211 BT_ASSERT_PRE(stream_class
->packet_context_field_type
,
212 "Stream class has no packet context field type: %!+S",
214 field_wrapper
= bt_field_wrapper_create(
215 &stream_class
->packet_context_field_pool
,
216 (void *) stream_class
->packet_context_field_type
);
217 if (!field_wrapper
) {
218 BT_LIB_LOGE("Cannot allocate one packet context field from stream class: "
219 "%![sc-]+S", stream_class
);
223 BT_ASSERT(field_wrapper
->field
);
228 bt_field_wrapper_destroy(field_wrapper
);
229 field_wrapper
= NULL
;
233 return (void *) field_wrapper
;
236 struct bt_trace
*bt_stream_class_borrow_trace(struct bt_stream_class
*stream_class
)
238 BT_ASSERT(stream_class
);
239 return (void *) bt_object_borrow_parent(&stream_class
->base
);
242 const char *bt_stream_class_get_name(struct bt_stream_class
*stream_class
)
244 BT_ASSERT_PRE_NON_NULL(stream_class
, "Stream class");
245 return stream_class
->name
->len
> 0 ? stream_class
->name
->str
: NULL
;
248 int bt_stream_class_set_name(struct bt_stream_class
*stream_class
,
254 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
259 if (stream_class
->frozen
) {
260 BT_LOGW("Invalid parameter: stream class is frozen: "
261 "addr=%p, name=\"%s\", id=%" PRId64
,
263 bt_stream_class_get_name(stream_class
),
264 bt_stream_class_get_id(stream_class
));
270 g_string_assign(stream_class
->name
, "");
272 if (strlen(name
) == 0) {
273 BT_LOGW("Invalid parameter: name is empty.");
278 g_string_assign(stream_class
->name
, name
);
281 BT_LOGV("Set stream class's name: "
282 "addr=%p, name=\"%s\", id=%" PRId64
,
283 stream_class
, bt_stream_class_get_name(stream_class
),
284 bt_stream_class_get_id(stream_class
));
289 int64_t bt_stream_class_get_id(struct bt_stream_class
*stream_class
)
293 BT_ASSERT_PRE_NON_NULL(stream_class
, "Stream class");
295 if (!stream_class
->id_set
) {
296 BT_LOGV("Stream class's ID is not set: addr=%p, name=\"%s\"",
298 bt_stream_class_get_name(stream_class
));
303 ret
= stream_class
->id
;
309 int bt_stream_class_set_id(struct bt_stream_class
*stream_class
,
313 int64_t id
= (int64_t) id_param
;
316 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
321 if (stream_class
->frozen
) {
322 BT_LOGW("Invalid parameter: stream class is frozen: "
323 "addr=%p, name=\"%s\", id=%" PRId64
,
325 bt_stream_class_get_name(stream_class
),
326 bt_stream_class_get_id(stream_class
));
332 BT_LOGW("Invalid parameter: invalid stream class's ID: "
333 "stream-class-addr=%p, stream-class-name=\"%s\", "
334 "stream-class-id=%" PRId64
", id=%" PRIu64
,
336 bt_stream_class_get_name(stream_class
),
337 bt_stream_class_get_id(stream_class
),
343 ret
= bt_stream_class_set_id_no_check(stream_class
, id
);
345 BT_LOGV("Set stream class's ID: "
346 "addr=%p, name=\"%s\", id=%" PRId64
,
348 bt_stream_class_get_name(stream_class
),
349 bt_stream_class_get_id(stream_class
));
356 void event_class_exists(gpointer element
, gpointer query
)
358 struct bt_event_class
*event_class_a
= element
;
359 struct search_query
*search_query
= query
;
360 struct bt_event_class
*event_class_b
= search_query
->value
;
363 if (search_query
->value
== element
) {
364 search_query
->found
= 1;
369 * Two event classes cannot share the same ID in a given
372 id_a
= bt_event_class_get_id(event_class_a
);
373 id_b
= bt_event_class_get_id(event_class_b
);
375 if (id_a
< 0 || id_b
< 0) {
376 /* at least one ID is not set: will be automatically set later */
381 BT_LOGW("Event class with this ID already exists in the stream class: "
382 "id=%" PRId64
", name=\"%s\"",
383 id_a
, bt_event_class_get_name(event_class_a
));
384 search_query
->found
= 1;
392 int bt_stream_class_add_event_class(struct bt_stream_class
*stream_class
,
393 struct bt_event_class
*event_class
)
396 int64_t *event_id
= NULL
;
397 struct bt_trace
*trace
= NULL
;
398 struct bt_stream_class
*old_stream_class
= NULL
;
399 struct bt_validation_output validation_output
= { 0 };
400 struct bt_field_type
*packet_header_type
= NULL
;
401 struct bt_field_type
*packet_context_type
= NULL
;
402 struct bt_field_type
*event_header_type
= NULL
;
403 struct bt_field_type
*stream_event_ctx_type
= NULL
;
404 struct bt_field_type
*event_context_type
= NULL
;
405 struct bt_field_type
*event_payload_type
= NULL
;
406 const enum bt_validation_flag validation_flags
=
407 BT_VALIDATION_FLAG_EVENT
;
408 struct bt_clock_class
*expected_clock_class
= NULL
;
411 BT_LOGW("Invalid parameter: stream class is NULL: "
412 "stream-class-addr=%p", stream_class
);
417 trace
= bt_stream_class_borrow_trace(stream_class
);
418 if (trace
&& trace
->is_static
) {
419 BT_LOGW("Invalid parameter: stream class's trace is static: "
420 "trace-addr=%p, trace-name=\"%s\"",
421 trace
, bt_trace_get_name(trace
));
426 if (!stream_class
|| !event_class
) {
427 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
428 "stream-class-addr=%p, event-class-addr=%p",
429 stream_class
, event_class
);
434 BT_LOGD("Adding event class to stream class: "
435 "stream-class-addr=%p, stream-class-name=\"%s\", "
436 "stream-class-id=%" PRId64
", event-class-addr=%p, "
437 "event-class-name=\"%s\", event-class-id=%" PRId64
,
438 stream_class
, bt_stream_class_get_name(stream_class
),
439 bt_stream_class_get_id(stream_class
),
441 bt_event_class_get_name(event_class
),
442 bt_event_class_get_id(event_class
));
443 trace
= bt_stream_class_borrow_trace(stream_class
);
445 if (stream_class
->frozen
) {
447 * We only check that the event class to be added has a
448 * single class which matches the stream class's
449 * expected clock class if the stream class is frozen.
450 * If it's not, then this event class is added "as is"
451 * and the validation will be performed when calling
452 * either bt_trace_add_stream_class() or
453 * bt_event_create(). This is because the stream class's
454 * field types (packet context, event header, event
455 * context) could change before the next call to one of
456 * those two functions.
458 expected_clock_class
= bt_get(stream_class
->clock_class
);
461 * At this point, `expected_clock_class` can be NULL,
462 * and bt_event_class_validate_single_clock_class()
465 ret
= bt_event_class_validate_single_clock_class(
466 event_class
, &expected_clock_class
);
468 BT_LOGW("Event class contains a field type which is not "
469 "recursively mapped to its stream class's "
470 "expected clock class: "
471 "stream-class-addr=%p, "
472 "stream-class-id=%" PRId64
", "
473 "stream-class-name=\"%s\", "
474 "expected-clock-class-addr=%p, "
475 "expected-clock-class-name=\"%s\"",
477 bt_stream_class_get_id(stream_class
),
478 bt_stream_class_get_name(stream_class
),
479 expected_clock_class
,
480 expected_clock_class
?
481 bt_clock_class_get_name(expected_clock_class
) :
487 event_id
= g_new(int64_t, 1);
489 BT_LOGE_STR("Failed to allocate one int64_t.");
494 /* Check for duplicate event classes */
495 struct search_query query
= { .value
= event_class
, .found
= 0 };
496 g_ptr_array_foreach(stream_class
->event_classes
, event_class_exists
,
499 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
504 old_stream_class
= bt_event_class_borrow_stream_class(event_class
);
505 if (old_stream_class
) {
506 /* Event class is already associated to a stream class. */
507 BT_LOGW("Event class is already part of another stream class: "
508 "event-class-stream-class-addr=%p, "
509 "event-class-stream-class-name=\"%s\", "
510 "event-class-stream-class-id=%" PRId64
,
512 bt_stream_class_get_name(old_stream_class
),
513 bt_stream_class_get_id(old_stream_class
));
520 * If the stream class is associated with a trace, then
521 * both those objects are frozen. Also, this event class
522 * is about to be frozen.
524 * Therefore the event class must be validated here.
525 * The trace and stream class should be valid at this
528 BT_ASSERT(trace
->valid
);
529 BT_ASSERT(stream_class
->valid
);
531 bt_trace_borrow_packet_header_field_type(trace
);
532 packet_context_type
=
533 bt_stream_class_borrow_packet_context_field_type(
536 bt_stream_class_borrow_event_header_field_type(
538 stream_event_ctx_type
=
539 bt_stream_class_borrow_event_context_field_type(
542 bt_event_class_borrow_context_field_type(
545 bt_event_class_borrow_payload_field_type(
547 ret
= bt_validate_class_types(
548 trace
->environment
, packet_header_type
,
549 packet_context_type
, event_header_type
,
550 stream_event_ctx_type
, event_context_type
,
551 event_payload_type
, trace
->valid
,
552 stream_class
->valid
, event_class
->valid
,
553 &validation_output
, validation_flags
,
558 * This means something went wrong during the
559 * validation process, not that the objects are
562 BT_LOGE("Failed to validate event class: ret=%d", ret
);
566 if ((validation_output
.valid_flags
& validation_flags
) !=
568 /* Invalid event class */
569 BT_LOGW("Invalid trace, stream class, or event class: "
571 validation_output
.valid_flags
);
577 /* Only set an event ID if none was explicitly set before */
578 *event_id
= bt_event_class_get_id(event_class
);
580 BT_LOGV("Event class has no ID: automatically setting it: "
581 "id=%" PRId64
, stream_class
->next_event_id
);
583 if (bt_event_class_set_id(event_class
,
584 stream_class
->next_event_id
)) {
585 BT_LOGE("Cannot set event class's ID: id=%" PRId64
,
586 stream_class
->next_event_id
);
590 stream_class
->next_event_id
++;
591 *event_id
= stream_class
->next_event_id
;
594 bt_object_set_parent(&event_class
->base
, &stream_class
->base
);
598 * At this point we know that the function will be
599 * successful. Therefore we can replace the event
600 * class's field types with what's in the validation
601 * output structure and mark this event class as valid.
603 bt_validation_replace_types(NULL
, NULL
, event_class
,
604 &validation_output
, validation_flags
);
605 event_class
->valid
= 1;
608 * Put what was not moved in
609 * bt_validation_replace_types().
611 bt_validation_output_put_types(&validation_output
);
614 /* Add to the event classes of the stream class */
615 g_ptr_array_add(stream_class
->event_classes
, event_class
);
616 g_hash_table_insert(stream_class
->event_classes_ht
, event_id
,
620 /* Freeze the event class */
621 bt_event_class_freeze(event_class
);
624 * It is safe to set the stream class's unique clock class
625 * now if the stream class is frozen.
627 if (stream_class
->frozen
&& expected_clock_class
) {
628 BT_ASSERT(!stream_class
->clock_class
||
629 stream_class
->clock_class
== expected_clock_class
);
630 BT_MOVE(stream_class
->clock_class
, expected_clock_class
);
633 /* Notifiy listeners of the trace's schema modification. */
635 struct bt_visitor_object obj
= { .object
= event_class
,
636 .type
= BT_VISITOR_OBJECT_TYPE_EVENT_CLASS
};
638 (void) bt_trace_object_modification(&obj
, trace
);
641 BT_LOGD("Added event class to stream class: "
642 "stream-class-addr=%p, stream-class-name=\"%s\", "
643 "stream-class-id=%" PRId64
", event-class-addr=%p, "
644 "event-class-name=\"%s\", event-class-id=%" PRId64
,
645 stream_class
, bt_stream_class_get_name(stream_class
),
646 bt_stream_class_get_id(stream_class
),
648 bt_event_class_get_name(event_class
),
649 bt_event_class_get_id(event_class
));
652 bt_validation_output_put_types(&validation_output
);
653 bt_put(expected_clock_class
);
658 int64_t bt_stream_class_get_event_class_count(
659 struct bt_stream_class
*stream_class
)
664 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
669 ret
= (int64_t) stream_class
->event_classes
->len
;
674 struct bt_event_class
*bt_stream_class_borrow_event_class_by_index(
675 struct bt_stream_class
*stream_class
, uint64_t index
)
677 BT_ASSERT_PRE_NON_NULL(stream_class
, "Stream class");
678 BT_ASSERT_PRE(index
< stream_class
->event_classes
->len
,
679 "Index is out of bounds: index=%" PRIu64
", "
681 index
, stream_class
->event_classes
->len
);
682 return g_ptr_array_index(stream_class
->event_classes
, index
);
685 struct bt_event_class
*bt_stream_class_borrow_event_class_by_id(
686 struct bt_stream_class
*stream_class
, uint64_t id
)
688 int64_t id_key
= (int64_t) id
;
690 BT_ASSERT_PRE_NON_NULL(stream_class
, "Stream class");
691 BT_ASSERT_PRE(id_key
>= 0,
692 "Invalid event class ID: %" PRIu64
, id
);
693 return g_hash_table_lookup(stream_class
->event_classes_ht
,
697 struct bt_field_type
*bt_stream_class_borrow_packet_context_field_type(
698 struct bt_stream_class
*stream_class
)
700 BT_ASSERT_PRE_NON_NULL(stream_class
, "Stream class");
701 return stream_class
->packet_context_field_type
;
704 int bt_stream_class_set_packet_context_field_type(
705 struct bt_stream_class
*stream_class
,
706 struct bt_field_type
*packet_context_type
)
711 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
716 if (stream_class
->frozen
) {
717 BT_LOGW("Invalid parameter: stream class is frozen: "
718 "addr=%p, name=\"%s\", id=%" PRId64
,
719 stream_class
, bt_stream_class_get_name(stream_class
),
720 bt_stream_class_get_id(stream_class
));
725 if (packet_context_type
&&
726 bt_field_type_get_type_id(packet_context_type
) !=
727 BT_FIELD_TYPE_ID_STRUCT
) {
728 /* A packet context must be a structure. */
729 BT_LOGW("Invalid parameter: stream class's packet context field type must be a structure: "
730 "addr=%p, name=\"%s\", id=%" PRId64
", "
731 "packet-context-ft-addr=%p, packet-context-ft-id=%s",
732 stream_class
, bt_stream_class_get_name(stream_class
),
733 bt_stream_class_get_id(stream_class
),
735 bt_common_field_type_id_string(
736 bt_field_type_get_type_id(packet_context_type
)));
741 bt_put(stream_class
->packet_context_field_type
);
742 bt_get(packet_context_type
);
743 stream_class
->packet_context_field_type
= packet_context_type
;
744 BT_LOGV("Set stream class's packet context field type: "
745 "addr=%p, name=\"%s\", id=%" PRId64
", "
746 "packet-context-ft-addr=%p",
747 stream_class
, bt_stream_class_get_name(stream_class
),
748 bt_stream_class_get_id(stream_class
),
749 packet_context_type
);
755 struct bt_field_type
*bt_stream_class_borrow_event_header_field_type(
756 struct bt_stream_class
*stream_class
)
758 struct bt_field_type
*ret
= NULL
;
760 BT_ASSERT_PRE_NON_NULL(stream_class
, "Stream class");
762 if (!stream_class
->event_header_field_type
) {
763 BT_LOGV("Stream class has no event header field type: "
764 "addr=%p, name=\"%s\", id=%" PRId64
,
766 bt_stream_class_get_name(stream_class
),
767 bt_stream_class_get_id(stream_class
));
771 ret
= stream_class
->event_header_field_type
;
777 int bt_stream_class_set_event_header_field_type(
778 struct bt_stream_class
*stream_class
,
779 struct bt_field_type
*event_header_type
)
784 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
789 if (stream_class
->frozen
) {
790 BT_LOGW("Invalid parameter: stream class is frozen: "
791 "addr=%p, name=\"%s\", id=%" PRId64
,
793 bt_stream_class_get_name(stream_class
),
794 bt_stream_class_get_id(stream_class
));
799 if (event_header_type
&&
800 bt_field_type_get_type_id(event_header_type
) !=
801 BT_FIELD_TYPE_ID_STRUCT
) {
802 /* An event header must be a structure. */
803 BT_LOGW("Invalid parameter: stream class's event header field type must be a structure: "
804 "addr=%p, name=\"%s\", id=%" PRId64
", "
805 "event-header-ft-addr=%p, event-header-ft-id=%s",
806 stream_class
, bt_stream_class_get_name(stream_class
),
807 bt_stream_class_get_id(stream_class
),
809 bt_common_field_type_id_string(
810 bt_field_type_get_type_id(event_header_type
)));
815 bt_put(stream_class
->event_header_field_type
);
816 stream_class
->event_header_field_type
= bt_get(event_header_type
);
817 BT_LOGV("Set stream class's event header field type: "
818 "addr=%p, name=\"%s\", id=%" PRId64
", "
819 "event-header-ft-addr=%p",
820 stream_class
, bt_stream_class_get_name(stream_class
),
821 bt_stream_class_get_id(stream_class
),
827 struct bt_field_type
*bt_stream_class_borrow_event_context_field_type(
828 struct bt_stream_class
*stream_class
)
830 struct bt_field_type
*ret
= NULL
;
832 BT_ASSERT_PRE_NON_NULL(stream_class
, "Stream class");
834 if (!stream_class
->event_context_field_type
) {
838 ret
= stream_class
->event_context_field_type
;
844 int bt_stream_class_set_event_context_field_type(
845 struct bt_stream_class
*stream_class
,
846 struct bt_field_type
*event_context_type
)
851 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
856 if (stream_class
->frozen
) {
857 BT_LOGW("Invalid parameter: stream class is frozen: "
858 "addr=%p, name=\"%s\", id=%" PRId64
,
859 stream_class
, bt_stream_class_get_name(stream_class
),
860 bt_stream_class_get_id(stream_class
));
865 if (event_context_type
&&
866 bt_field_type_get_type_id(event_context_type
) !=
867 BT_FIELD_TYPE_ID_STRUCT
) {
868 /* A packet context must be a structure. */
869 BT_LOGW("Invalid parameter: stream class's event context field type must be a structure: "
870 "addr=%p, name=\"%s\", id=%" PRId64
", "
871 "event-context-ft-addr=%p, event-context-ft-id=%s",
872 stream_class
, bt_stream_class_get_name(stream_class
),
873 bt_stream_class_get_id(stream_class
),
875 bt_common_field_type_id_string(
876 bt_field_type_get_type_id(event_context_type
)));
881 bt_put(stream_class
->event_context_field_type
);
882 stream_class
->event_context_field_type
= bt_get(event_context_type
);
883 BT_LOGV("Set stream class's event context field type: "
884 "addr=%p, name=\"%s\", id=%" PRId64
", "
885 "event-context-ft-addr=%p",
886 stream_class
, bt_stream_class_get_name(stream_class
),
887 bt_stream_class_get_id(stream_class
),
894 int64_t get_event_class_count(void *element
)
896 return bt_stream_class_get_event_class_count(
897 (struct bt_stream_class
*) element
);
901 void *get_event_class(void *element
, int i
)
903 return bt_stream_class_get_event_class_by_index(
904 (struct bt_stream_class
*) element
, i
);
908 int visit_event_class(void *object
, bt_visitor visitor
,void *data
)
910 struct bt_visitor_object obj
= {
912 .type
= BT_VISITOR_OBJECT_TYPE_EVENT_CLASS
915 return visitor(&obj
, data
);
919 int bt_stream_class_visit(struct bt_stream_class
*stream_class
,
920 bt_visitor visitor
, void *data
)
923 struct bt_visitor_object obj
= {
924 .object
= stream_class
,
925 .type
= BT_VISITOR_OBJECT_TYPE_STREAM_CLASS
928 if (!stream_class
|| !visitor
) {
929 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
930 "stream-class-addr=%p, visitor=%p",
931 stream_class
, visitor
);
936 ret
= visitor_helper(&obj
, get_event_class_count
,
938 visit_event_class
, visitor
, data
);
939 BT_LOGV("visitor_helper() returned: ret=%d", ret
);
946 void bt_stream_class_freeze(struct bt_stream_class
*stream_class
)
948 if (!stream_class
|| stream_class
->frozen
) {
952 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64
,
953 stream_class
, bt_stream_class_get_name(stream_class
),
954 bt_stream_class_get_id(stream_class
));
955 stream_class
->frozen
= 1;
956 bt_field_type_freeze(stream_class
->event_header_field_type
);
957 bt_field_type_freeze(stream_class
->packet_context_field_type
);
958 bt_field_type_freeze(stream_class
->event_context_field_type
);
959 bt_clock_class_freeze(stream_class
->clock_class
);
963 int bt_stream_class_validate_single_clock_class(
964 struct bt_stream_class
*stream_class
,
965 struct bt_clock_class
**expected_clock_class
)
970 BT_ASSERT(stream_class
);
971 BT_ASSERT(expected_clock_class
);
972 ret
= bt_field_type_validate_single_clock_class(
973 stream_class
->packet_context_field_type
,
974 expected_clock_class
);
976 BT_LOGW("Stream class's packet context field type "
977 "is not recursively mapped to the "
978 "expected clock class: "
979 "stream-class-addr=%p, "
980 "stream-class-name=\"%s\", "
981 "stream-class-id=%" PRId64
", "
984 bt_stream_class_get_name(stream_class
),
986 stream_class
->packet_context_field_type
);
990 ret
= bt_field_type_validate_single_clock_class(
991 stream_class
->event_header_field_type
,
992 expected_clock_class
);
994 BT_LOGW("Stream class's event header field type "
995 "is not recursively mapped to the "
996 "expected clock class: "
997 "stream-class-addr=%p, "
998 "stream-class-name=\"%s\", "
999 "stream-class-id=%" PRId64
", "
1002 bt_stream_class_get_name(stream_class
),
1004 stream_class
->event_header_field_type
);
1008 ret
= bt_field_type_validate_single_clock_class(
1009 stream_class
->event_context_field_type
,
1010 expected_clock_class
);
1012 BT_LOGW("Stream class's event context field type "
1013 "is not recursively mapped to the "
1014 "expected clock class: "
1015 "stream-class-addr=%p, "
1016 "stream-class-name=\"%s\", "
1017 "stream-class-id=%" PRId64
", "
1020 bt_stream_class_get_name(stream_class
),
1022 stream_class
->event_context_field_type
);
1026 for (i
= 0; i
< stream_class
->event_classes
->len
; i
++) {
1027 struct bt_event_class
*event_class
=
1028 g_ptr_array_index(stream_class
->event_classes
, i
);
1030 BT_ASSERT(event_class
);
1031 ret
= bt_event_class_validate_single_clock_class(
1032 event_class
, expected_clock_class
);
1034 BT_LOGW("Stream class's event class contains a "
1035 "field type which is not recursively mapped to "
1036 "the expected clock class: "
1037 "stream-class-addr=%p, "
1038 "stream-class-name=\"%s\", "
1039 "stream-class-id=%" PRId64
,
1041 bt_stream_class_get_name(stream_class
),