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/ref.h>
47 #include <babeltrace/compiler-internal.h>
48 #include <babeltrace/align-internal.h>
49 #include <babeltrace/endian-internal.h>
55 void bt_ctf_stream_class_destroy(struct bt_object
*obj
);
57 int init_event_header(struct bt_ctf_stream_class
*stream_class
);
59 int init_packet_context(struct bt_ctf_stream_class
*stream_class
);
61 struct bt_ctf_stream_class
*bt_ctf_stream_class_create(const char *name
)
63 struct bt_ctf_stream_class
*stream_class
;
66 BT_LOGD("Creating default stream class object: name=\"%s\"", name
);
67 stream_class
= bt_ctf_stream_class_create_empty(name
);
69 BT_LOGD_STR("Cannot create empty stream class.");
73 ret
= init_event_header(stream_class
);
75 BT_LOGE_STR("Cannot initialize stream class's event header field type.");
79 ret
= init_packet_context(stream_class
);
81 BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
85 BT_LOGD("Created default stream class object: addr=%p, name=\"%s\"",
94 struct bt_ctf_stream_class
*bt_ctf_stream_class_create_empty(const char *name
)
96 struct bt_ctf_stream_class
*stream_class
= NULL
;
98 BT_LOGD("Creating empty stream class object: name=\"%s\"", name
);
100 if (name
&& bt_ctf_validate_identifier(name
)) {
101 BT_LOGW("Invalid parameter: stream class's name is not a valid CTF identifier: "
102 "name=\"%s\"", name
);
106 stream_class
= g_new0(struct bt_ctf_stream_class
, 1);
108 BT_LOGE_STR("Failed to allocate one stream class.");
112 stream_class
->name
= g_string_new(name
);
113 stream_class
->event_classes
= g_ptr_array_new_with_free_func(
114 (GDestroyNotify
) bt_object_release
);
115 if (!stream_class
->event_classes
) {
116 BT_LOGE_STR("Failed to allocate a GPtrArray.");
120 stream_class
->event_classes_ht
= g_hash_table_new_full(g_int64_hash
,
121 g_int64_equal
, g_free
, NULL
);
122 if (!stream_class
->event_classes_ht
) {
123 BT_LOGE_STR("Failed to allocate a GHashTable.");
127 bt_object_init(stream_class
, bt_ctf_stream_class_destroy
);
128 BT_LOGD("Created empty stream class object: addr=%p, name=\"%s\"",
133 BT_PUT(stream_class
);
137 struct bt_ctf_trace
*bt_ctf_stream_class_get_trace(
138 struct bt_ctf_stream_class
*stream_class
)
140 return stream_class
?
141 bt_get(bt_ctf_stream_class_borrow_trace(stream_class
)) :
145 const char *bt_ctf_stream_class_get_name(
146 struct bt_ctf_stream_class
*stream_class
)
148 const char *name
= NULL
;
151 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
155 name
= stream_class
->name
->str
;
160 int bt_ctf_stream_class_set_name(struct bt_ctf_stream_class
*stream_class
,
166 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
171 if (stream_class
->frozen
) {
172 BT_LOGW("Invalid parameter: stream class is frozen: "
173 "addr=%p, name=\"%s\", id=%" PRId64
,
174 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
175 bt_ctf_stream_class_get_id(stream_class
));
180 g_string_assign(stream_class
->name
, name
);
181 BT_LOGV("Set stream class's name: "
182 "addr=%p, name=\"%s\", id=%" PRId64
,
183 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
184 bt_ctf_stream_class_get_id(stream_class
));
189 struct bt_ctf_clock
*bt_ctf_stream_class_get_clock(
190 struct bt_ctf_stream_class
*stream_class
)
192 struct bt_ctf_clock
*clock
= NULL
;
195 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
199 if (!stream_class
->clock
) {
200 BT_LOGV("Stream class has no clock: "
201 "addr=%p, name=\"%s\", id=%" PRId64
,
202 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
203 bt_ctf_stream_class_get_id(stream_class
));
207 clock
= bt_get(stream_class
->clock
);
212 int bt_ctf_stream_class_set_clock(struct bt_ctf_stream_class
*stream_class
,
213 struct bt_ctf_clock
*clock
)
216 struct bt_ctf_field_type
*timestamp_field
= NULL
;
218 if (!stream_class
|| !clock
) {
219 BT_LOGW("Invalid parameter: stream class or clock is NULL: "
220 "stream-class-addr=%p, clock-addr=%p",
221 stream_class
, clock
);
226 if (stream_class
->frozen
) {
227 BT_LOGW("Invalid parameter: stream class is frozen: "
228 "addr=%p, name=\"%s\", id=%" PRId64
,
229 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
230 bt_ctf_stream_class_get_id(stream_class
));
235 /* Replace the current clock of this stream class. */
236 bt_put(stream_class
->clock
);
237 stream_class
->clock
= bt_get(clock
);
238 BT_LOGV("Set stream class's clock: "
239 "addr=%p, name=\"%s\", id=%" PRId64
", "
240 "clock-addr=%p, clock-name=\"%s\"",
241 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
242 bt_ctf_stream_class_get_id(stream_class
),
244 bt_ctf_clock_get_name(stream_class
->clock
));
247 bt_put(timestamp_field
);
251 int64_t bt_ctf_stream_class_get_id(struct bt_ctf_stream_class
*stream_class
)
256 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
261 if (!stream_class
->id_set
) {
262 BT_LOGV("Stream class's ID is not set: addr=%p, name=\"%s\"",
264 bt_ctf_stream_class_get_name(stream_class
));
269 ret
= stream_class
->id
;
275 void _bt_ctf_stream_class_set_id(
276 struct bt_ctf_stream_class
*stream_class
, int64_t id
)
278 assert(stream_class
);
279 stream_class
->id
= id
;
280 stream_class
->id_set
= 1;
281 BT_LOGV("Set stream class's ID (internal): "
282 "addr=%p, name=\"%s\", id=%" PRId64
,
283 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
284 bt_ctf_stream_class_get_id(stream_class
));
287 struct event_class_set_stream_class_id_data
{
288 int64_t stream_class_id
;
293 void event_class_set_stream_id(gpointer event_class
, gpointer data
)
295 struct event_class_set_stream_class_id_data
*typed_data
= data
;
297 typed_data
->ret
|= bt_ctf_event_class_set_stream_id(event_class
,
298 typed_data
->stream_class_id
);
302 int bt_ctf_stream_class_set_id_no_check(
303 struct bt_ctf_stream_class
*stream_class
, int64_t id
)
306 struct event_class_set_stream_class_id_data data
=
307 { .stream_class_id
= id
, .ret
= 0 };
310 * Make sure all event classes have their "stream_id" attribute
313 g_ptr_array_foreach(stream_class
->event_classes
,
314 event_class_set_stream_id
, &data
);
317 BT_LOGE("Cannot set the IDs of all stream class's event classes: "
318 "addr=%p, name=\"%s\", id=%" PRId64
,
319 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
320 bt_ctf_stream_class_get_id(stream_class
));
324 _bt_ctf_stream_class_set_id(stream_class
, id
);
329 int bt_ctf_stream_class_set_id(struct bt_ctf_stream_class
*stream_class
,
333 int64_t id
= (int64_t) id_param
;
336 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
341 if (stream_class
->frozen
) {
342 BT_LOGW("Invalid parameter: stream class is frozen: "
343 "addr=%p, name=\"%s\", id=%" PRId64
,
344 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
345 bt_ctf_stream_class_get_id(stream_class
));
351 BT_LOGW("Invalid parameter: invalid stream class's ID: "
352 "stream-class-addr=%p, stream-class-name=\"%s\", "
353 "stream-class-id=%" PRId64
", id=%" PRIu64
,
354 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
355 bt_ctf_stream_class_get_id(stream_class
),
361 ret
= bt_ctf_stream_class_set_id_no_check(stream_class
, id
);
363 BT_LOGV("Set stream class's ID: "
364 "addr=%p, name=\"%s\", id=%" PRId64
,
365 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
366 bt_ctf_stream_class_get_id(stream_class
));
373 void event_class_exists(gpointer element
, gpointer query
)
375 struct bt_ctf_event_class
*event_class_a
= element
;
376 struct search_query
*search_query
= query
;
377 struct bt_ctf_event_class
*event_class_b
= search_query
->value
;
380 if (search_query
->value
== element
) {
381 search_query
->found
= 1;
386 * Two event classes cannot share the same ID in a given
389 id_a
= bt_ctf_event_class_get_id(event_class_a
);
390 id_b
= bt_ctf_event_class_get_id(event_class_b
);
392 if (id_a
< 0 || id_b
< 0) {
393 /* at least one ID is not set: will be automatically set later */
398 BT_LOGW("Event class with this ID already exists in the stream class: "
399 "id=%" PRId64
", name=\"%s\"",
400 id_a
, bt_ctf_event_class_get_name(event_class_a
));
401 search_query
->found
= 1;
409 int bt_ctf_stream_class_add_event_class(
410 struct bt_ctf_stream_class
*stream_class
,
411 struct bt_ctf_event_class
*event_class
)
414 int64_t *event_id
= NULL
;
415 struct bt_ctf_trace
*trace
= NULL
;
416 struct bt_ctf_stream_class
*old_stream_class
= NULL
;
417 struct bt_ctf_validation_output validation_output
= { 0 };
418 struct bt_ctf_field_type
*packet_header_type
= NULL
;
419 struct bt_ctf_field_type
*packet_context_type
= NULL
;
420 struct bt_ctf_field_type
*event_header_type
= NULL
;
421 struct bt_ctf_field_type
*stream_event_ctx_type
= NULL
;
422 struct bt_ctf_field_type
*event_context_type
= NULL
;
423 struct bt_ctf_field_type
*event_payload_type
= NULL
;
424 const enum bt_ctf_validation_flag validation_flags
=
425 BT_CTF_VALIDATION_FLAG_EVENT
;
427 if (!stream_class
|| !event_class
) {
428 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
429 "stream-class-addr=%p, event-class-addr=%p",
430 stream_class
, event_class
);
435 BT_LOGD("Adding event class to stream class: "
436 "stream-class-addr=%p, stream-class-name=\"%s\", "
437 "stream-class-id=%" PRId64
", event-class-addr=%p, "
438 "event-class-name=\"%s\", event-class-id=%" PRId64
,
439 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
440 bt_ctf_stream_class_get_id(stream_class
),
442 bt_ctf_event_class_get_name(event_class
),
443 bt_ctf_event_class_get_id(event_class
));
445 trace
= bt_ctf_stream_class_get_trace(stream_class
);
446 if (trace
&& trace
->is_static
) {
451 event_id
= g_new(int64_t, 1);
453 BT_LOGE_STR("Failed to allocate one int64_t.");
458 /* Check for duplicate event classes */
459 struct search_query query
= { .value
= event_class
, .found
= 0 };
460 g_ptr_array_foreach(stream_class
->event_classes
, event_class_exists
,
463 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
468 old_stream_class
= bt_ctf_event_class_get_stream_class(event_class
);
469 if (old_stream_class
) {
470 /* Event class is already associated to a stream class. */
471 BT_LOGW("Event class is already part of another stream class: "
472 "event-class-stream-class-addr=%p, "
473 "event-class-stream-class-name=\"%s\", "
474 "event-class-stream-class-id=%" PRId64
,
476 bt_ctf_stream_class_get_name(old_stream_class
),
477 bt_ctf_stream_class_get_id(old_stream_class
));
484 * If the stream class is associated with a trace, then
485 * both those objects are frozen. Also, this event class
486 * is about to be frozen.
488 * Therefore the event class must be validated here.
489 * The trace and stream class should be valid at this
492 assert(trace
->valid
);
493 assert(stream_class
->valid
);
495 bt_ctf_trace_get_packet_header_type(trace
);
496 packet_context_type
=
497 bt_ctf_stream_class_get_packet_context_type(
500 bt_ctf_stream_class_get_event_header_type(stream_class
);
501 stream_event_ctx_type
=
502 bt_ctf_stream_class_get_event_context_type(
505 bt_ctf_event_class_get_context_type(event_class
);
507 bt_ctf_event_class_get_payload_type(event_class
);
508 ret
= bt_ctf_validate_class_types(
509 trace
->environment
, packet_header_type
,
510 packet_context_type
, event_header_type
,
511 stream_event_ctx_type
, event_context_type
,
512 event_payload_type
, trace
->valid
,
513 stream_class
->valid
, event_class
->valid
,
514 &validation_output
, validation_flags
);
515 BT_PUT(packet_header_type
);
516 BT_PUT(packet_context_type
);
517 BT_PUT(event_header_type
);
518 BT_PUT(stream_event_ctx_type
);
519 BT_PUT(event_context_type
);
520 BT_PUT(event_payload_type
);
524 * This means something went wrong during the
525 * validation process, not that the objects are
528 BT_LOGE("Failed to validate event class: ret=%d", ret
);
532 if ((validation_output
.valid_flags
& validation_flags
) !=
534 /* Invalid event class */
535 BT_LOGW("Invalid trace, stream class, or event class: "
537 validation_output
.valid_flags
);
543 /* Only set an event ID if none was explicitly set before */
544 *event_id
= bt_ctf_event_class_get_id(event_class
);
546 BT_LOGV("Event class has no ID: automatically setting it: "
547 "id=%" PRId64
, stream_class
->next_event_id
);
549 if (bt_ctf_event_class_set_id(event_class
,
550 stream_class
->next_event_id
)) {
551 BT_LOGE("Cannot set event class's ID: id=%" PRId64
,
552 stream_class
->next_event_id
);
556 stream_class
->next_event_id
++;
557 *event_id
= stream_class
->next_event_id
;
560 ret
= bt_ctf_event_class_set_stream_id(event_class
, stream_class
->id
);
562 BT_LOGE("Cannot set event class's stream class ID attribute: ret=%d",
567 bt_object_set_parent(event_class
, stream_class
);
571 * At this point we know that the function will be
572 * successful. Therefore we can replace the event
573 * class's field types with what's in the validation
574 * output structure and mark this event class as valid.
576 bt_ctf_validation_replace_types(NULL
, NULL
, event_class
,
577 &validation_output
, validation_flags
);
578 event_class
->valid
= 1;
581 * Put what was not moved in
582 * bt_ctf_validation_replace_types().
584 bt_ctf_validation_output_put_types(&validation_output
);
587 /* Add to the event classes of the stream class */
588 g_ptr_array_add(stream_class
->event_classes
, event_class
);
589 g_hash_table_insert(stream_class
->event_classes_ht
, event_id
,
593 /* Freeze the event class */
594 bt_ctf_event_class_freeze(event_class
);
596 /* Notifiy listeners of the trace's schema modification. */
598 struct bt_ctf_object obj
= { .object
= event_class
,
599 .type
= BT_CTF_OBJECT_TYPE_EVENT_CLASS
};
601 (void) bt_ctf_trace_object_modification(&obj
, trace
);
604 BT_LOGD("Added event class to stream class: "
605 "stream-class-addr=%p, stream-class-name=\"%s\", "
606 "stream-class-id=%" PRId64
", event-class-addr=%p, "
607 "event-class-name=\"%s\", event-class-id=%" PRId64
,
608 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
609 bt_ctf_stream_class_get_id(stream_class
),
611 bt_ctf_event_class_get_name(event_class
),
612 bt_ctf_event_class_get_id(event_class
));
616 BT_PUT(old_stream_class
);
617 bt_ctf_validation_output_put_types(&validation_output
);
618 assert(!packet_header_type
);
619 assert(!packet_context_type
);
620 assert(!event_header_type
);
621 assert(!stream_event_ctx_type
);
622 assert(!event_context_type
);
623 assert(!event_payload_type
);
629 int64_t bt_ctf_stream_class_get_event_class_count(
630 struct bt_ctf_stream_class
*stream_class
)
635 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
640 ret
= (int64_t) stream_class
->event_classes
->len
;
645 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_index(
646 struct bt_ctf_stream_class
*stream_class
, uint64_t index
)
648 struct bt_ctf_event_class
*event_class
= NULL
;
651 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
655 if (index
>= stream_class
->event_classes
->len
) {
656 BT_LOGW("Invalid parameter: index is out of bounds: "
657 "addr=%p, name=\"%s\", id=%" PRId64
", "
658 "index=%" PRIu64
", count=%u",
659 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
660 bt_ctf_stream_class_get_id(stream_class
),
661 index
, stream_class
->event_classes
->len
);
665 event_class
= g_ptr_array_index(stream_class
->event_classes
, index
);
671 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_id(
672 struct bt_ctf_stream_class
*stream_class
, uint64_t id
)
674 int64_t id_key
= (int64_t) id
;
675 struct bt_ctf_event_class
*event_class
= NULL
;
678 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
683 BT_LOGW("Invalid parameter: invalid event class's ID: "
684 "stream-class-addr=%p, stream-class-name=\"%s\", "
685 "stream-class-id=%" PRId64
", event-class-id=%" PRIu64
,
687 bt_ctf_stream_class_get_name(stream_class
),
688 bt_ctf_stream_class_get_id(stream_class
), id
);
692 event_class
= g_hash_table_lookup(stream_class
->event_classes_ht
,
699 struct bt_ctf_field_type
*bt_ctf_stream_class_get_packet_context_type(
700 struct bt_ctf_stream_class
*stream_class
)
702 struct bt_ctf_field_type
*ret
= NULL
;
705 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
709 bt_get(stream_class
->packet_context_type
);
710 ret
= stream_class
->packet_context_type
;
715 int bt_ctf_stream_class_set_packet_context_type(
716 struct bt_ctf_stream_class
*stream_class
,
717 struct bt_ctf_field_type
*packet_context_type
)
722 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
727 if (stream_class
->frozen
) {
728 BT_LOGW("Invalid parameter: stream class is frozen: "
729 "addr=%p, name=\"%s\", id=%" PRId64
,
730 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
731 bt_ctf_stream_class_get_id(stream_class
));
736 if (packet_context_type
&&
737 bt_ctf_field_type_get_type_id(packet_context_type
) !=
738 BT_CTF_FIELD_TYPE_ID_STRUCT
) {
739 /* A packet context must be a structure. */
740 BT_LOGW("Invalid parameter: stream class's packet context field type must be a structure: "
741 "addr=%p, name=\"%s\", id=%" PRId64
", "
742 "packet-context-ft-addr=%p, packet-context-ft-id=%s",
743 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
744 bt_ctf_stream_class_get_id(stream_class
),
746 bt_ctf_field_type_id_string(
747 bt_ctf_field_type_get_type_id(packet_context_type
)));
752 bt_put(stream_class
->packet_context_type
);
753 bt_get(packet_context_type
);
754 stream_class
->packet_context_type
= packet_context_type
;
755 BT_LOGV("Set stream class's packet context field type: "
756 "addr=%p, name=\"%s\", id=%" PRId64
", "
757 "packet-context-ft-addr=%p",
758 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
759 bt_ctf_stream_class_get_id(stream_class
),
760 packet_context_type
);
766 struct bt_ctf_field_type
*bt_ctf_stream_class_get_event_header_type(
767 struct bt_ctf_stream_class
*stream_class
)
769 struct bt_ctf_field_type
*ret
= NULL
;
772 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
776 if (!stream_class
->event_header_type
) {
777 BT_LOGV("Stream class has no event header field type: "
778 "addr=%p, name=\"%s\", id=%" PRId64
,
779 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
780 bt_ctf_stream_class_get_id(stream_class
));
784 bt_get(stream_class
->event_header_type
);
785 ret
= stream_class
->event_header_type
;
790 int bt_ctf_stream_class_set_event_header_type(
791 struct bt_ctf_stream_class
*stream_class
,
792 struct bt_ctf_field_type
*event_header_type
)
797 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
802 if (stream_class
->frozen
) {
803 BT_LOGW("Invalid parameter: stream class is frozen: "
804 "addr=%p, name=\"%s\", id=%" PRId64
,
805 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
806 bt_ctf_stream_class_get_id(stream_class
));
811 if (event_header_type
&&
812 bt_ctf_field_type_get_type_id(event_header_type
) !=
813 BT_CTF_FIELD_TYPE_ID_STRUCT
) {
814 /* An event header must be a structure. */
815 BT_LOGW("Invalid parameter: stream class's event header field type must be a structure: "
816 "addr=%p, name=\"%s\", id=%" PRId64
", "
817 "event-header-ft-addr=%p, event-header-ft-id=%s",
818 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
819 bt_ctf_stream_class_get_id(stream_class
),
821 bt_ctf_field_type_id_string(
822 bt_ctf_field_type_get_type_id(event_header_type
)));
827 bt_put(stream_class
->event_header_type
);
828 stream_class
->event_header_type
= bt_get(event_header_type
);
829 BT_LOGV("Set stream class's event header field type: "
830 "addr=%p, name=\"%s\", id=%" PRId64
", "
831 "event-header-ft-addr=%p",
832 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
833 bt_ctf_stream_class_get_id(stream_class
),
839 struct bt_ctf_field_type
*bt_ctf_stream_class_get_event_context_type(
840 struct bt_ctf_stream_class
*stream_class
)
842 struct bt_ctf_field_type
*ret
= NULL
;
845 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
849 if (!stream_class
->event_context_type
) {
853 bt_get(stream_class
->event_context_type
);
854 ret
= stream_class
->event_context_type
;
859 int bt_ctf_stream_class_set_event_context_type(
860 struct bt_ctf_stream_class
*stream_class
,
861 struct bt_ctf_field_type
*event_context_type
)
866 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
871 if (stream_class
->frozen
) {
872 BT_LOGW("Invalid parameter: stream class is frozen: "
873 "addr=%p, name=\"%s\", id=%" PRId64
,
874 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
875 bt_ctf_stream_class_get_id(stream_class
));
880 if (event_context_type
&&
881 bt_ctf_field_type_get_type_id(event_context_type
) !=
882 BT_CTF_FIELD_TYPE_ID_STRUCT
) {
883 /* A packet context must be a structure. */
884 BT_LOGW("Invalid parameter: stream class's event context field type must be a structure: "
885 "addr=%p, name=\"%s\", id=%" PRId64
", "
886 "event-context-ft-addr=%p, event-context-ft-id=%s",
887 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
888 bt_ctf_stream_class_get_id(stream_class
),
890 bt_ctf_field_type_id_string(
891 bt_ctf_field_type_get_type_id(event_context_type
)));
896 bt_put(stream_class
->event_context_type
);
897 stream_class
->event_context_type
= bt_get(event_context_type
);
898 BT_LOGV("Set stream class's event context field type: "
899 "addr=%p, name=\"%s\", id=%" PRId64
", "
900 "event-context-ft-addr=%p",
901 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
902 bt_ctf_stream_class_get_id(stream_class
),
908 /* Pre-2.0 CTF writer backward compatibility */
909 void bt_ctf_stream_class_get(struct bt_ctf_stream_class
*stream_class
)
911 bt_get(stream_class
);
914 /* Pre-2.0 CTF writer backward compatibility */
915 void bt_ctf_stream_class_put(struct bt_ctf_stream_class
*stream_class
)
917 bt_put(stream_class
);
921 int64_t get_event_class_count(void *element
)
923 return bt_ctf_stream_class_get_event_class_count(
924 (struct bt_ctf_stream_class
*) element
);
928 void *get_event_class(void *element
, int i
)
930 return bt_ctf_stream_class_get_event_class_by_index(
931 (struct bt_ctf_stream_class
*) element
, i
);
935 int visit_event_class(void *object
, bt_ctf_visitor visitor
,void *data
)
937 struct bt_ctf_object obj
=
939 .type
= BT_CTF_OBJECT_TYPE_EVENT_CLASS
};
941 return visitor(&obj
, data
);
944 int bt_ctf_stream_class_visit(struct bt_ctf_stream_class
*stream_class
,
945 bt_ctf_visitor visitor
, void *data
)
948 struct bt_ctf_object obj
=
949 { .object
= stream_class
,
950 .type
= BT_CTF_OBJECT_TYPE_STREAM_CLASS
};
952 if (!stream_class
|| !visitor
) {
953 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
954 "stream-class-addr=%p, visitor=%p",
955 stream_class
, visitor
);
960 ret
= visitor_helper(&obj
, get_event_class_count
,
962 visit_event_class
, visitor
, data
);
963 BT_LOGV("visitor_helper() returned: ret=%d", ret
);
969 void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class
*stream_class
)
971 if (!stream_class
|| stream_class
->frozen
) {
975 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64
,
976 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
977 bt_ctf_stream_class_get_id(stream_class
));
978 stream_class
->frozen
= 1;
979 bt_ctf_field_type_freeze(stream_class
->event_header_type
);
980 bt_ctf_field_type_freeze(stream_class
->packet_context_type
);
981 bt_ctf_field_type_freeze(stream_class
->event_context_type
);
983 if (stream_class
->clock
) {
984 bt_ctf_clock_class_freeze(stream_class
->clock
->clock_class
);
989 int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class
*stream_class
,
990 struct metadata_context
*context
)
995 BT_LOGD("Serializing stream class's metadata: "
996 "stream-class-addr=%p, stream-class-name=\"%s\", "
997 "stream-class-id=%" PRId64
", metadata-context-addr=%p",
998 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
999 bt_ctf_stream_class_get_id(stream_class
), context
);
1000 g_string_assign(context
->field_name
, "");
1001 context
->current_indentation_level
= 1;
1002 if (!stream_class
->id_set
) {
1003 BT_LOGW_STR("Stream class's ID is not set.");
1008 g_string_append_printf(context
->string
,
1009 "stream {\n\tid = %" PRId64
";\n", stream_class
->id
);
1010 if (stream_class
->event_header_type
) {
1011 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
1012 g_string_append(context
->string
, "\tevent.header := ");
1013 ret
= bt_ctf_field_type_serialize(stream_class
->event_header_type
,
1016 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
1020 g_string_append(context
->string
, ";");
1024 if (stream_class
->packet_context_type
) {
1025 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
1026 g_string_append(context
->string
, "\n\n\tpacket.context := ");
1027 ret
= bt_ctf_field_type_serialize(stream_class
->packet_context_type
,
1030 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
1034 g_string_append(context
->string
, ";");
1037 if (stream_class
->event_context_type
) {
1038 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
1039 g_string_append(context
->string
, "\n\n\tevent.context := ");
1040 ret
= bt_ctf_field_type_serialize(
1041 stream_class
->event_context_type
, context
);
1043 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
1047 g_string_append(context
->string
, ";");
1050 g_string_append(context
->string
, "\n};\n\n");
1052 for (i
= 0; i
< stream_class
->event_classes
->len
; i
++) {
1053 struct bt_ctf_event_class
*event_class
=
1054 stream_class
->event_classes
->pdata
[i
];
1056 ret
= bt_ctf_event_class_serialize(event_class
, context
);
1058 BT_LOGW("Cannot serialize event class's metadata: "
1059 "event-class-addr=%p, event-class-name=\"%s\", "
1060 "event-class-id=%" PRId64
,
1062 bt_ctf_event_class_get_name(event_class
),
1063 bt_ctf_event_class_get_id(event_class
));
1068 context
->current_indentation_level
= 0;
1073 void bt_ctf_stream_class_destroy(struct bt_object
*obj
)
1075 struct bt_ctf_stream_class
*stream_class
;
1077 stream_class
= container_of(obj
, struct bt_ctf_stream_class
, base
);
1078 BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64
,
1079 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
1080 bt_ctf_stream_class_get_id(stream_class
));
1081 bt_put(stream_class
->clock
);
1083 if (stream_class
->event_classes_ht
) {
1084 g_hash_table_destroy(stream_class
->event_classes_ht
);
1086 if (stream_class
->event_classes
) {
1087 BT_LOGD_STR("Destroying event classes.");
1088 g_ptr_array_free(stream_class
->event_classes
, TRUE
);
1091 if (stream_class
->name
) {
1092 g_string_free(stream_class
->name
, TRUE
);
1095 BT_LOGD_STR("Putting event header field type.");
1096 bt_put(stream_class
->event_header_type
);
1097 BT_LOGD_STR("Putting packet context field type.");
1098 bt_put(stream_class
->packet_context_type
);
1099 BT_LOGD_STR("Putting event context field type.");
1100 bt_put(stream_class
->event_context_type
);
1101 g_free(stream_class
);
1105 int init_event_header(struct bt_ctf_stream_class
*stream_class
)
1108 struct bt_ctf_field_type
*event_header_type
=
1109 bt_ctf_field_type_structure_create();
1110 struct bt_ctf_field_type
*_uint32_t
=
1111 get_field_type(FIELD_TYPE_ALIAS_UINT32_T
);
1112 struct bt_ctf_field_type
*_uint64_t
=
1113 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
1115 if (!event_header_type
) {
1116 BT_LOGE_STR("Cannot create empty structure field type.");
1121 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
1124 BT_LOGE_STR("Cannot add `id` field to event header field type.");
1128 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
1129 _uint64_t
, "timestamp");
1131 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
1135 BT_MOVE(stream_class
->event_header_type
, event_header_type
);
1138 bt_put(event_header_type
);
1147 int init_packet_context(struct bt_ctf_stream_class
*stream_class
)
1150 struct bt_ctf_field_type
*packet_context_type
=
1151 bt_ctf_field_type_structure_create();
1152 struct bt_ctf_field_type
*_uint64_t
=
1153 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
1154 struct bt_ctf_field_type
*ts_begin_end_uint64_t
;
1156 if (!packet_context_type
) {
1157 BT_LOGE_STR("Cannot create empty structure field type.");
1162 ts_begin_end_uint64_t
= bt_ctf_field_type_copy(_uint64_t
);
1163 if (!ts_begin_end_uint64_t
) {
1164 BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
1170 * We create a stream packet context as proposed in the CTF
1173 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1174 ts_begin_end_uint64_t
, "timestamp_begin");
1176 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
1180 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1181 ts_begin_end_uint64_t
, "timestamp_end");
1183 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
1187 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1188 _uint64_t
, "content_size");
1190 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
1194 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1195 _uint64_t
, "packet_size");
1197 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
1201 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1202 _uint64_t
, "events_discarded");
1204 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
1208 BT_MOVE(stream_class
->packet_context_type
, packet_context_type
);
1211 bt_put(packet_context_type
);
1216 bt_put(ts_begin_end_uint64_t
);
1221 int try_map_clock_class(struct bt_ctf_stream_class
*stream_class
,
1222 struct bt_ctf_field_type
*ft
)
1224 struct bt_ctf_clock_class
*mapped_clock_class
= NULL
;
1228 /* Field does not exist: not an error */
1232 assert(bt_ctf_field_type_is_integer(ft
));
1233 mapped_clock_class
=
1234 bt_ctf_field_type_integer_get_mapped_clock_class(ft
);
1235 if (!mapped_clock_class
) {
1236 if (!stream_class
->clock
) {
1237 BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
1238 "stream-class-addr=%p, stream-class-name=\"%s\", "
1239 "stream-class-id=%" PRId64
", ft-addr=%p",
1240 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
1241 bt_ctf_stream_class_get_id(stream_class
), ft
);
1246 ret
= bt_ctf_field_type_integer_set_mapped_clock_class_no_check(
1247 ft
, stream_class
->clock
->clock_class
);
1249 BT_LOGW("Cannot set field type's mapped clock class: "
1250 "stream-class-addr=%p, stream-class-name=\"%s\", "
1251 "stream-class-id=%" PRId64
", ft-addr=%p",
1252 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
1253 bt_ctf_stream_class_get_id(stream_class
), ft
);
1257 BT_LOGV("Automatically mapped field type to stream class's clock class: "
1258 "stream-class-addr=%p, stream-class-name=\"%s\", "
1259 "stream-class-id=%" PRId64
", ft-addr=%p",
1260 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
1261 bt_ctf_stream_class_get_id(stream_class
), ft
);
1265 bt_put(mapped_clock_class
);
1270 int bt_ctf_stream_class_map_clock_class(
1271 struct bt_ctf_stream_class
*stream_class
,
1272 struct bt_ctf_field_type
*packet_context_type
,
1273 struct bt_ctf_field_type
*event_header_type
)
1275 struct bt_ctf_field_type
*ft
= NULL
;
1278 assert(stream_class
);
1280 if (packet_context_type
) {
1281 ft
= bt_ctf_field_type_structure_get_field_type_by_name(
1282 packet_context_type
, "timestamp_begin");
1283 if (try_map_clock_class(stream_class
, ft
)) {
1284 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
1290 ft
= bt_ctf_field_type_structure_get_field_type_by_name(
1291 packet_context_type
, "timestamp_end");
1292 if (try_map_clock_class(stream_class
, ft
)) {
1293 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
1301 if (event_header_type
) {
1302 ft
= bt_ctf_field_type_structure_get_field_type_by_name(
1303 event_header_type
, "timestamp");
1304 if (try_map_clock_class(stream_class
, ft
)) {
1305 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");