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>
54 void bt_ctf_stream_class_destroy(struct bt_object
*obj
);
56 int init_event_header(struct bt_ctf_stream_class
*stream_class
);
58 int init_packet_context(struct bt_ctf_stream_class
*stream_class
);
60 struct bt_ctf_stream_class
*bt_ctf_stream_class_create(const char *name
)
62 struct bt_ctf_stream_class
*stream_class
;
65 BT_LOGD("Creating default stream class object: name=\"%s\"", name
);
66 stream_class
= bt_ctf_stream_class_create_empty(name
);
68 BT_LOGD_STR("Cannot create empty stream class.");
72 ret
= init_event_header(stream_class
);
74 BT_LOGE_STR("Cannot initialize stream class's event header field type.");
78 ret
= init_packet_context(stream_class
);
80 BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
84 BT_LOGD("Created default stream class object: addr=%p, name=\"%s\"",
93 struct bt_ctf_stream_class
*bt_ctf_stream_class_create_empty(const char *name
)
95 struct bt_ctf_stream_class
*stream_class
= NULL
;
97 BT_LOGD("Creating empty stream class object: name=\"%s\"", name
);
99 if (name
&& bt_ctf_validate_identifier(name
)) {
100 BT_LOGW("Invalid parameter: stream class's name is not a valid CTF identifier: "
101 "name=\"%s\"", name
);
105 stream_class
= g_new0(struct bt_ctf_stream_class
, 1);
107 BT_LOGE_STR("Failed to allocate one stream class.");
111 stream_class
->name
= g_string_new(name
);
112 stream_class
->event_classes
= g_ptr_array_new_with_free_func(
113 (GDestroyNotify
) bt_object_release
);
114 if (!stream_class
->event_classes
) {
115 BT_LOGE_STR("Failed to allocate a GPtrArray.");
119 stream_class
->event_classes_ht
= g_hash_table_new_full(g_int64_hash
,
120 g_int64_equal
, g_free
, NULL
);
121 if (!stream_class
->event_classes_ht
) {
122 BT_LOGE_STR("Failed to allocate a GHashTable.");
126 stream_class
->packet_context_type
= bt_ctf_field_type_structure_create();
127 if (!stream_class
->packet_context_type
) {
128 BT_LOGE_STR("Cannot stream class's initial packet context field type.");
132 stream_class
->event_header_type
= bt_ctf_field_type_structure_create();
133 if (!stream_class
->event_header_type
) {
134 BT_LOGE_STR("Cannot stream class's initial event header field type.");
138 stream_class
->event_context_type
= bt_ctf_field_type_structure_create();
139 if (!stream_class
->event_context_type
) {
140 BT_LOGE_STR("Cannot stream class's initial event context field type.");
144 bt_object_init(stream_class
, bt_ctf_stream_class_destroy
);
145 BT_LOGD("Created empty stream class object: addr=%p, name=\"%s\"",
150 BT_PUT(stream_class
);
154 struct bt_ctf_trace
*bt_ctf_stream_class_get_trace(
155 struct bt_ctf_stream_class
*stream_class
)
157 return stream_class
?
158 bt_get(bt_ctf_stream_class_borrow_trace(stream_class
)) :
162 const char *bt_ctf_stream_class_get_name(
163 struct bt_ctf_stream_class
*stream_class
)
165 const char *name
= NULL
;
168 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
172 name
= stream_class
->name
->str
;
177 int bt_ctf_stream_class_set_name(struct bt_ctf_stream_class
*stream_class
,
183 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
188 if (stream_class
->frozen
) {
189 BT_LOGW("Invalid parameter: stream class is frozen: "
190 "addr=%p, name=\"%s\", id=%" PRId64
,
191 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
192 bt_ctf_stream_class_get_id(stream_class
));
197 g_string_assign(stream_class
->name
, name
);
198 BT_LOGV("Set stream class's name: "
199 "addr=%p, name=\"%s\", id=%" PRId64
,
200 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
201 bt_ctf_stream_class_get_id(stream_class
));
206 struct bt_ctf_clock
*bt_ctf_stream_class_get_clock(
207 struct bt_ctf_stream_class
*stream_class
)
209 struct bt_ctf_clock
*clock
= NULL
;
212 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
216 if (!stream_class
->clock
) {
217 BT_LOGV("Stream class has no clock: "
218 "addr=%p, name=\"%s\", id=%" PRId64
,
219 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
220 bt_ctf_stream_class_get_id(stream_class
));
224 clock
= bt_get(stream_class
->clock
);
229 int bt_ctf_stream_class_set_clock(struct bt_ctf_stream_class
*stream_class
,
230 struct bt_ctf_clock
*clock
)
233 struct bt_ctf_field_type
*timestamp_field
= NULL
;
235 if (!stream_class
|| !clock
) {
236 BT_LOGW("Invalid parameter: stream class or clock is NULL: "
237 "stream-class-addr=%p, clock-addr=%p",
238 stream_class
, clock
);
243 if (stream_class
->frozen
) {
244 BT_LOGW("Invalid parameter: stream class is frozen: "
245 "addr=%p, name=\"%s\", id=%" PRId64
,
246 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
247 bt_ctf_stream_class_get_id(stream_class
));
253 * Look for a "timestamp" integer field type in the stream
254 * class's event header field type and map the stream class's
255 * clock's class to that field type if there's no current
258 timestamp_field
= bt_ctf_field_type_structure_get_field_type_by_name(
259 stream_class
->event_header_type
, "timestamp");
260 if (timestamp_field
) {
261 struct bt_ctf_clock_class
*mapped_clock_class
=
262 bt_ctf_field_type_integer_get_mapped_clock_class(
265 if (!mapped_clock_class
) {
266 ret
= bt_ctf_field_type_integer_set_mapped_clock_class(
267 timestamp_field
, clock
->clock_class
);
273 BT_PUT(mapped_clock_class
);
276 /* Replace the current clock of this stream class. */
277 bt_put(stream_class
->clock
);
278 stream_class
->clock
= bt_get(clock
);
279 BT_LOGV("Set stream class's clock: "
280 "addr=%p, name=\"%s\", id=%" PRId64
", "
281 "clock-addr=%p, clock-name=\"%s\"",
282 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
283 bt_ctf_stream_class_get_id(stream_class
),
285 bt_ctf_clock_get_name(stream_class
->clock
));
288 bt_put(timestamp_field
);
292 int64_t bt_ctf_stream_class_get_id(struct bt_ctf_stream_class
*stream_class
)
297 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
302 if (!stream_class
->id_set
) {
303 BT_LOGV("Stream class's ID is not set: addr=%p, name=\"%s\"",
305 bt_ctf_stream_class_get_name(stream_class
));
310 ret
= stream_class
->id
;
316 void _bt_ctf_stream_class_set_id(
317 struct bt_ctf_stream_class
*stream_class
, int64_t id
)
319 assert(stream_class
);
320 stream_class
->id
= id
;
321 stream_class
->id_set
= 1;
322 BT_LOGV("Set stream class's ID (internal): "
323 "addr=%p, name=\"%s\", id=%" PRId64
,
324 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
325 bt_ctf_stream_class_get_id(stream_class
));
328 struct event_class_set_stream_class_id_data
{
329 int64_t stream_class_id
;
334 void event_class_set_stream_id(gpointer event_class
, gpointer data
)
336 struct event_class_set_stream_class_id_data
*typed_data
= data
;
338 typed_data
->ret
|= bt_ctf_event_class_set_stream_id(event_class
,
339 typed_data
->stream_class_id
);
343 int bt_ctf_stream_class_set_id_no_check(
344 struct bt_ctf_stream_class
*stream_class
, int64_t id
)
347 struct event_class_set_stream_class_id_data data
=
348 { .stream_class_id
= id
, .ret
= 0 };
351 * Make sure all event classes have their "stream_id" attribute
354 g_ptr_array_foreach(stream_class
->event_classes
,
355 event_class_set_stream_id
, &data
);
358 BT_LOGE("Cannot set the IDs of all stream class's event classes: "
359 "addr=%p, name=\"%s\", id=%" PRId64
,
360 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
361 bt_ctf_stream_class_get_id(stream_class
));
365 _bt_ctf_stream_class_set_id(stream_class
, id
);
370 int bt_ctf_stream_class_set_id(struct bt_ctf_stream_class
*stream_class
,
374 int64_t id
= (int64_t) id_param
;
377 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
382 if (stream_class
->frozen
) {
383 BT_LOGW("Invalid parameter: stream class is frozen: "
384 "addr=%p, name=\"%s\", id=%" PRId64
,
385 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
386 bt_ctf_stream_class_get_id(stream_class
));
392 BT_LOGW("Invalid parameter: invalid stream class's ID: "
393 "stream-class-addr=%p, stream-class-name=\"%s\", "
394 "stream-class-id=%" PRId64
", id=%" PRIu64
,
395 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
396 bt_ctf_stream_class_get_id(stream_class
),
402 ret
= bt_ctf_stream_class_set_id_no_check(stream_class
, id
);
404 BT_LOGV("Set stream class's ID: "
405 "addr=%p, name=\"%s\", id=%" PRId64
,
406 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
407 bt_ctf_stream_class_get_id(stream_class
));
414 void event_class_exists(gpointer element
, gpointer query
)
416 struct bt_ctf_event_class
*event_class_a
= element
;
417 struct search_query
*search_query
= query
;
418 struct bt_ctf_event_class
*event_class_b
= search_query
->value
;
421 if (search_query
->value
== element
) {
422 search_query
->found
= 1;
427 * Two event classes cannot share the same ID in a given
430 id_a
= bt_ctf_event_class_get_id(event_class_a
);
431 id_b
= bt_ctf_event_class_get_id(event_class_b
);
433 if (id_a
< 0 || id_b
< 0) {
434 /* at least one ID is not set: will be automatically set later */
439 BT_LOGW("Event class with this ID already exists in the stream class: "
440 "id=%" PRId64
", name=\"%s\"",
441 id_a
, bt_ctf_event_class_get_name(event_class_a
));
442 search_query
->found
= 1;
450 int bt_ctf_stream_class_add_event_class(
451 struct bt_ctf_stream_class
*stream_class
,
452 struct bt_ctf_event_class
*event_class
)
455 int64_t *event_id
= NULL
;
456 struct bt_ctf_trace
*trace
= NULL
;
457 struct bt_ctf_stream_class
*old_stream_class
= NULL
;
458 struct bt_ctf_validation_output validation_output
= { 0 };
459 struct bt_ctf_field_type
*packet_header_type
= NULL
;
460 struct bt_ctf_field_type
*packet_context_type
= NULL
;
461 struct bt_ctf_field_type
*event_header_type
= NULL
;
462 struct bt_ctf_field_type
*stream_event_ctx_type
= NULL
;
463 struct bt_ctf_field_type
*event_context_type
= NULL
;
464 struct bt_ctf_field_type
*event_payload_type
= NULL
;
465 const enum bt_ctf_validation_flag validation_flags
=
466 BT_CTF_VALIDATION_FLAG_EVENT
;
468 BT_LOGD("Adding event class to stream class: "
469 "stream-class-addr=%p, stream-class-name=\"%s\", "
470 "stream-class-id=%" PRId64
", event-class-addr=%p, "
471 "event-class-name=\"%s\", event-class-id=%" PRId64
,
472 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
473 bt_ctf_stream_class_get_id(stream_class
),
475 bt_ctf_event_class_get_name(event_class
),
476 bt_ctf_event_class_get_id(event_class
));
478 if (!stream_class
|| !event_class
) {
479 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
480 "stream-class-addr=%p, event-class-addr=%p",
481 stream_class
, event_class
);
486 trace
= bt_ctf_stream_class_get_trace(stream_class
);
487 if (trace
&& trace
->is_static
) {
492 event_id
= g_new(int64_t, 1);
494 BT_LOGE_STR("Failed to allocate one int64_t.");
499 /* Check for duplicate event classes */
500 struct search_query query
= { .value
= event_class
, .found
= 0 };
501 g_ptr_array_foreach(stream_class
->event_classes
, event_class_exists
,
504 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
509 old_stream_class
= bt_ctf_event_class_get_stream_class(event_class
);
510 if (old_stream_class
) {
511 /* Event class is already associated to a stream class. */
512 BT_LOGW("Event class is already part of another stream class: "
513 "event-class-stream-class-addr=%p, "
514 "event-class-stream-class-name=\"%s\", "
515 "event-class-stream-class-id=%" PRId64
,
517 bt_ctf_stream_class_get_name(old_stream_class
),
518 bt_ctf_stream_class_get_id(old_stream_class
));
525 * If the stream class is associated with a trace, then
526 * both those objects are frozen. Also, this event class
527 * is about to be frozen.
529 * Therefore the event class must be validated here.
530 * The trace and stream class should be valid at this
533 assert(trace
->valid
);
534 assert(stream_class
->valid
);
536 bt_ctf_trace_get_packet_header_type(trace
);
537 packet_context_type
=
538 bt_ctf_stream_class_get_packet_context_type(
541 bt_ctf_stream_class_get_event_header_type(stream_class
);
542 stream_event_ctx_type
=
543 bt_ctf_stream_class_get_event_context_type(
546 bt_ctf_event_class_get_context_type(event_class
);
548 bt_ctf_event_class_get_payload_type(event_class
);
549 ret
= bt_ctf_validate_class_types(
550 trace
->environment
, packet_header_type
,
551 packet_context_type
, event_header_type
,
552 stream_event_ctx_type
, event_context_type
,
553 event_payload_type
, trace
->valid
,
554 stream_class
->valid
, event_class
->valid
,
555 &validation_output
, validation_flags
);
556 BT_PUT(packet_header_type
);
557 BT_PUT(packet_context_type
);
558 BT_PUT(event_header_type
);
559 BT_PUT(stream_event_ctx_type
);
560 BT_PUT(event_context_type
);
561 BT_PUT(event_payload_type
);
565 * This means something went wrong during the
566 * validation process, not that the objects are
569 BT_LOGE("Failed to validate event class: ret=%d", ret
);
573 if ((validation_output
.valid_flags
& validation_flags
) !=
575 /* Invalid event class */
576 BT_LOGW("Invalid trace, stream class, or event class: "
578 validation_output
.valid_flags
);
584 /* Only set an event ID if none was explicitly set before */
585 *event_id
= bt_ctf_event_class_get_id(event_class
);
587 BT_LOGV("Event class has no ID: automatically setting it: "
588 "id=%" PRId64
, stream_class
->next_event_id
);
590 if (bt_ctf_event_class_set_id(event_class
,
591 stream_class
->next_event_id
)) {
592 BT_LOGE("Cannot set event class's ID: id=%" PRId64
,
593 stream_class
->next_event_id
);
597 stream_class
->next_event_id
++;
598 *event_id
= stream_class
->next_event_id
;
601 ret
= bt_ctf_event_class_set_stream_id(event_class
, stream_class
->id
);
603 BT_LOGE("Cannot set event class's stream class ID attribute: ret=%d",
608 bt_object_set_parent(event_class
, stream_class
);
612 * At this point we know that the function will be
613 * successful. Therefore we can replace the event
614 * class's field types with what's in the validation
615 * output structure and mark this event class as valid.
617 bt_ctf_validation_replace_types(NULL
, NULL
, event_class
,
618 &validation_output
, validation_flags
);
619 event_class
->valid
= 1;
622 * Put what was not moved in
623 * bt_ctf_validation_replace_types().
625 bt_ctf_validation_output_put_types(&validation_output
);
628 /* Add to the event classes of the stream class */
629 g_ptr_array_add(stream_class
->event_classes
, event_class
);
630 g_hash_table_insert(stream_class
->event_classes_ht
, event_id
,
634 /* Freeze the event class */
635 bt_ctf_event_class_freeze(event_class
);
637 /* Notifiy listeners of the trace's schema modification. */
639 struct bt_ctf_object obj
= { .object
= event_class
,
640 .type
= BT_CTF_OBJECT_TYPE_EVENT_CLASS
};
642 (void) bt_ctf_trace_object_modification(&obj
, trace
);
645 BT_LOGD("Added event class to stream class: "
646 "stream-class-addr=%p, stream-class-name=\"%s\", "
647 "stream-class-id=%" PRId64
", event-class-addr=%p, "
648 "event-class-name=\"%s\", event-class-id=%" PRId64
,
649 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
650 bt_ctf_stream_class_get_id(stream_class
),
652 bt_ctf_event_class_get_name(event_class
),
653 bt_ctf_event_class_get_id(event_class
));
657 BT_PUT(old_stream_class
);
658 bt_ctf_validation_output_put_types(&validation_output
);
659 assert(!packet_header_type
);
660 assert(!packet_context_type
);
661 assert(!event_header_type
);
662 assert(!stream_event_ctx_type
);
663 assert(!event_context_type
);
664 assert(!event_payload_type
);
670 int64_t bt_ctf_stream_class_get_event_class_count(
671 struct bt_ctf_stream_class
*stream_class
)
676 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
681 ret
= (int64_t) stream_class
->event_classes
->len
;
686 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_index(
687 struct bt_ctf_stream_class
*stream_class
, uint64_t index
)
689 struct bt_ctf_event_class
*event_class
= NULL
;
692 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
696 if (index
>= stream_class
->event_classes
->len
) {
697 BT_LOGW("Invalid parameter: index is out of bounds: "
698 "addr=%p, name=\"%s\", id=%" PRId64
", "
699 "index=%" PRIu64
", count=%u",
700 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
701 bt_ctf_stream_class_get_id(stream_class
),
702 index
, stream_class
->event_classes
->len
);
706 event_class
= g_ptr_array_index(stream_class
->event_classes
, index
);
712 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_id(
713 struct bt_ctf_stream_class
*stream_class
, uint64_t id
)
715 int64_t id_key
= (int64_t) id
;
716 struct bt_ctf_event_class
*event_class
= NULL
;
719 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
724 BT_LOGW("Invalid parameter: invalid event class's ID: "
725 "stream-class-addr=%p, stream-class-name=\"%s\", "
726 "stream-class-id=%" PRId64
", event-class-id=%" PRIu64
,
728 bt_ctf_stream_class_get_name(stream_class
),
729 bt_ctf_stream_class_get_id(stream_class
), id
);
733 event_class
= g_hash_table_lookup(stream_class
->event_classes_ht
,
740 struct bt_ctf_field_type
*bt_ctf_stream_class_get_packet_context_type(
741 struct bt_ctf_stream_class
*stream_class
)
743 struct bt_ctf_field_type
*ret
= NULL
;
746 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
750 bt_get(stream_class
->packet_context_type
);
751 ret
= stream_class
->packet_context_type
;
756 int bt_ctf_stream_class_set_packet_context_type(
757 struct bt_ctf_stream_class
*stream_class
,
758 struct bt_ctf_field_type
*packet_context_type
)
763 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
768 if (stream_class
->frozen
) {
769 BT_LOGW("Invalid parameter: stream class is frozen: "
770 "addr=%p, name=\"%s\", id=%" PRId64
,
771 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
772 bt_ctf_stream_class_get_id(stream_class
));
777 if (packet_context_type
&&
778 bt_ctf_field_type_get_type_id(packet_context_type
) !=
779 BT_CTF_FIELD_TYPE_ID_STRUCT
) {
780 /* A packet context must be a structure. */
781 BT_LOGW("Invalid parameter: stream class's packet context field type must be a structure: "
782 "addr=%p, name=\"%s\", id=%" PRId64
", "
783 "packet-context-ft-addr=%p, packet-context-ft-id=%s",
784 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
785 bt_ctf_stream_class_get_id(stream_class
),
787 bt_ctf_field_type_id_string(
788 bt_ctf_field_type_get_type_id(packet_context_type
)));
793 bt_put(stream_class
->packet_context_type
);
794 bt_get(packet_context_type
);
795 stream_class
->packet_context_type
= packet_context_type
;
796 BT_LOGV("Set stream class's packet context field type: "
797 "addr=%p, name=\"%s\", id=%" PRId64
", "
798 "packet-context-ft-addr=%p",
799 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
800 bt_ctf_stream_class_get_id(stream_class
),
801 packet_context_type
);
807 struct bt_ctf_field_type
*bt_ctf_stream_class_get_event_header_type(
808 struct bt_ctf_stream_class
*stream_class
)
810 struct bt_ctf_field_type
*ret
= NULL
;
813 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
817 if (!stream_class
->event_header_type
) {
818 BT_LOGV("Stream class has no event header field type: "
819 "addr=%p, name=\"%s\", id=%" PRId64
,
820 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
821 bt_ctf_stream_class_get_id(stream_class
));
825 bt_get(stream_class
->event_header_type
);
826 ret
= stream_class
->event_header_type
;
831 int bt_ctf_stream_class_set_event_header_type(
832 struct bt_ctf_stream_class
*stream_class
,
833 struct bt_ctf_field_type
*event_header_type
)
838 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
843 if (stream_class
->frozen
) {
844 BT_LOGW("Invalid parameter: stream class is frozen: "
845 "addr=%p, name=\"%s\", id=%" PRId64
,
846 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
847 bt_ctf_stream_class_get_id(stream_class
));
852 if (event_header_type
&&
853 bt_ctf_field_type_get_type_id(event_header_type
) !=
854 BT_CTF_FIELD_TYPE_ID_STRUCT
) {
855 /* An event header must be a structure. */
856 BT_LOGW("Invalid parameter: stream class's event header field type must be a structure: "
857 "addr=%p, name=\"%s\", id=%" PRId64
", "
858 "event-header-ft-addr=%p, event-header-ft-id=%s",
859 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
860 bt_ctf_stream_class_get_id(stream_class
),
862 bt_ctf_field_type_id_string(
863 bt_ctf_field_type_get_type_id(event_header_type
)));
868 bt_put(stream_class
->event_header_type
);
869 stream_class
->event_header_type
= bt_get(event_header_type
);
870 BT_LOGV("Set stream class's event header field type: "
871 "addr=%p, name=\"%s\", id=%" PRId64
", "
872 "event-header-ft-addr=%p",
873 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
874 bt_ctf_stream_class_get_id(stream_class
),
880 struct bt_ctf_field_type
*bt_ctf_stream_class_get_event_context_type(
881 struct bt_ctf_stream_class
*stream_class
)
883 struct bt_ctf_field_type
*ret
= NULL
;
886 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
890 if (!stream_class
->event_context_type
) {
894 bt_get(stream_class
->event_context_type
);
895 ret
= stream_class
->event_context_type
;
900 int bt_ctf_stream_class_set_event_context_type(
901 struct bt_ctf_stream_class
*stream_class
,
902 struct bt_ctf_field_type
*event_context_type
)
907 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
912 if (stream_class
->frozen
) {
913 BT_LOGW("Invalid parameter: stream class is frozen: "
914 "addr=%p, name=\"%s\", id=%" PRId64
,
915 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
916 bt_ctf_stream_class_get_id(stream_class
));
921 if (event_context_type
&&
922 bt_ctf_field_type_get_type_id(event_context_type
) !=
923 BT_CTF_FIELD_TYPE_ID_STRUCT
) {
924 /* A packet context must be a structure. */
925 BT_LOGW("Invalid parameter: stream class's event context field type must be a structure: "
926 "addr=%p, name=\"%s\", id=%" PRId64
", "
927 "event-context-ft-addr=%p, event-context-ft-id=%s",
928 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
929 bt_ctf_stream_class_get_id(stream_class
),
931 bt_ctf_field_type_id_string(
932 bt_ctf_field_type_get_type_id(event_context_type
)));
937 bt_put(stream_class
->event_context_type
);
938 stream_class
->event_context_type
= bt_get(event_context_type
);
939 BT_LOGV("Set stream class's event context field type: "
940 "addr=%p, name=\"%s\", id=%" PRId64
", "
941 "event-context-ft-addr=%p",
942 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
943 bt_ctf_stream_class_get_id(stream_class
),
949 /* Pre-2.0 CTF writer backward compatibility */
950 void bt_ctf_stream_class_get(struct bt_ctf_stream_class
*stream_class
)
952 bt_get(stream_class
);
955 /* Pre-2.0 CTF writer backward compatibility */
956 void bt_ctf_stream_class_put(struct bt_ctf_stream_class
*stream_class
)
958 bt_put(stream_class
);
962 int64_t get_event_class_count(void *element
)
964 return bt_ctf_stream_class_get_event_class_count(
965 (struct bt_ctf_stream_class
*) element
);
969 void *get_event_class(void *element
, int i
)
971 return bt_ctf_stream_class_get_event_class_by_index(
972 (struct bt_ctf_stream_class
*) element
, i
);
976 int visit_event_class(void *object
, bt_ctf_visitor visitor
,void *data
)
978 struct bt_ctf_object obj
=
980 .type
= BT_CTF_OBJECT_TYPE_EVENT_CLASS
};
982 return visitor(&obj
, data
);
985 int bt_ctf_stream_class_visit(struct bt_ctf_stream_class
*stream_class
,
986 bt_ctf_visitor visitor
, void *data
)
989 struct bt_ctf_object obj
=
990 { .object
= stream_class
,
991 .type
= BT_CTF_OBJECT_TYPE_STREAM_CLASS
};
993 if (!stream_class
|| !visitor
) {
994 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
995 "stream-class-addr=%p, visitor=%p",
996 stream_class
, visitor
);
1001 ret
= visitor_helper(&obj
, get_event_class_count
,
1003 visit_event_class
, visitor
, data
);
1004 BT_LOGV("visitor_helper() returned: ret=%d", ret
);
1010 void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class
*stream_class
)
1012 if (!stream_class
|| stream_class
->frozen
) {
1016 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64
,
1017 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
1018 bt_ctf_stream_class_get_id(stream_class
));
1019 stream_class
->frozen
= 1;
1020 bt_ctf_field_type_freeze(stream_class
->event_header_type
);
1021 bt_ctf_field_type_freeze(stream_class
->packet_context_type
);
1022 bt_ctf_field_type_freeze(stream_class
->event_context_type
);
1024 if (stream_class
->clock
) {
1025 bt_ctf_clock_class_freeze(stream_class
->clock
->clock_class
);
1030 int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class
*stream_class
,
1031 struct metadata_context
*context
)
1036 BT_LOGD("Serializing stream class's metadata: "
1037 "stream-class-addr=%p, stream-class-name=\"%s\", "
1038 "stream-class-id=%" PRId64
", metadata-context-addr=%p",
1039 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
1040 bt_ctf_stream_class_get_id(stream_class
), context
);
1041 g_string_assign(context
->field_name
, "");
1042 context
->current_indentation_level
= 1;
1043 if (!stream_class
->id_set
) {
1044 BT_LOGW_STR("Stream class's ID is not set.");
1049 g_string_append_printf(context
->string
,
1050 "stream {\n\tid = %" PRId64
";\n\tevent.header := ",
1052 ret
= bt_ctf_field_type_serialize(stream_class
->event_header_type
,
1055 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
1060 if (stream_class
->packet_context_type
) {
1061 g_string_append(context
->string
, ";\n\n\tpacket.context := ");
1062 ret
= bt_ctf_field_type_serialize(stream_class
->packet_context_type
,
1065 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
1071 if (stream_class
->event_context_type
) {
1072 g_string_append(context
->string
, ";\n\n\tevent.context := ");
1073 ret
= bt_ctf_field_type_serialize(
1074 stream_class
->event_context_type
, context
);
1076 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
1082 g_string_append(context
->string
, ";\n};\n\n");
1083 for (i
= 0; i
< stream_class
->event_classes
->len
; i
++) {
1084 struct bt_ctf_event_class
*event_class
=
1085 stream_class
->event_classes
->pdata
[i
];
1087 ret
= bt_ctf_event_class_serialize(event_class
, context
);
1089 BT_LOGW("Cannot serialize event class's metadata: "
1090 "event-class-addr=%p, event-class-name=\"%s\", "
1091 "event-class-id=%" PRId64
,
1093 bt_ctf_event_class_get_name(event_class
),
1094 bt_ctf_event_class_get_id(event_class
));
1099 context
->current_indentation_level
= 0;
1104 void bt_ctf_stream_class_destroy(struct bt_object
*obj
)
1106 struct bt_ctf_stream_class
*stream_class
;
1108 stream_class
= container_of(obj
, struct bt_ctf_stream_class
, base
);
1109 BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64
,
1110 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
1111 bt_ctf_stream_class_get_id(stream_class
));
1112 bt_put(stream_class
->clock
);
1114 if (stream_class
->event_classes_ht
) {
1115 g_hash_table_destroy(stream_class
->event_classes_ht
);
1117 if (stream_class
->event_classes
) {
1118 g_ptr_array_free(stream_class
->event_classes
, TRUE
);
1121 if (stream_class
->name
) {
1122 g_string_free(stream_class
->name
, TRUE
);
1125 bt_put(stream_class
->event_header_type
);
1126 bt_put(stream_class
->packet_context_type
);
1127 bt_put(stream_class
->event_context_type
);
1128 g_free(stream_class
);
1132 int init_event_header(struct bt_ctf_stream_class
*stream_class
)
1135 struct bt_ctf_field_type
*event_header_type
=
1136 bt_ctf_field_type_structure_create();
1137 struct bt_ctf_field_type
*_uint32_t
=
1138 get_field_type(FIELD_TYPE_ALIAS_UINT32_T
);
1139 struct bt_ctf_field_type
*_uint64_t
=
1140 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
1142 if (!event_header_type
) {
1143 BT_LOGE_STR("Cannot create empty structure field type.");
1148 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
1151 BT_LOGE_STR("Cannot add `id` field to event header field type.");
1155 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
1156 _uint64_t
, "timestamp");
1158 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
1162 BT_MOVE(stream_class
->event_header_type
, event_header_type
);
1165 bt_put(event_header_type
);
1174 int init_packet_context(struct bt_ctf_stream_class
*stream_class
)
1177 struct bt_ctf_field_type
*packet_context_type
=
1178 bt_ctf_field_type_structure_create();
1179 struct bt_ctf_field_type
*_uint64_t
=
1180 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
1182 if (!packet_context_type
) {
1183 BT_LOGE_STR("Cannot create empty structure field type.");
1189 * We create a stream packet context as proposed in the CTF
1192 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1193 _uint64_t
, "timestamp_begin");
1195 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
1199 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1200 _uint64_t
, "timestamp_end");
1202 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
1206 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1207 _uint64_t
, "content_size");
1209 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
1213 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1214 _uint64_t
, "packet_size");
1216 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
1220 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1221 _uint64_t
, "events_discarded");
1223 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
1227 BT_MOVE(stream_class
->packet_context_type
, packet_context_type
);
1230 bt_put(packet_context_type
);