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/ctf-writer/clock.h>
33 #include <babeltrace/ctf-writer/clock-internal.h>
34 #include <babeltrace/ctf-ir/clock-class-internal.h>
35 #include <babeltrace/ctf-writer/event.h>
36 #include <babeltrace/ctf-ir/event-class-internal.h>
37 #include <babeltrace/ctf-ir/event-internal.h>
38 #include <babeltrace/ctf-ir/field-types-internal.h>
39 #include <babeltrace/ctf-ir/fields-internal.h>
40 #include <babeltrace/ctf-writer/stream.h>
41 #include <babeltrace/ctf-ir/stream-class-internal.h>
42 #include <babeltrace/ctf-ir/validation-internal.h>
43 #include <babeltrace/ctf-ir/visitor-internal.h>
44 #include <babeltrace/ctf-writer/functor-internal.h>
45 #include <babeltrace/ctf-ir/utils.h>
46 #include <babeltrace/ctf-ir/utils-internal.h>
47 #include <babeltrace/ref.h>
48 #include <babeltrace/compiler-internal.h>
49 #include <babeltrace/align-internal.h>
50 #include <babeltrace/endian-internal.h>
51 #include <babeltrace/assert-internal.h>
52 #include <babeltrace/assert-pre-internal.h>
58 void bt_stream_class_destroy(struct bt_object
*obj
);
60 int init_event_header(struct bt_stream_class
*stream_class
);
62 int init_packet_context(struct bt_stream_class
*stream_class
);
64 struct bt_stream_class
*bt_stream_class_create(const char *name
)
66 struct bt_stream_class
*stream_class
;
69 BT_LOGD("Creating default stream class object: name=\"%s\"", name
);
70 stream_class
= bt_stream_class_create_empty(name
);
72 BT_LOGD_STR("Cannot create empty stream class.");
76 ret
= init_event_header(stream_class
);
78 BT_LOGE_STR("Cannot initialize stream class's event header field type.");
82 ret
= init_packet_context(stream_class
);
84 BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
88 BT_LOGD("Created default stream class object: addr=%p, name=\"%s\"",
97 struct bt_stream_class
*bt_stream_class_create_empty(const char *name
)
99 struct bt_stream_class
*stream_class
= NULL
;
101 BT_LOGD("Creating empty stream class object: name=\"%s\"", name
);
103 stream_class
= g_new0(struct bt_stream_class
, 1);
105 BT_LOGE_STR("Failed to allocate one stream class.");
109 stream_class
->name
= g_string_new(name
);
110 stream_class
->event_classes
= g_ptr_array_new_with_free_func(
111 (GDestroyNotify
) bt_object_release
);
112 if (!stream_class
->event_classes
) {
113 BT_LOGE_STR("Failed to allocate a GPtrArray.");
117 stream_class
->event_classes_ht
= g_hash_table_new_full(g_int64_hash
,
118 g_int64_equal
, g_free
, NULL
);
119 if (!stream_class
->event_classes_ht
) {
120 BT_LOGE_STR("Failed to allocate a GHashTable.");
124 bt_object_init(stream_class
, bt_stream_class_destroy
);
125 BT_LOGD("Created empty stream class object: addr=%p, name=\"%s\"",
130 BT_PUT(stream_class
);
134 struct bt_trace
*bt_stream_class_get_trace(
135 struct bt_stream_class
*stream_class
)
137 BT_ASSERT_PRE_NON_NULL(stream_class
, "Stream class");
138 return bt_get(bt_stream_class_borrow_trace(stream_class
));
141 const char *bt_stream_class_get_name(
142 struct bt_stream_class
*stream_class
)
144 BT_ASSERT_PRE_NON_NULL(stream_class
, "Stream class");
145 return stream_class
->name
->len
> 0 ? stream_class
->name
->str
: NULL
;
148 int bt_stream_class_set_name(struct bt_stream_class
*stream_class
,
154 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
159 if (stream_class
->frozen
) {
160 BT_LOGW("Invalid parameter: stream class is frozen: "
161 "addr=%p, name=\"%s\", id=%" PRId64
,
162 stream_class
, bt_stream_class_get_name(stream_class
),
163 bt_stream_class_get_id(stream_class
));
169 g_string_assign(stream_class
->name
, "");
171 if (strlen(name
) == 0) {
172 BT_LOGW("Invalid parameter: name is empty.");
177 g_string_assign(stream_class
->name
, name
);
180 BT_LOGV("Set stream class's name: "
181 "addr=%p, name=\"%s\", id=%" PRId64
,
182 stream_class
, bt_stream_class_get_name(stream_class
),
183 bt_stream_class_get_id(stream_class
));
188 struct bt_ctf_clock
*bt_stream_class_get_clock(
189 struct bt_stream_class
*stream_class
)
191 struct bt_ctf_clock
*clock
= NULL
;
194 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
198 if (!stream_class
->clock
) {
199 BT_LOGV("Stream class has no clock: "
200 "addr=%p, name=\"%s\", id=%" PRId64
,
201 stream_class
, bt_stream_class_get_name(stream_class
),
202 bt_stream_class_get_id(stream_class
));
206 clock
= bt_get(stream_class
->clock
);
211 int bt_stream_class_set_clock(struct bt_stream_class
*stream_class
,
212 struct bt_ctf_clock
*clock
)
215 struct bt_field_type
*timestamp_field
= NULL
;
217 if (!stream_class
|| !clock
) {
218 BT_LOGW("Invalid parameter: stream class or clock is NULL: "
219 "stream-class-addr=%p, clock-addr=%p",
220 stream_class
, clock
);
225 if (stream_class
->frozen
) {
226 BT_LOGW("Invalid parameter: stream class is frozen: "
227 "addr=%p, name=\"%s\", id=%" PRId64
,
228 stream_class
, bt_stream_class_get_name(stream_class
),
229 bt_stream_class_get_id(stream_class
));
234 /* Replace the current clock of this stream class. */
235 bt_put(stream_class
->clock
);
236 stream_class
->clock
= bt_get(clock
);
237 BT_LOGV("Set stream class's clock: "
238 "addr=%p, name=\"%s\", id=%" PRId64
", "
239 "clock-addr=%p, clock-name=\"%s\"",
240 stream_class
, bt_stream_class_get_name(stream_class
),
241 bt_stream_class_get_id(stream_class
),
243 bt_ctf_clock_get_name(stream_class
->clock
));
246 bt_put(timestamp_field
);
250 int64_t bt_stream_class_get_id(struct bt_stream_class
*stream_class
)
254 BT_ASSERT_PRE_NON_NULL(stream_class
, "Stream class");
256 if (!stream_class
->id_set
) {
257 BT_LOGV("Stream class's ID is not set: addr=%p, name=\"%s\"",
259 bt_stream_class_get_name(stream_class
));
264 ret
= stream_class
->id
;
271 void _bt_stream_class_set_id(
272 struct bt_stream_class
*stream_class
, int64_t id
)
274 BT_ASSERT(stream_class
);
275 stream_class
->id
= id
;
276 stream_class
->id_set
= 1;
277 BT_LOGV("Set stream class's ID (internal): "
278 "addr=%p, name=\"%s\", id=%" PRId64
,
279 stream_class
, bt_stream_class_get_name(stream_class
),
280 bt_stream_class_get_id(stream_class
));
283 struct event_class_set_stream_class_id_data
{
284 int64_t stream_class_id
;
289 int bt_stream_class_set_id_no_check(
290 struct bt_stream_class
*stream_class
, int64_t id
)
292 _bt_stream_class_set_id(stream_class
, id
);
296 int bt_stream_class_set_id(struct bt_stream_class
*stream_class
,
300 int64_t id
= (int64_t) id_param
;
303 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
308 if (stream_class
->frozen
) {
309 BT_LOGW("Invalid parameter: stream class is frozen: "
310 "addr=%p, name=\"%s\", id=%" PRId64
,
311 stream_class
, bt_stream_class_get_name(stream_class
),
312 bt_stream_class_get_id(stream_class
));
318 BT_LOGW("Invalid parameter: invalid stream class's ID: "
319 "stream-class-addr=%p, stream-class-name=\"%s\", "
320 "stream-class-id=%" PRId64
", id=%" PRIu64
,
321 stream_class
, bt_stream_class_get_name(stream_class
),
322 bt_stream_class_get_id(stream_class
),
328 ret
= bt_stream_class_set_id_no_check(stream_class
, id
);
330 BT_LOGV("Set stream class's ID: "
331 "addr=%p, name=\"%s\", id=%" PRId64
,
332 stream_class
, bt_stream_class_get_name(stream_class
),
333 bt_stream_class_get_id(stream_class
));
340 void event_class_exists(gpointer element
, gpointer query
)
342 struct bt_event_class
*event_class_a
= element
;
343 struct search_query
*search_query
= query
;
344 struct bt_event_class
*event_class_b
= search_query
->value
;
347 if (search_query
->value
== element
) {
348 search_query
->found
= 1;
353 * Two event classes cannot share the same ID in a given
356 id_a
= bt_event_class_get_id(event_class_a
);
357 id_b
= bt_event_class_get_id(event_class_b
);
359 if (id_a
< 0 || id_b
< 0) {
360 /* at least one ID is not set: will be automatically set later */
365 BT_LOGW("Event class with this ID already exists in the stream class: "
366 "id=%" PRId64
", name=\"%s\"",
367 id_a
, bt_event_class_get_name(event_class_a
));
368 search_query
->found
= 1;
376 int bt_stream_class_add_event_class(
377 struct bt_stream_class
*stream_class
,
378 struct bt_event_class
*event_class
)
381 int64_t *event_id
= NULL
;
382 struct bt_trace
*trace
= NULL
;
383 struct bt_stream_class
*old_stream_class
= NULL
;
384 struct bt_validation_output validation_output
= { 0 };
385 struct bt_field_type
*packet_header_type
= NULL
;
386 struct bt_field_type
*packet_context_type
= NULL
;
387 struct bt_field_type
*event_header_type
= NULL
;
388 struct bt_field_type
*stream_event_ctx_type
= NULL
;
389 struct bt_field_type
*event_context_type
= NULL
;
390 struct bt_field_type
*event_payload_type
= NULL
;
391 const enum bt_validation_flag validation_flags
=
392 BT_VALIDATION_FLAG_EVENT
;
393 struct bt_clock_class
*expected_clock_class
= NULL
;
395 if (!stream_class
|| !event_class
) {
396 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
397 "stream-class-addr=%p, event-class-addr=%p",
398 stream_class
, event_class
);
403 BT_LOGD("Adding event class to stream class: "
404 "stream-class-addr=%p, stream-class-name=\"%s\", "
405 "stream-class-id=%" PRId64
", event-class-addr=%p, "
406 "event-class-name=\"%s\", event-class-id=%" PRId64
,
407 stream_class
, bt_stream_class_get_name(stream_class
),
408 bt_stream_class_get_id(stream_class
),
410 bt_event_class_get_name(event_class
),
411 bt_event_class_get_id(event_class
));
413 trace
= bt_stream_class_get_trace(stream_class
);
414 if (trace
&& trace
->is_static
) {
415 BT_LOGW("Invalid parameter: stream class's trace is static: "
416 "trace-addr=%p, trace-name=\"%s\"",
417 trace
, bt_trace_get_name(trace
));
422 if (stream_class
->frozen
) {
424 * We only check that the event class to be added has a
425 * single class which matches the stream class's
426 * expected clock class if the stream class is frozen.
427 * If it's not, then this event class is added "as is"
428 * and the validation will be performed when calling
429 * either bt_trace_add_stream_class() or
430 * bt_event_create(). This is because the stream class's
431 * field types (packet context, event header, event
432 * context) could change before the next call to one of
433 * those two functions.
435 expected_clock_class
= bt_get(stream_class
->clock_class
);
438 * At this point, `expected_clock_class` can be NULL,
439 * and bt_event_class_validate_single_clock_class()
442 ret
= bt_event_class_validate_single_clock_class(
443 event_class
, &expected_clock_class
);
445 BT_LOGW("Event class contains a field type which is not "
446 "recursively mapped to its stream class's "
447 "expected clock class: "
448 "stream-class-addr=%p, "
449 "stream-class-id=%" PRId64
", "
450 "stream-class-name=\"%s\", "
451 "expected-clock-class-addr=%p, "
452 "expected-clock-class-name=\"%s\"",
454 bt_stream_class_get_id(stream_class
),
455 bt_stream_class_get_name(stream_class
),
456 expected_clock_class
,
457 expected_clock_class
?
458 bt_clock_class_get_name(expected_clock_class
) :
464 event_id
= g_new(int64_t, 1);
466 BT_LOGE_STR("Failed to allocate one int64_t.");
471 /* Check for duplicate event classes */
472 struct search_query query
= { .value
= event_class
, .found
= 0 };
473 g_ptr_array_foreach(stream_class
->event_classes
, event_class_exists
,
476 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
481 old_stream_class
= bt_event_class_get_stream_class(event_class
);
482 if (old_stream_class
) {
483 /* Event class is already associated to a stream class. */
484 BT_LOGW("Event class is already part of another stream class: "
485 "event-class-stream-class-addr=%p, "
486 "event-class-stream-class-name=\"%s\", "
487 "event-class-stream-class-id=%" PRId64
,
489 bt_stream_class_get_name(old_stream_class
),
490 bt_stream_class_get_id(old_stream_class
));
497 * If the stream class is associated with a trace, then
498 * both those objects are frozen. Also, this event class
499 * is about to be frozen.
501 * Therefore the event class must be validated here.
502 * The trace and stream class should be valid at this
505 BT_ASSERT(trace
->valid
);
506 BT_ASSERT(stream_class
->valid
);
508 bt_trace_get_packet_header_type(trace
);
509 packet_context_type
=
510 bt_stream_class_get_packet_context_type(
513 bt_stream_class_get_event_header_type(stream_class
);
514 stream_event_ctx_type
=
515 bt_stream_class_get_event_context_type(
518 bt_event_class_get_context_type(event_class
);
520 bt_event_class_get_payload_type(event_class
);
521 ret
= bt_validate_class_types(
522 trace
->environment
, packet_header_type
,
523 packet_context_type
, event_header_type
,
524 stream_event_ctx_type
, event_context_type
,
525 event_payload_type
, trace
->valid
,
526 stream_class
->valid
, event_class
->valid
,
527 &validation_output
, validation_flags
);
528 BT_PUT(packet_header_type
);
529 BT_PUT(packet_context_type
);
530 BT_PUT(event_header_type
);
531 BT_PUT(stream_event_ctx_type
);
532 BT_PUT(event_context_type
);
533 BT_PUT(event_payload_type
);
537 * This means something went wrong during the
538 * validation process, not that the objects are
541 BT_LOGE("Failed to validate event class: ret=%d", ret
);
545 if ((validation_output
.valid_flags
& validation_flags
) !=
547 /* Invalid event class */
548 BT_LOGW("Invalid trace, stream class, or event class: "
550 validation_output
.valid_flags
);
556 /* Only set an event ID if none was explicitly set before */
557 *event_id
= bt_event_class_get_id(event_class
);
559 BT_LOGV("Event class has no ID: automatically setting it: "
560 "id=%" PRId64
, stream_class
->next_event_id
);
562 if (bt_event_class_set_id(event_class
,
563 stream_class
->next_event_id
)) {
564 BT_LOGE("Cannot set event class's ID: id=%" PRId64
,
565 stream_class
->next_event_id
);
569 stream_class
->next_event_id
++;
570 *event_id
= stream_class
->next_event_id
;
573 bt_object_set_parent(event_class
, stream_class
);
577 * At this point we know that the function will be
578 * successful. Therefore we can replace the event
579 * class's field types with what's in the validation
580 * output structure and mark this event class as valid.
582 bt_validation_replace_types(NULL
, NULL
, event_class
,
583 &validation_output
, validation_flags
);
584 event_class
->valid
= 1;
587 * Put what was not moved in
588 * bt_validation_replace_types().
590 bt_validation_output_put_types(&validation_output
);
593 /* Add to the event classes of the stream class */
594 g_ptr_array_add(stream_class
->event_classes
, event_class
);
595 g_hash_table_insert(stream_class
->event_classes_ht
, event_id
,
599 /* Freeze the event class */
600 bt_event_class_freeze(event_class
);
603 * It is safe to set the stream class's unique clock class
604 * now if the stream class is frozen.
606 if (stream_class
->frozen
&& expected_clock_class
) {
607 BT_ASSERT(!stream_class
->clock_class
||
608 stream_class
->clock_class
== expected_clock_class
);
609 BT_MOVE(stream_class
->clock_class
, expected_clock_class
);
612 /* Notifiy listeners of the trace's schema modification. */
614 struct bt_visitor_object obj
= { .object
= event_class
,
615 .type
= BT_VISITOR_OBJECT_TYPE_EVENT_CLASS
};
617 (void) bt_trace_object_modification(&obj
, trace
);
620 BT_LOGD("Added event class to stream class: "
621 "stream-class-addr=%p, stream-class-name=\"%s\", "
622 "stream-class-id=%" PRId64
", event-class-addr=%p, "
623 "event-class-name=\"%s\", event-class-id=%" PRId64
,
624 stream_class
, bt_stream_class_get_name(stream_class
),
625 bt_stream_class_get_id(stream_class
),
627 bt_event_class_get_name(event_class
),
628 bt_event_class_get_id(event_class
));
632 BT_PUT(old_stream_class
);
633 bt_validation_output_put_types(&validation_output
);
634 bt_put(expected_clock_class
);
635 BT_ASSERT(!packet_header_type
);
636 BT_ASSERT(!packet_context_type
);
637 BT_ASSERT(!event_header_type
);
638 BT_ASSERT(!stream_event_ctx_type
);
639 BT_ASSERT(!event_context_type
);
640 BT_ASSERT(!event_payload_type
);
646 int64_t bt_stream_class_get_event_class_count(
647 struct bt_stream_class
*stream_class
)
652 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
657 ret
= (int64_t) stream_class
->event_classes
->len
;
662 struct bt_event_class
*bt_stream_class_get_event_class_by_index(
663 struct bt_stream_class
*stream_class
, uint64_t index
)
665 BT_ASSERT_PRE_NON_NULL(stream_class
, "Stream class");
666 BT_ASSERT_PRE(index
< stream_class
->event_classes
->len
,
667 "Index is out of bounds: index=%" PRIu64
", "
669 index
, stream_class
->event_classes
->len
);
670 return bt_get(g_ptr_array_index(stream_class
->event_classes
, index
));
673 struct bt_event_class
*bt_stream_class_get_event_class_by_id(
674 struct bt_stream_class
*stream_class
, uint64_t id
)
676 int64_t id_key
= (int64_t) id
;
678 BT_ASSERT_PRE_NON_NULL(stream_class
, "Stream class");
679 BT_ASSERT_PRE(id_key
>= 0,
680 "Invalid event class ID: %" PRIu64
, id
);
681 return bt_get(g_hash_table_lookup(stream_class
->event_classes_ht
,
685 struct bt_field_type
*bt_stream_class_get_packet_context_type(
686 struct bt_stream_class
*stream_class
)
688 BT_ASSERT_PRE_NON_NULL(stream_class
, "Stream class");
689 return bt_get(stream_class
->packet_context_type
);
692 int bt_stream_class_set_packet_context_type(
693 struct bt_stream_class
*stream_class
,
694 struct bt_field_type
*packet_context_type
)
699 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
704 if (stream_class
->frozen
) {
705 BT_LOGW("Invalid parameter: stream class is frozen: "
706 "addr=%p, name=\"%s\", id=%" PRId64
,
707 stream_class
, bt_stream_class_get_name(stream_class
),
708 bt_stream_class_get_id(stream_class
));
713 if (packet_context_type
&&
714 bt_field_type_get_type_id(packet_context_type
) !=
715 BT_FIELD_TYPE_ID_STRUCT
) {
716 /* A packet context must be a structure. */
717 BT_LOGW("Invalid parameter: stream class's packet context field type must be a structure: "
718 "addr=%p, name=\"%s\", id=%" PRId64
", "
719 "packet-context-ft-addr=%p, packet-context-ft-id=%s",
720 stream_class
, bt_stream_class_get_name(stream_class
),
721 bt_stream_class_get_id(stream_class
),
723 bt_field_type_id_string(
724 bt_field_type_get_type_id(packet_context_type
)));
729 bt_put(stream_class
->packet_context_type
);
730 bt_get(packet_context_type
);
731 stream_class
->packet_context_type
= packet_context_type
;
732 BT_LOGV("Set stream class's packet context field type: "
733 "addr=%p, name=\"%s\", id=%" PRId64
", "
734 "packet-context-ft-addr=%p",
735 stream_class
, bt_stream_class_get_name(stream_class
),
736 bt_stream_class_get_id(stream_class
),
737 packet_context_type
);
743 struct bt_field_type
*bt_stream_class_get_event_header_type(
744 struct bt_stream_class
*stream_class
)
746 struct bt_field_type
*ret
= NULL
;
748 BT_ASSERT_PRE_NON_NULL(stream_class
, "Stream class");
750 if (!stream_class
->event_header_type
) {
751 BT_LOGV("Stream class has no event header field type: "
752 "addr=%p, name=\"%s\", id=%" PRId64
,
753 stream_class
, bt_stream_class_get_name(stream_class
),
754 bt_stream_class_get_id(stream_class
));
758 ret
= bt_get(stream_class
->event_header_type
);
764 int bt_stream_class_set_event_header_type(
765 struct bt_stream_class
*stream_class
,
766 struct bt_field_type
*event_header_type
)
771 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
776 if (stream_class
->frozen
) {
777 BT_LOGW("Invalid parameter: stream class is frozen: "
778 "addr=%p, name=\"%s\", id=%" PRId64
,
779 stream_class
, bt_stream_class_get_name(stream_class
),
780 bt_stream_class_get_id(stream_class
));
785 if (event_header_type
&&
786 bt_field_type_get_type_id(event_header_type
) !=
787 BT_FIELD_TYPE_ID_STRUCT
) {
788 /* An event header must be a structure. */
789 BT_LOGW("Invalid parameter: stream class's event header field type must be a structure: "
790 "addr=%p, name=\"%s\", id=%" PRId64
", "
791 "event-header-ft-addr=%p, event-header-ft-id=%s",
792 stream_class
, bt_stream_class_get_name(stream_class
),
793 bt_stream_class_get_id(stream_class
),
795 bt_field_type_id_string(
796 bt_field_type_get_type_id(event_header_type
)));
801 bt_put(stream_class
->event_header_type
);
802 stream_class
->event_header_type
= bt_get(event_header_type
);
803 BT_LOGV("Set stream class's event header field type: "
804 "addr=%p, name=\"%s\", id=%" PRId64
", "
805 "event-header-ft-addr=%p",
806 stream_class
, bt_stream_class_get_name(stream_class
),
807 bt_stream_class_get_id(stream_class
),
813 struct bt_field_type
*bt_stream_class_get_event_context_type(
814 struct bt_stream_class
*stream_class
)
816 struct bt_field_type
*ret
= NULL
;
818 BT_ASSERT_PRE_NON_NULL(stream_class
, "Stream class");
820 if (!stream_class
->event_context_type
) {
824 ret
= bt_get(stream_class
->event_context_type
);
830 int bt_stream_class_set_event_context_type(
831 struct bt_stream_class
*stream_class
,
832 struct bt_field_type
*event_context_type
)
837 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
842 if (stream_class
->frozen
) {
843 BT_LOGW("Invalid parameter: stream class is frozen: "
844 "addr=%p, name=\"%s\", id=%" PRId64
,
845 stream_class
, bt_stream_class_get_name(stream_class
),
846 bt_stream_class_get_id(stream_class
));
851 if (event_context_type
&&
852 bt_field_type_get_type_id(event_context_type
) !=
853 BT_FIELD_TYPE_ID_STRUCT
) {
854 /* A packet context must be a structure. */
855 BT_LOGW("Invalid parameter: stream class's event context field type must be a structure: "
856 "addr=%p, name=\"%s\", id=%" PRId64
", "
857 "event-context-ft-addr=%p, event-context-ft-id=%s",
858 stream_class
, bt_stream_class_get_name(stream_class
),
859 bt_stream_class_get_id(stream_class
),
861 bt_field_type_id_string(
862 bt_field_type_get_type_id(event_context_type
)));
867 bt_put(stream_class
->event_context_type
);
868 stream_class
->event_context_type
= bt_get(event_context_type
);
869 BT_LOGV("Set stream class's event context field type: "
870 "addr=%p, name=\"%s\", id=%" PRId64
", "
871 "event-context-ft-addr=%p",
872 stream_class
, bt_stream_class_get_name(stream_class
),
873 bt_stream_class_get_id(stream_class
),
879 /* Pre-2.0 CTF writer backward compatibility */
880 void bt_ctf_stream_class_get(struct bt_stream_class
*stream_class
)
882 bt_get(stream_class
);
885 /* Pre-2.0 CTF writer backward compatibility */
886 void bt_ctf_stream_class_put(struct bt_stream_class
*stream_class
)
888 bt_put(stream_class
);
892 int64_t get_event_class_count(void *element
)
894 return bt_stream_class_get_event_class_count(
895 (struct bt_stream_class
*) element
);
899 void *get_event_class(void *element
, int i
)
901 return bt_stream_class_get_event_class_by_index(
902 (struct bt_stream_class
*) element
, i
);
906 int visit_event_class(void *object
, bt_visitor visitor
,void *data
)
908 struct bt_visitor_object obj
=
910 .type
= BT_VISITOR_OBJECT_TYPE_EVENT_CLASS
};
912 return visitor(&obj
, data
);
915 int bt_stream_class_visit(struct bt_stream_class
*stream_class
,
916 bt_visitor visitor
, void *data
)
919 struct bt_visitor_object obj
=
920 { .object
= stream_class
,
921 .type
= BT_VISITOR_OBJECT_TYPE_STREAM_CLASS
};
923 if (!stream_class
|| !visitor
) {
924 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
925 "stream-class-addr=%p, visitor=%p",
926 stream_class
, visitor
);
931 ret
= visitor_helper(&obj
, get_event_class_count
,
933 visit_event_class
, visitor
, data
);
934 BT_LOGV("visitor_helper() returned: ret=%d", ret
);
940 void bt_stream_class_freeze(struct bt_stream_class
*stream_class
)
942 if (!stream_class
|| stream_class
->frozen
) {
946 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64
,
947 stream_class
, bt_stream_class_get_name(stream_class
),
948 bt_stream_class_get_id(stream_class
));
949 stream_class
->frozen
= 1;
950 bt_field_type_freeze(stream_class
->event_header_type
);
951 bt_field_type_freeze(stream_class
->packet_context_type
);
952 bt_field_type_freeze(stream_class
->event_context_type
);
954 if (stream_class
->clock
) {
955 bt_clock_class_freeze(stream_class
->clock
->clock_class
);
960 int bt_stream_class_serialize(struct bt_stream_class
*stream_class
,
961 struct metadata_context
*context
)
965 struct bt_trace
*trace
;
966 struct bt_field_type
*packet_header_type
= NULL
;
968 BT_LOGD("Serializing stream class's metadata: "
969 "stream-class-addr=%p, stream-class-name=\"%s\", "
970 "stream-class-id=%" PRId64
", metadata-context-addr=%p",
971 stream_class
, bt_stream_class_get_name(stream_class
),
972 bt_stream_class_get_id(stream_class
), context
);
973 g_string_assign(context
->field_name
, "");
974 context
->current_indentation_level
= 1;
975 if (!stream_class
->id_set
) {
976 BT_LOGW_STR("Stream class's ID is not set.");
981 g_string_append(context
->string
, "stream {\n");
984 * The reference to the trace is only borrowed since the
985 * serialization of the stream class might have been triggered
986 * by the trace's destruction. In such a case, the trace's
987 * reference count would, unexepectedly, go through the sequence
988 * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
991 trace
= bt_stream_class_borrow_trace(stream_class
);
993 packet_header_type
= bt_trace_get_packet_header_type(trace
);
995 if (packet_header_type
) {
996 struct bt_field_type
*stream_id_type
;
999 bt_field_type_structure_get_field_type_by_name(
1000 packet_header_type
, "stream_id");
1001 if (stream_id_type
) {
1003 * Only set the stream's id if the trace's packet header
1004 * contains a stream_id field. This field is only
1005 * needed if the trace contains only one stream
1008 g_string_append_printf(context
->string
,
1009 "\tid = %" PRId64
";\n", stream_class
->id
);
1011 bt_put(stream_id_type
);
1013 if (stream_class
->event_header_type
) {
1014 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
1015 g_string_append(context
->string
, "\tevent.header := ");
1016 ret
= bt_field_type_serialize(stream_class
->event_header_type
,
1019 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
1023 g_string_append(context
->string
, ";");
1027 if (stream_class
->packet_context_type
) {
1028 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
1029 g_string_append(context
->string
, "\n\n\tpacket.context := ");
1030 ret
= bt_field_type_serialize(stream_class
->packet_context_type
,
1033 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
1037 g_string_append(context
->string
, ";");
1040 if (stream_class
->event_context_type
) {
1041 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
1042 g_string_append(context
->string
, "\n\n\tevent.context := ");
1043 ret
= bt_field_type_serialize(
1044 stream_class
->event_context_type
, context
);
1046 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
1050 g_string_append(context
->string
, ";");
1053 g_string_append(context
->string
, "\n};\n\n");
1055 for (i
= 0; i
< stream_class
->event_classes
->len
; i
++) {
1056 struct bt_event_class
*event_class
=
1057 stream_class
->event_classes
->pdata
[i
];
1059 ret
= bt_event_class_serialize(event_class
, context
);
1061 BT_LOGW("Cannot serialize event class's metadata: "
1062 "event-class-addr=%p, event-class-name=\"%s\", "
1063 "event-class-id=%" PRId64
,
1065 bt_event_class_get_name(event_class
),
1066 bt_event_class_get_id(event_class
));
1071 bt_put(packet_header_type
);
1072 context
->current_indentation_level
= 0;
1077 void bt_stream_class_destroy(struct bt_object
*obj
)
1079 struct bt_stream_class
*stream_class
;
1081 stream_class
= container_of(obj
, struct bt_stream_class
, base
);
1082 BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64
,
1083 stream_class
, bt_stream_class_get_name(stream_class
),
1084 bt_stream_class_get_id(stream_class
));
1085 bt_put(stream_class
->clock
);
1086 bt_put(stream_class
->clock_class
);
1088 if (stream_class
->event_classes_ht
) {
1089 g_hash_table_destroy(stream_class
->event_classes_ht
);
1091 if (stream_class
->event_classes
) {
1092 BT_LOGD_STR("Destroying event classes.");
1093 g_ptr_array_free(stream_class
->event_classes
, TRUE
);
1096 if (stream_class
->name
) {
1097 g_string_free(stream_class
->name
, TRUE
);
1100 BT_LOGD_STR("Putting event header field type.");
1101 bt_put(stream_class
->event_header_type
);
1102 BT_LOGD_STR("Putting packet context field type.");
1103 bt_put(stream_class
->packet_context_type
);
1104 BT_LOGD_STR("Putting event context field type.");
1105 bt_put(stream_class
->event_context_type
);
1106 g_free(stream_class
);
1110 int init_event_header(struct bt_stream_class
*stream_class
)
1113 struct bt_field_type
*event_header_type
=
1114 bt_field_type_structure_create();
1115 struct bt_field_type
*_uint32_t
=
1116 get_field_type(FIELD_TYPE_ALIAS_UINT32_T
);
1117 struct bt_field_type
*_uint64_t
=
1118 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
1120 if (!event_header_type
) {
1121 BT_LOGE_STR("Cannot create empty structure field type.");
1126 ret
= bt_field_type_structure_add_field(event_header_type
,
1129 BT_LOGE_STR("Cannot add `id` field to event header field type.");
1133 ret
= bt_field_type_structure_add_field(event_header_type
,
1134 _uint64_t
, "timestamp");
1136 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
1140 BT_MOVE(stream_class
->event_header_type
, event_header_type
);
1143 bt_put(event_header_type
);
1152 int init_packet_context(struct bt_stream_class
*stream_class
)
1155 struct bt_field_type
*packet_context_type
=
1156 bt_field_type_structure_create();
1157 struct bt_field_type
*_uint64_t
=
1158 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
1159 struct bt_field_type
*ts_begin_end_uint64_t
;
1161 if (!packet_context_type
) {
1162 BT_LOGE_STR("Cannot create empty structure field type.");
1167 ts_begin_end_uint64_t
= bt_field_type_copy(_uint64_t
);
1168 if (!ts_begin_end_uint64_t
) {
1169 BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
1175 * We create a stream packet context as proposed in the CTF
1178 ret
= bt_field_type_structure_add_field(packet_context_type
,
1179 ts_begin_end_uint64_t
, "timestamp_begin");
1181 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
1185 ret
= bt_field_type_structure_add_field(packet_context_type
,
1186 ts_begin_end_uint64_t
, "timestamp_end");
1188 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
1192 ret
= bt_field_type_structure_add_field(packet_context_type
,
1193 _uint64_t
, "content_size");
1195 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
1199 ret
= bt_field_type_structure_add_field(packet_context_type
,
1200 _uint64_t
, "packet_size");
1202 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
1206 ret
= bt_field_type_structure_add_field(packet_context_type
,
1207 _uint64_t
, "events_discarded");
1209 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
1213 BT_MOVE(stream_class
->packet_context_type
, packet_context_type
);
1216 bt_put(packet_context_type
);
1221 bt_put(ts_begin_end_uint64_t
);
1226 int try_map_clock_class(struct bt_stream_class
*stream_class
,
1227 struct bt_field_type
*parent_ft
, const char *field_name
)
1229 struct bt_clock_class
*mapped_clock_class
= NULL
;
1231 struct bt_field_type
*ft
=
1232 bt_field_type_structure_get_field_type_by_name(parent_ft
,
1235 BT_ASSERT(stream_class
->clock
);
1238 /* Field does not exist: not an error */
1242 BT_ASSERT(bt_field_type_is_integer(ft
));
1243 mapped_clock_class
=
1244 bt_field_type_integer_get_mapped_clock_class(ft
);
1245 if (!mapped_clock_class
) {
1246 struct bt_field_type
*ft_copy
;
1248 if (!stream_class
->clock
) {
1249 BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
1250 "stream-class-addr=%p, stream-class-name=\"%s\", "
1251 "stream-class-id=%" PRId64
", ft-addr=%p",
1252 stream_class
, bt_stream_class_get_name(stream_class
),
1253 bt_stream_class_get_id(stream_class
), ft
);
1258 ft_copy
= bt_field_type_copy(ft
);
1260 BT_LOGE("Failed to copy integer field type: ft-addr=%p",
1264 ret
= bt_field_type_integer_set_mapped_clock_class_no_check(
1265 ft_copy
, stream_class
->clock
->clock_class
);
1266 BT_ASSERT(ret
== 0);
1267 ret
= bt_field_type_structure_replace_field(parent_ft
,
1268 field_name
, ft_copy
);
1270 BT_LOGV("Automatically mapped field type to stream class's clock class: "
1271 "stream-class-addr=%p, stream-class-name=\"%s\", "
1272 "stream-class-id=%" PRId64
", ft-addr=%p, "
1274 stream_class
, bt_stream_class_get_name(stream_class
),
1275 bt_stream_class_get_id(stream_class
), ft
, ft_copy
);
1280 bt_put(mapped_clock_class
);
1285 int bt_stream_class_map_clock_class(
1286 struct bt_stream_class
*stream_class
,
1287 struct bt_field_type
*packet_context_type
,
1288 struct bt_field_type
*event_header_type
)
1292 BT_ASSERT(stream_class
);
1294 if (!stream_class
->clock
) {
1295 /* No clock class to map to */
1299 if (packet_context_type
) {
1300 if (try_map_clock_class(stream_class
, packet_context_type
,
1301 "timestamp_begin")) {
1302 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
1307 if (try_map_clock_class(stream_class
, packet_context_type
,
1309 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
1315 if (event_header_type
) {
1316 if (try_map_clock_class(stream_class
, event_header_type
,
1318 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
1329 int bt_stream_class_validate_single_clock_class(
1330 struct bt_stream_class
*stream_class
,
1331 struct bt_clock_class
**expected_clock_class
)
1336 BT_ASSERT(stream_class
);
1337 BT_ASSERT(expected_clock_class
);
1338 ret
= bt_validate_single_clock_class(stream_class
->packet_context_type
,
1339 expected_clock_class
);
1341 BT_LOGW("Stream class's packet context field type "
1342 "is not recursively mapped to the "
1343 "expected clock class: "
1344 "stream-class-addr=%p, "
1345 "stream-class-name=\"%s\", "
1346 "stream-class-id=%" PRId64
", "
1349 bt_stream_class_get_name(stream_class
),
1351 stream_class
->packet_context_type
);
1355 ret
= bt_validate_single_clock_class(stream_class
->event_header_type
,
1356 expected_clock_class
);
1358 BT_LOGW("Stream class's event header field type "
1359 "is not recursively mapped to the "
1360 "expected clock class: "
1361 "stream-class-addr=%p, "
1362 "stream-class-name=\"%s\", "
1363 "stream-class-id=%" PRId64
", "
1366 bt_stream_class_get_name(stream_class
),
1368 stream_class
->event_header_type
);
1372 ret
= bt_validate_single_clock_class(stream_class
->event_context_type
,
1373 expected_clock_class
);
1375 BT_LOGW("Stream class's event context field type "
1376 "is not recursively mapped to the "
1377 "expected clock class: "
1378 "stream-class-addr=%p, "
1379 "stream-class-name=\"%s\", "
1380 "stream-class-id=%" PRId64
", "
1383 bt_stream_class_get_name(stream_class
),
1385 stream_class
->event_context_type
);
1389 for (i
= 0; i
< stream_class
->event_classes
->len
; i
++) {
1390 struct bt_event_class
*event_class
=
1391 g_ptr_array_index(stream_class
->event_classes
, i
);
1393 BT_ASSERT(event_class
);
1394 ret
= bt_event_class_validate_single_clock_class(event_class
,
1395 expected_clock_class
);
1397 BT_LOGW("Stream class's event class contains a "
1398 "field type which is not recursively mapped to "
1399 "the expected clock class: "
1400 "stream-class-addr=%p, "
1401 "stream-class-name=\"%s\", "
1402 "stream-class-id=%" PRId64
,
1404 bt_stream_class_get_name(stream_class
),