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>
57 void bt_stream_class_destroy(struct bt_object
*obj
);
59 int init_event_header(struct bt_stream_class
*stream_class
);
61 int init_packet_context(struct bt_stream_class
*stream_class
);
63 struct bt_stream_class
*bt_stream_class_create(const char *name
)
65 struct bt_stream_class
*stream_class
;
68 BT_LOGD("Creating default stream class object: name=\"%s\"", name
);
69 stream_class
= bt_stream_class_create_empty(name
);
71 BT_LOGD_STR("Cannot create empty stream class.");
75 ret
= init_event_header(stream_class
);
77 BT_LOGE_STR("Cannot initialize stream class's event header field type.");
81 ret
= init_packet_context(stream_class
);
83 BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
87 BT_LOGD("Created default stream class object: addr=%p, name=\"%s\"",
96 struct bt_stream_class
*bt_stream_class_create_empty(const char *name
)
98 struct bt_stream_class
*stream_class
= NULL
;
100 BT_LOGD("Creating empty stream class object: name=\"%s\"", name
);
102 stream_class
= g_new0(struct bt_stream_class
, 1);
104 BT_LOGE_STR("Failed to allocate one stream class.");
108 stream_class
->name
= g_string_new(name
);
109 stream_class
->event_classes
= g_ptr_array_new_with_free_func(
110 (GDestroyNotify
) bt_object_release
);
111 if (!stream_class
->event_classes
) {
112 BT_LOGE_STR("Failed to allocate a GPtrArray.");
116 stream_class
->event_classes_ht
= g_hash_table_new_full(g_int64_hash
,
117 g_int64_equal
, g_free
, NULL
);
118 if (!stream_class
->event_classes_ht
) {
119 BT_LOGE_STR("Failed to allocate a GHashTable.");
123 bt_object_init(stream_class
, bt_stream_class_destroy
);
124 BT_LOGD("Created empty stream class object: addr=%p, name=\"%s\"",
129 BT_PUT(stream_class
);
133 struct bt_trace
*bt_stream_class_get_trace(
134 struct bt_stream_class
*stream_class
)
136 return stream_class
?
137 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 const char *name
= NULL
;
147 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
151 name
= stream_class
->name
->len
> 0 ? stream_class
->name
->str
: NULL
;
156 int bt_stream_class_set_name(struct bt_stream_class
*stream_class
,
162 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
167 if (stream_class
->frozen
) {
168 BT_LOGW("Invalid parameter: stream class is frozen: "
169 "addr=%p, name=\"%s\", id=%" PRId64
,
170 stream_class
, bt_stream_class_get_name(stream_class
),
171 bt_stream_class_get_id(stream_class
));
177 g_string_assign(stream_class
->name
, "");
179 if (strlen(name
) == 0) {
180 BT_LOGW("Invalid parameter: name is empty.");
185 g_string_assign(stream_class
->name
, name
);
188 BT_LOGV("Set stream class's name: "
189 "addr=%p, name=\"%s\", id=%" PRId64
,
190 stream_class
, bt_stream_class_get_name(stream_class
),
191 bt_stream_class_get_id(stream_class
));
196 struct bt_ctf_clock
*bt_stream_class_get_clock(
197 struct bt_stream_class
*stream_class
)
199 struct bt_ctf_clock
*clock
= NULL
;
202 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
206 if (!stream_class
->clock
) {
207 BT_LOGV("Stream class has no clock: "
208 "addr=%p, name=\"%s\", id=%" PRId64
,
209 stream_class
, bt_stream_class_get_name(stream_class
),
210 bt_stream_class_get_id(stream_class
));
214 clock
= bt_get(stream_class
->clock
);
219 int bt_stream_class_set_clock(struct bt_stream_class
*stream_class
,
220 struct bt_ctf_clock
*clock
)
223 struct bt_field_type
*timestamp_field
= NULL
;
225 if (!stream_class
|| !clock
) {
226 BT_LOGW("Invalid parameter: stream class or clock is NULL: "
227 "stream-class-addr=%p, clock-addr=%p",
228 stream_class
, clock
);
233 if (stream_class
->frozen
) {
234 BT_LOGW("Invalid parameter: stream class is frozen: "
235 "addr=%p, name=\"%s\", id=%" PRId64
,
236 stream_class
, bt_stream_class_get_name(stream_class
),
237 bt_stream_class_get_id(stream_class
));
242 /* Replace the current clock of this stream class. */
243 bt_put(stream_class
->clock
);
244 stream_class
->clock
= bt_get(clock
);
245 BT_LOGV("Set stream class's clock: "
246 "addr=%p, name=\"%s\", id=%" PRId64
", "
247 "clock-addr=%p, clock-name=\"%s\"",
248 stream_class
, bt_stream_class_get_name(stream_class
),
249 bt_stream_class_get_id(stream_class
),
251 bt_ctf_clock_get_name(stream_class
->clock
));
254 bt_put(timestamp_field
);
258 int64_t bt_stream_class_get_id(struct bt_stream_class
*stream_class
)
263 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
268 if (!stream_class
->id_set
) {
269 BT_LOGV("Stream class's ID is not set: addr=%p, name=\"%s\"",
271 bt_stream_class_get_name(stream_class
));
276 ret
= stream_class
->id
;
282 void _bt_stream_class_set_id(
283 struct bt_stream_class
*stream_class
, int64_t id
)
285 BT_ASSERT(stream_class
);
286 stream_class
->id
= id
;
287 stream_class
->id_set
= 1;
288 BT_LOGV("Set stream class's ID (internal): "
289 "addr=%p, name=\"%s\", id=%" PRId64
,
290 stream_class
, bt_stream_class_get_name(stream_class
),
291 bt_stream_class_get_id(stream_class
));
294 struct event_class_set_stream_class_id_data
{
295 int64_t stream_class_id
;
300 int bt_stream_class_set_id_no_check(
301 struct bt_stream_class
*stream_class
, int64_t id
)
303 _bt_stream_class_set_id(stream_class
, id
);
307 int bt_stream_class_set_id(struct bt_stream_class
*stream_class
,
311 int64_t id
= (int64_t) id_param
;
314 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
319 if (stream_class
->frozen
) {
320 BT_LOGW("Invalid parameter: stream class is frozen: "
321 "addr=%p, name=\"%s\", id=%" PRId64
,
322 stream_class
, bt_stream_class_get_name(stream_class
),
323 bt_stream_class_get_id(stream_class
));
329 BT_LOGW("Invalid parameter: invalid stream class's ID: "
330 "stream-class-addr=%p, stream-class-name=\"%s\", "
331 "stream-class-id=%" PRId64
", id=%" PRIu64
,
332 stream_class
, bt_stream_class_get_name(stream_class
),
333 bt_stream_class_get_id(stream_class
),
339 ret
= bt_stream_class_set_id_no_check(stream_class
, id
);
341 BT_LOGV("Set stream class's ID: "
342 "addr=%p, name=\"%s\", id=%" PRId64
,
343 stream_class
, bt_stream_class_get_name(stream_class
),
344 bt_stream_class_get_id(stream_class
));
351 void event_class_exists(gpointer element
, gpointer query
)
353 struct bt_event_class
*event_class_a
= element
;
354 struct search_query
*search_query
= query
;
355 struct bt_event_class
*event_class_b
= search_query
->value
;
358 if (search_query
->value
== element
) {
359 search_query
->found
= 1;
364 * Two event classes cannot share the same ID in a given
367 id_a
= bt_event_class_get_id(event_class_a
);
368 id_b
= bt_event_class_get_id(event_class_b
);
370 if (id_a
< 0 || id_b
< 0) {
371 /* at least one ID is not set: will be automatically set later */
376 BT_LOGW("Event class with this ID already exists in the stream class: "
377 "id=%" PRId64
", name=\"%s\"",
378 id_a
, bt_event_class_get_name(event_class_a
));
379 search_query
->found
= 1;
387 int bt_stream_class_add_event_class(
388 struct bt_stream_class
*stream_class
,
389 struct bt_event_class
*event_class
)
392 int64_t *event_id
= NULL
;
393 struct bt_trace
*trace
= NULL
;
394 struct bt_stream_class
*old_stream_class
= NULL
;
395 struct bt_validation_output validation_output
= { 0 };
396 struct bt_field_type
*packet_header_type
= NULL
;
397 struct bt_field_type
*packet_context_type
= NULL
;
398 struct bt_field_type
*event_header_type
= NULL
;
399 struct bt_field_type
*stream_event_ctx_type
= NULL
;
400 struct bt_field_type
*event_context_type
= NULL
;
401 struct bt_field_type
*event_payload_type
= NULL
;
402 const enum bt_validation_flag validation_flags
=
403 BT_VALIDATION_FLAG_EVENT
;
404 struct bt_clock_class
*expected_clock_class
= NULL
;
406 if (!stream_class
|| !event_class
) {
407 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
408 "stream-class-addr=%p, event-class-addr=%p",
409 stream_class
, event_class
);
414 BT_LOGD("Adding event class to stream class: "
415 "stream-class-addr=%p, stream-class-name=\"%s\", "
416 "stream-class-id=%" PRId64
", event-class-addr=%p, "
417 "event-class-name=\"%s\", event-class-id=%" PRId64
,
418 stream_class
, bt_stream_class_get_name(stream_class
),
419 bt_stream_class_get_id(stream_class
),
421 bt_event_class_get_name(event_class
),
422 bt_event_class_get_id(event_class
));
424 trace
= bt_stream_class_get_trace(stream_class
);
425 if (trace
&& trace
->is_static
) {
426 BT_LOGW("Invalid parameter: stream class's trace is static: "
427 "trace-addr=%p, trace-name=\"%s\"",
428 trace
, bt_trace_get_name(trace
));
433 if (stream_class
->frozen
) {
435 * We only check that the event class to be added has a
436 * single class which matches the stream class's
437 * expected clock class if the stream class is frozen.
438 * If it's not, then this event class is added "as is"
439 * and the validation will be performed when calling
440 * either bt_trace_add_stream_class() or
441 * bt_event_create(). This is because the stream class's
442 * field types (packet context, event header, event
443 * context) could change before the next call to one of
444 * those two functions.
446 expected_clock_class
= bt_get(stream_class
->clock_class
);
449 * At this point, `expected_clock_class` can be NULL,
450 * and bt_event_class_validate_single_clock_class()
453 ret
= bt_event_class_validate_single_clock_class(
454 event_class
, &expected_clock_class
);
456 BT_LOGW("Event class contains a field type which is not "
457 "recursively mapped to its stream class's "
458 "expected clock class: "
459 "stream-class-addr=%p, "
460 "stream-class-id=%" PRId64
", "
461 "stream-class-name=\"%s\", "
462 "expected-clock-class-addr=%p, "
463 "expected-clock-class-name=\"%s\"",
465 bt_stream_class_get_id(stream_class
),
466 bt_stream_class_get_name(stream_class
),
467 expected_clock_class
,
468 expected_clock_class
?
469 bt_clock_class_get_name(expected_clock_class
) :
475 event_id
= g_new(int64_t, 1);
477 BT_LOGE_STR("Failed to allocate one int64_t.");
482 /* Check for duplicate event classes */
483 struct search_query query
= { .value
= event_class
, .found
= 0 };
484 g_ptr_array_foreach(stream_class
->event_classes
, event_class_exists
,
487 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
492 old_stream_class
= bt_event_class_get_stream_class(event_class
);
493 if (old_stream_class
) {
494 /* Event class is already associated to a stream class. */
495 BT_LOGW("Event class is already part of another stream class: "
496 "event-class-stream-class-addr=%p, "
497 "event-class-stream-class-name=\"%s\", "
498 "event-class-stream-class-id=%" PRId64
,
500 bt_stream_class_get_name(old_stream_class
),
501 bt_stream_class_get_id(old_stream_class
));
508 * If the stream class is associated with a trace, then
509 * both those objects are frozen. Also, this event class
510 * is about to be frozen.
512 * Therefore the event class must be validated here.
513 * The trace and stream class should be valid at this
516 BT_ASSERT(trace
->valid
);
517 BT_ASSERT(stream_class
->valid
);
519 bt_trace_get_packet_header_type(trace
);
520 packet_context_type
=
521 bt_stream_class_get_packet_context_type(
524 bt_stream_class_get_event_header_type(stream_class
);
525 stream_event_ctx_type
=
526 bt_stream_class_get_event_context_type(
529 bt_event_class_get_context_type(event_class
);
531 bt_event_class_get_payload_type(event_class
);
532 ret
= bt_validate_class_types(
533 trace
->environment
, packet_header_type
,
534 packet_context_type
, event_header_type
,
535 stream_event_ctx_type
, event_context_type
,
536 event_payload_type
, trace
->valid
,
537 stream_class
->valid
, event_class
->valid
,
538 &validation_output
, validation_flags
);
539 BT_PUT(packet_header_type
);
540 BT_PUT(packet_context_type
);
541 BT_PUT(event_header_type
);
542 BT_PUT(stream_event_ctx_type
);
543 BT_PUT(event_context_type
);
544 BT_PUT(event_payload_type
);
548 * This means something went wrong during the
549 * validation process, not that the objects are
552 BT_LOGE("Failed to validate event class: ret=%d", ret
);
556 if ((validation_output
.valid_flags
& validation_flags
) !=
558 /* Invalid event class */
559 BT_LOGW("Invalid trace, stream class, or event class: "
561 validation_output
.valid_flags
);
567 /* Only set an event ID if none was explicitly set before */
568 *event_id
= bt_event_class_get_id(event_class
);
570 BT_LOGV("Event class has no ID: automatically setting it: "
571 "id=%" PRId64
, stream_class
->next_event_id
);
573 if (bt_event_class_set_id(event_class
,
574 stream_class
->next_event_id
)) {
575 BT_LOGE("Cannot set event class's ID: id=%" PRId64
,
576 stream_class
->next_event_id
);
580 stream_class
->next_event_id
++;
581 *event_id
= stream_class
->next_event_id
;
584 bt_object_set_parent(event_class
, stream_class
);
588 * At this point we know that the function will be
589 * successful. Therefore we can replace the event
590 * class's field types with what's in the validation
591 * output structure and mark this event class as valid.
593 bt_validation_replace_types(NULL
, NULL
, event_class
,
594 &validation_output
, validation_flags
);
595 event_class
->valid
= 1;
598 * Put what was not moved in
599 * bt_validation_replace_types().
601 bt_validation_output_put_types(&validation_output
);
604 /* Add to the event classes of the stream class */
605 g_ptr_array_add(stream_class
->event_classes
, event_class
);
606 g_hash_table_insert(stream_class
->event_classes_ht
, event_id
,
610 /* Freeze the event class */
611 bt_event_class_freeze(event_class
);
614 * It is safe to set the stream class's unique clock class
615 * now if the stream class is frozen.
617 if (stream_class
->frozen
&& expected_clock_class
) {
618 BT_ASSERT(!stream_class
->clock_class
||
619 stream_class
->clock_class
== expected_clock_class
);
620 BT_MOVE(stream_class
->clock_class
, expected_clock_class
);
623 /* Notifiy listeners of the trace's schema modification. */
625 struct bt_visitor_object obj
= { .object
= event_class
,
626 .type
= BT_VISITOR_OBJECT_TYPE_EVENT_CLASS
};
628 (void) bt_trace_object_modification(&obj
, trace
);
631 BT_LOGD("Added event class to stream class: "
632 "stream-class-addr=%p, stream-class-name=\"%s\", "
633 "stream-class-id=%" PRId64
", event-class-addr=%p, "
634 "event-class-name=\"%s\", event-class-id=%" PRId64
,
635 stream_class
, bt_stream_class_get_name(stream_class
),
636 bt_stream_class_get_id(stream_class
),
638 bt_event_class_get_name(event_class
),
639 bt_event_class_get_id(event_class
));
643 BT_PUT(old_stream_class
);
644 bt_validation_output_put_types(&validation_output
);
645 bt_put(expected_clock_class
);
646 BT_ASSERT(!packet_header_type
);
647 BT_ASSERT(!packet_context_type
);
648 BT_ASSERT(!event_header_type
);
649 BT_ASSERT(!stream_event_ctx_type
);
650 BT_ASSERT(!event_context_type
);
651 BT_ASSERT(!event_payload_type
);
657 int64_t bt_stream_class_get_event_class_count(
658 struct bt_stream_class
*stream_class
)
663 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
668 ret
= (int64_t) stream_class
->event_classes
->len
;
673 struct bt_event_class
*bt_stream_class_get_event_class_by_index(
674 struct bt_stream_class
*stream_class
, uint64_t index
)
676 struct bt_event_class
*event_class
= NULL
;
679 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
683 if (index
>= stream_class
->event_classes
->len
) {
684 BT_LOGW("Invalid parameter: index is out of bounds: "
685 "addr=%p, name=\"%s\", id=%" PRId64
", "
686 "index=%" PRIu64
", count=%u",
687 stream_class
, bt_stream_class_get_name(stream_class
),
688 bt_stream_class_get_id(stream_class
),
689 index
, stream_class
->event_classes
->len
);
693 event_class
= g_ptr_array_index(stream_class
->event_classes
, index
);
699 struct bt_event_class
*bt_stream_class_get_event_class_by_id(
700 struct bt_stream_class
*stream_class
, uint64_t id
)
702 int64_t id_key
= (int64_t) id
;
703 struct bt_event_class
*event_class
= NULL
;
706 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
711 BT_LOGW("Invalid parameter: invalid event class's ID: "
712 "stream-class-addr=%p, stream-class-name=\"%s\", "
713 "stream-class-id=%" PRId64
", event-class-id=%" PRIu64
,
715 bt_stream_class_get_name(stream_class
),
716 bt_stream_class_get_id(stream_class
), id
);
720 event_class
= g_hash_table_lookup(stream_class
->event_classes_ht
,
727 struct bt_field_type
*bt_stream_class_get_packet_context_type(
728 struct bt_stream_class
*stream_class
)
730 struct bt_field_type
*ret
= NULL
;
733 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
737 bt_get(stream_class
->packet_context_type
);
738 ret
= stream_class
->packet_context_type
;
743 int bt_stream_class_set_packet_context_type(
744 struct bt_stream_class
*stream_class
,
745 struct bt_field_type
*packet_context_type
)
750 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
755 if (stream_class
->frozen
) {
756 BT_LOGW("Invalid parameter: stream class is frozen: "
757 "addr=%p, name=\"%s\", id=%" PRId64
,
758 stream_class
, bt_stream_class_get_name(stream_class
),
759 bt_stream_class_get_id(stream_class
));
764 if (packet_context_type
&&
765 bt_field_type_get_type_id(packet_context_type
) !=
766 BT_FIELD_TYPE_ID_STRUCT
) {
767 /* A packet context must be a structure. */
768 BT_LOGW("Invalid parameter: stream class's packet context field type must be a structure: "
769 "addr=%p, name=\"%s\", id=%" PRId64
", "
770 "packet-context-ft-addr=%p, packet-context-ft-id=%s",
771 stream_class
, bt_stream_class_get_name(stream_class
),
772 bt_stream_class_get_id(stream_class
),
774 bt_field_type_id_string(
775 bt_field_type_get_type_id(packet_context_type
)));
780 bt_put(stream_class
->packet_context_type
);
781 bt_get(packet_context_type
);
782 stream_class
->packet_context_type
= packet_context_type
;
783 BT_LOGV("Set stream class's packet context field type: "
784 "addr=%p, name=\"%s\", id=%" PRId64
", "
785 "packet-context-ft-addr=%p",
786 stream_class
, bt_stream_class_get_name(stream_class
),
787 bt_stream_class_get_id(stream_class
),
788 packet_context_type
);
794 struct bt_field_type
*bt_stream_class_get_event_header_type(
795 struct bt_stream_class
*stream_class
)
797 struct bt_field_type
*ret
= NULL
;
800 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
804 if (!stream_class
->event_header_type
) {
805 BT_LOGV("Stream class has no event header field type: "
806 "addr=%p, name=\"%s\", id=%" PRId64
,
807 stream_class
, bt_stream_class_get_name(stream_class
),
808 bt_stream_class_get_id(stream_class
));
812 bt_get(stream_class
->event_header_type
);
813 ret
= stream_class
->event_header_type
;
818 int bt_stream_class_set_event_header_type(
819 struct bt_stream_class
*stream_class
,
820 struct bt_field_type
*event_header_type
)
825 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
830 if (stream_class
->frozen
) {
831 BT_LOGW("Invalid parameter: stream class is frozen: "
832 "addr=%p, name=\"%s\", id=%" PRId64
,
833 stream_class
, bt_stream_class_get_name(stream_class
),
834 bt_stream_class_get_id(stream_class
));
839 if (event_header_type
&&
840 bt_field_type_get_type_id(event_header_type
) !=
841 BT_FIELD_TYPE_ID_STRUCT
) {
842 /* An event header must be a structure. */
843 BT_LOGW("Invalid parameter: stream class's event header field type must be a structure: "
844 "addr=%p, name=\"%s\", id=%" PRId64
", "
845 "event-header-ft-addr=%p, event-header-ft-id=%s",
846 stream_class
, bt_stream_class_get_name(stream_class
),
847 bt_stream_class_get_id(stream_class
),
849 bt_field_type_id_string(
850 bt_field_type_get_type_id(event_header_type
)));
855 bt_put(stream_class
->event_header_type
);
856 stream_class
->event_header_type
= bt_get(event_header_type
);
857 BT_LOGV("Set stream class's event header field type: "
858 "addr=%p, name=\"%s\", id=%" PRId64
", "
859 "event-header-ft-addr=%p",
860 stream_class
, bt_stream_class_get_name(stream_class
),
861 bt_stream_class_get_id(stream_class
),
867 struct bt_field_type
*bt_stream_class_get_event_context_type(
868 struct bt_stream_class
*stream_class
)
870 struct bt_field_type
*ret
= NULL
;
873 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
877 if (!stream_class
->event_context_type
) {
881 bt_get(stream_class
->event_context_type
);
882 ret
= stream_class
->event_context_type
;
887 int bt_stream_class_set_event_context_type(
888 struct bt_stream_class
*stream_class
,
889 struct bt_field_type
*event_context_type
)
894 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
899 if (stream_class
->frozen
) {
900 BT_LOGW("Invalid parameter: stream class is frozen: "
901 "addr=%p, name=\"%s\", id=%" PRId64
,
902 stream_class
, bt_stream_class_get_name(stream_class
),
903 bt_stream_class_get_id(stream_class
));
908 if (event_context_type
&&
909 bt_field_type_get_type_id(event_context_type
) !=
910 BT_FIELD_TYPE_ID_STRUCT
) {
911 /* A packet context must be a structure. */
912 BT_LOGW("Invalid parameter: stream class's event context field type must be a structure: "
913 "addr=%p, name=\"%s\", id=%" PRId64
", "
914 "event-context-ft-addr=%p, event-context-ft-id=%s",
915 stream_class
, bt_stream_class_get_name(stream_class
),
916 bt_stream_class_get_id(stream_class
),
918 bt_field_type_id_string(
919 bt_field_type_get_type_id(event_context_type
)));
924 bt_put(stream_class
->event_context_type
);
925 stream_class
->event_context_type
= bt_get(event_context_type
);
926 BT_LOGV("Set stream class's event context field type: "
927 "addr=%p, name=\"%s\", id=%" PRId64
", "
928 "event-context-ft-addr=%p",
929 stream_class
, bt_stream_class_get_name(stream_class
),
930 bt_stream_class_get_id(stream_class
),
936 /* Pre-2.0 CTF writer backward compatibility */
937 void bt_ctf_stream_class_get(struct bt_stream_class
*stream_class
)
939 bt_get(stream_class
);
942 /* Pre-2.0 CTF writer backward compatibility */
943 void bt_ctf_stream_class_put(struct bt_stream_class
*stream_class
)
945 bt_put(stream_class
);
949 int64_t get_event_class_count(void *element
)
951 return bt_stream_class_get_event_class_count(
952 (struct bt_stream_class
*) element
);
956 void *get_event_class(void *element
, int i
)
958 return bt_stream_class_get_event_class_by_index(
959 (struct bt_stream_class
*) element
, i
);
963 int visit_event_class(void *object
, bt_visitor visitor
,void *data
)
965 struct bt_visitor_object obj
=
967 .type
= BT_VISITOR_OBJECT_TYPE_EVENT_CLASS
};
969 return visitor(&obj
, data
);
972 int bt_stream_class_visit(struct bt_stream_class
*stream_class
,
973 bt_visitor visitor
, void *data
)
976 struct bt_visitor_object obj
=
977 { .object
= stream_class
,
978 .type
= BT_VISITOR_OBJECT_TYPE_STREAM_CLASS
};
980 if (!stream_class
|| !visitor
) {
981 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
982 "stream-class-addr=%p, visitor=%p",
983 stream_class
, visitor
);
988 ret
= visitor_helper(&obj
, get_event_class_count
,
990 visit_event_class
, visitor
, data
);
991 BT_LOGV("visitor_helper() returned: ret=%d", ret
);
997 void bt_stream_class_freeze(struct bt_stream_class
*stream_class
)
999 if (!stream_class
|| stream_class
->frozen
) {
1003 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64
,
1004 stream_class
, bt_stream_class_get_name(stream_class
),
1005 bt_stream_class_get_id(stream_class
));
1006 stream_class
->frozen
= 1;
1007 bt_field_type_freeze(stream_class
->event_header_type
);
1008 bt_field_type_freeze(stream_class
->packet_context_type
);
1009 bt_field_type_freeze(stream_class
->event_context_type
);
1011 if (stream_class
->clock
) {
1012 bt_clock_class_freeze(stream_class
->clock
->clock_class
);
1017 int bt_stream_class_serialize(struct bt_stream_class
*stream_class
,
1018 struct metadata_context
*context
)
1022 struct bt_trace
*trace
;
1023 struct bt_field_type
*packet_header_type
= NULL
;
1025 BT_LOGD("Serializing stream class's metadata: "
1026 "stream-class-addr=%p, stream-class-name=\"%s\", "
1027 "stream-class-id=%" PRId64
", metadata-context-addr=%p",
1028 stream_class
, bt_stream_class_get_name(stream_class
),
1029 bt_stream_class_get_id(stream_class
), context
);
1030 g_string_assign(context
->field_name
, "");
1031 context
->current_indentation_level
= 1;
1032 if (!stream_class
->id_set
) {
1033 BT_LOGW_STR("Stream class's ID is not set.");
1038 g_string_append(context
->string
, "stream {\n");
1041 * The reference to the trace is only borrowed since the
1042 * serialization of the stream class might have been triggered
1043 * by the trace's destruction. In such a case, the trace's
1044 * reference count would, unexepectedly, go through the sequence
1045 * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
1046 * and serialization.
1048 trace
= bt_stream_class_borrow_trace(stream_class
);
1050 packet_header_type
= bt_trace_get_packet_header_type(trace
);
1052 if (packet_header_type
) {
1053 struct bt_field_type
*stream_id_type
;
1056 bt_field_type_structure_get_field_type_by_name(
1057 packet_header_type
, "stream_id");
1058 if (stream_id_type
) {
1060 * Only set the stream's id if the trace's packet header
1061 * contains a stream_id field. This field is only
1062 * needed if the trace contains only one stream
1065 g_string_append_printf(context
->string
,
1066 "\tid = %" PRId64
";\n", stream_class
->id
);
1068 bt_put(stream_id_type
);
1070 if (stream_class
->event_header_type
) {
1071 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
1072 g_string_append(context
->string
, "\tevent.header := ");
1073 ret
= bt_field_type_serialize(stream_class
->event_header_type
,
1076 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
1080 g_string_append(context
->string
, ";");
1084 if (stream_class
->packet_context_type
) {
1085 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
1086 g_string_append(context
->string
, "\n\n\tpacket.context := ");
1087 ret
= bt_field_type_serialize(stream_class
->packet_context_type
,
1090 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
1094 g_string_append(context
->string
, ";");
1097 if (stream_class
->event_context_type
) {
1098 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
1099 g_string_append(context
->string
, "\n\n\tevent.context := ");
1100 ret
= bt_field_type_serialize(
1101 stream_class
->event_context_type
, context
);
1103 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
1107 g_string_append(context
->string
, ";");
1110 g_string_append(context
->string
, "\n};\n\n");
1112 for (i
= 0; i
< stream_class
->event_classes
->len
; i
++) {
1113 struct bt_event_class
*event_class
=
1114 stream_class
->event_classes
->pdata
[i
];
1116 ret
= bt_event_class_serialize(event_class
, context
);
1118 BT_LOGW("Cannot serialize event class's metadata: "
1119 "event-class-addr=%p, event-class-name=\"%s\", "
1120 "event-class-id=%" PRId64
,
1122 bt_event_class_get_name(event_class
),
1123 bt_event_class_get_id(event_class
));
1128 bt_put(packet_header_type
);
1129 context
->current_indentation_level
= 0;
1134 void bt_stream_class_destroy(struct bt_object
*obj
)
1136 struct bt_stream_class
*stream_class
;
1138 stream_class
= container_of(obj
, struct bt_stream_class
, base
);
1139 BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64
,
1140 stream_class
, bt_stream_class_get_name(stream_class
),
1141 bt_stream_class_get_id(stream_class
));
1142 bt_put(stream_class
->clock
);
1143 bt_put(stream_class
->clock_class
);
1145 if (stream_class
->event_classes_ht
) {
1146 g_hash_table_destroy(stream_class
->event_classes_ht
);
1148 if (stream_class
->event_classes
) {
1149 BT_LOGD_STR("Destroying event classes.");
1150 g_ptr_array_free(stream_class
->event_classes
, TRUE
);
1153 if (stream_class
->name
) {
1154 g_string_free(stream_class
->name
, TRUE
);
1157 BT_LOGD_STR("Putting event header field type.");
1158 bt_put(stream_class
->event_header_type
);
1159 BT_LOGD_STR("Putting packet context field type.");
1160 bt_put(stream_class
->packet_context_type
);
1161 BT_LOGD_STR("Putting event context field type.");
1162 bt_put(stream_class
->event_context_type
);
1163 g_free(stream_class
);
1167 int init_event_header(struct bt_stream_class
*stream_class
)
1170 struct bt_field_type
*event_header_type
=
1171 bt_field_type_structure_create();
1172 struct bt_field_type
*_uint32_t
=
1173 get_field_type(FIELD_TYPE_ALIAS_UINT32_T
);
1174 struct bt_field_type
*_uint64_t
=
1175 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
1177 if (!event_header_type
) {
1178 BT_LOGE_STR("Cannot create empty structure field type.");
1183 ret
= bt_field_type_structure_add_field(event_header_type
,
1186 BT_LOGE_STR("Cannot add `id` field to event header field type.");
1190 ret
= bt_field_type_structure_add_field(event_header_type
,
1191 _uint64_t
, "timestamp");
1193 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
1197 BT_MOVE(stream_class
->event_header_type
, event_header_type
);
1200 bt_put(event_header_type
);
1209 int init_packet_context(struct bt_stream_class
*stream_class
)
1212 struct bt_field_type
*packet_context_type
=
1213 bt_field_type_structure_create();
1214 struct bt_field_type
*_uint64_t
=
1215 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
1216 struct bt_field_type
*ts_begin_end_uint64_t
;
1218 if (!packet_context_type
) {
1219 BT_LOGE_STR("Cannot create empty structure field type.");
1224 ts_begin_end_uint64_t
= bt_field_type_copy(_uint64_t
);
1225 if (!ts_begin_end_uint64_t
) {
1226 BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
1232 * We create a stream packet context as proposed in the CTF
1235 ret
= bt_field_type_structure_add_field(packet_context_type
,
1236 ts_begin_end_uint64_t
, "timestamp_begin");
1238 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
1242 ret
= bt_field_type_structure_add_field(packet_context_type
,
1243 ts_begin_end_uint64_t
, "timestamp_end");
1245 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
1249 ret
= bt_field_type_structure_add_field(packet_context_type
,
1250 _uint64_t
, "content_size");
1252 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
1256 ret
= bt_field_type_structure_add_field(packet_context_type
,
1257 _uint64_t
, "packet_size");
1259 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
1263 ret
= bt_field_type_structure_add_field(packet_context_type
,
1264 _uint64_t
, "events_discarded");
1266 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
1270 BT_MOVE(stream_class
->packet_context_type
, packet_context_type
);
1273 bt_put(packet_context_type
);
1278 bt_put(ts_begin_end_uint64_t
);
1283 int try_map_clock_class(struct bt_stream_class
*stream_class
,
1284 struct bt_field_type
*parent_ft
, const char *field_name
)
1286 struct bt_clock_class
*mapped_clock_class
= NULL
;
1288 struct bt_field_type
*ft
=
1289 bt_field_type_structure_get_field_type_by_name(parent_ft
,
1292 BT_ASSERT(stream_class
->clock
);
1295 /* Field does not exist: not an error */
1299 BT_ASSERT(bt_field_type_is_integer(ft
));
1300 mapped_clock_class
=
1301 bt_field_type_integer_get_mapped_clock_class(ft
);
1302 if (!mapped_clock_class
) {
1303 struct bt_field_type
*ft_copy
;
1305 if (!stream_class
->clock
) {
1306 BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
1307 "stream-class-addr=%p, stream-class-name=\"%s\", "
1308 "stream-class-id=%" PRId64
", ft-addr=%p",
1309 stream_class
, bt_stream_class_get_name(stream_class
),
1310 bt_stream_class_get_id(stream_class
), ft
);
1315 ft_copy
= bt_field_type_copy(ft
);
1317 BT_LOGE("Failed to copy integer field type: ft-addr=%p",
1321 ret
= bt_field_type_integer_set_mapped_clock_class_no_check(
1322 ft_copy
, stream_class
->clock
->clock_class
);
1323 BT_ASSERT(ret
== 0);
1324 ret
= bt_field_type_structure_replace_field(parent_ft
,
1325 field_name
, ft_copy
);
1327 BT_LOGV("Automatically mapped field type to stream class's clock class: "
1328 "stream-class-addr=%p, stream-class-name=\"%s\", "
1329 "stream-class-id=%" PRId64
", ft-addr=%p, "
1331 stream_class
, bt_stream_class_get_name(stream_class
),
1332 bt_stream_class_get_id(stream_class
), ft
, ft_copy
);
1337 bt_put(mapped_clock_class
);
1342 int bt_stream_class_map_clock_class(
1343 struct bt_stream_class
*stream_class
,
1344 struct bt_field_type
*packet_context_type
,
1345 struct bt_field_type
*event_header_type
)
1349 BT_ASSERT(stream_class
);
1351 if (!stream_class
->clock
) {
1352 /* No clock class to map to */
1356 if (packet_context_type
) {
1357 if (try_map_clock_class(stream_class
, packet_context_type
,
1358 "timestamp_begin")) {
1359 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
1364 if (try_map_clock_class(stream_class
, packet_context_type
,
1366 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
1372 if (event_header_type
) {
1373 if (try_map_clock_class(stream_class
, event_header_type
,
1375 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
1386 int bt_stream_class_validate_single_clock_class(
1387 struct bt_stream_class
*stream_class
,
1388 struct bt_clock_class
**expected_clock_class
)
1393 BT_ASSERT(stream_class
);
1394 BT_ASSERT(expected_clock_class
);
1395 ret
= bt_validate_single_clock_class(stream_class
->packet_context_type
,
1396 expected_clock_class
);
1398 BT_LOGW("Stream class's packet context field type "
1399 "is not recursively mapped to the "
1400 "expected clock class: "
1401 "stream-class-addr=%p, "
1402 "stream-class-name=\"%s\", "
1403 "stream-class-id=%" PRId64
", "
1406 bt_stream_class_get_name(stream_class
),
1408 stream_class
->packet_context_type
);
1412 ret
= bt_validate_single_clock_class(stream_class
->event_header_type
,
1413 expected_clock_class
);
1415 BT_LOGW("Stream class's event header field type "
1416 "is not recursively mapped to the "
1417 "expected clock class: "
1418 "stream-class-addr=%p, "
1419 "stream-class-name=\"%s\", "
1420 "stream-class-id=%" PRId64
", "
1423 bt_stream_class_get_name(stream_class
),
1425 stream_class
->event_header_type
);
1429 ret
= bt_validate_single_clock_class(stream_class
->event_context_type
,
1430 expected_clock_class
);
1432 BT_LOGW("Stream class's event context field type "
1433 "is not recursively mapped to the "
1434 "expected clock class: "
1435 "stream-class-addr=%p, "
1436 "stream-class-name=\"%s\", "
1437 "stream-class-id=%" PRId64
", "
1440 bt_stream_class_get_name(stream_class
),
1442 stream_class
->event_context_type
);
1446 for (i
= 0; i
< stream_class
->event_classes
->len
; i
++) {
1447 struct bt_event_class
*event_class
=
1448 g_ptr_array_index(stream_class
->event_classes
, i
);
1450 BT_ASSERT(event_class
);
1451 ret
= bt_event_class_validate_single_clock_class(event_class
,
1452 expected_clock_class
);
1454 BT_LOGW("Stream class's event class contains a "
1455 "field type which is not recursively mapped to "
1456 "the expected clock class: "
1457 "stream-class-addr=%p, "
1458 "stream-class-name=\"%s\", "
1459 "stream-class-id=%" PRId64
,
1461 bt_stream_class_get_name(stream_class
),