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 stream_class
= g_new0(struct bt_ctf_stream_class
, 1);
102 BT_LOGE_STR("Failed to allocate one stream class.");
106 stream_class
->name
= g_string_new(name
);
107 stream_class
->event_classes
= g_ptr_array_new_with_free_func(
108 (GDestroyNotify
) bt_object_release
);
109 if (!stream_class
->event_classes
) {
110 BT_LOGE_STR("Failed to allocate a GPtrArray.");
114 stream_class
->event_classes_ht
= g_hash_table_new_full(g_int64_hash
,
115 g_int64_equal
, g_free
, NULL
);
116 if (!stream_class
->event_classes_ht
) {
117 BT_LOGE_STR("Failed to allocate a GHashTable.");
121 bt_object_init(stream_class
, bt_ctf_stream_class_destroy
);
122 BT_LOGD("Created empty stream class object: addr=%p, name=\"%s\"",
127 BT_PUT(stream_class
);
131 struct bt_ctf_trace
*bt_ctf_stream_class_get_trace(
132 struct bt_ctf_stream_class
*stream_class
)
134 return stream_class
?
135 bt_get(bt_ctf_stream_class_borrow_trace(stream_class
)) :
139 const char *bt_ctf_stream_class_get_name(
140 struct bt_ctf_stream_class
*stream_class
)
142 const char *name
= NULL
;
145 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
149 name
= stream_class
->name
->str
;
154 int bt_ctf_stream_class_set_name(struct bt_ctf_stream_class
*stream_class
,
160 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
165 if (stream_class
->frozen
) {
166 BT_LOGW("Invalid parameter: stream class is frozen: "
167 "addr=%p, name=\"%s\", id=%" PRId64
,
168 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
169 bt_ctf_stream_class_get_id(stream_class
));
174 g_string_assign(stream_class
->name
, name
);
175 BT_LOGV("Set stream class's name: "
176 "addr=%p, name=\"%s\", id=%" PRId64
,
177 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
178 bt_ctf_stream_class_get_id(stream_class
));
183 struct bt_ctf_clock
*bt_ctf_stream_class_get_clock(
184 struct bt_ctf_stream_class
*stream_class
)
186 struct bt_ctf_clock
*clock
= NULL
;
189 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
193 if (!stream_class
->clock
) {
194 BT_LOGV("Stream class has no clock: "
195 "addr=%p, name=\"%s\", id=%" PRId64
,
196 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
197 bt_ctf_stream_class_get_id(stream_class
));
201 clock
= bt_get(stream_class
->clock
);
206 int bt_ctf_stream_class_set_clock(struct bt_ctf_stream_class
*stream_class
,
207 struct bt_ctf_clock
*clock
)
210 struct bt_ctf_field_type
*timestamp_field
= NULL
;
212 if (!stream_class
|| !clock
) {
213 BT_LOGW("Invalid parameter: stream class or clock is NULL: "
214 "stream-class-addr=%p, clock-addr=%p",
215 stream_class
, clock
);
220 if (stream_class
->frozen
) {
221 BT_LOGW("Invalid parameter: stream class is frozen: "
222 "addr=%p, name=\"%s\", id=%" PRId64
,
223 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
224 bt_ctf_stream_class_get_id(stream_class
));
229 /* Replace the current clock of this stream class. */
230 bt_put(stream_class
->clock
);
231 stream_class
->clock
= bt_get(clock
);
232 BT_LOGV("Set stream class's clock: "
233 "addr=%p, name=\"%s\", id=%" PRId64
", "
234 "clock-addr=%p, clock-name=\"%s\"",
235 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
236 bt_ctf_stream_class_get_id(stream_class
),
238 bt_ctf_clock_get_name(stream_class
->clock
));
241 bt_put(timestamp_field
);
245 int64_t bt_ctf_stream_class_get_id(struct bt_ctf_stream_class
*stream_class
)
250 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
255 if (!stream_class
->id_set
) {
256 BT_LOGV("Stream class's ID is not set: addr=%p, name=\"%s\"",
258 bt_ctf_stream_class_get_name(stream_class
));
263 ret
= stream_class
->id
;
269 void _bt_ctf_stream_class_set_id(
270 struct bt_ctf_stream_class
*stream_class
, int64_t id
)
272 assert(stream_class
);
273 stream_class
->id
= id
;
274 stream_class
->id_set
= 1;
275 BT_LOGV("Set stream class's ID (internal): "
276 "addr=%p, name=\"%s\", id=%" PRId64
,
277 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
278 bt_ctf_stream_class_get_id(stream_class
));
281 struct event_class_set_stream_class_id_data
{
282 int64_t stream_class_id
;
287 void event_class_set_stream_id(gpointer event_class
, gpointer data
)
289 struct event_class_set_stream_class_id_data
*typed_data
= data
;
291 typed_data
->ret
|= bt_ctf_event_class_set_stream_id(event_class
,
292 typed_data
->stream_class_id
);
296 int bt_ctf_stream_class_set_id_no_check(
297 struct bt_ctf_stream_class
*stream_class
, int64_t id
)
300 struct event_class_set_stream_class_id_data data
=
301 { .stream_class_id
= id
, .ret
= 0 };
304 * Make sure all event classes have their "stream_id" attribute
307 g_ptr_array_foreach(stream_class
->event_classes
,
308 event_class_set_stream_id
, &data
);
311 BT_LOGE("Cannot set the IDs of all stream class's event classes: "
312 "addr=%p, name=\"%s\", id=%" PRId64
,
313 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
314 bt_ctf_stream_class_get_id(stream_class
));
318 _bt_ctf_stream_class_set_id(stream_class
, id
);
323 int bt_ctf_stream_class_set_id(struct bt_ctf_stream_class
*stream_class
,
327 int64_t id
= (int64_t) id_param
;
330 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
335 if (stream_class
->frozen
) {
336 BT_LOGW("Invalid parameter: stream class is frozen: "
337 "addr=%p, name=\"%s\", id=%" PRId64
,
338 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
339 bt_ctf_stream_class_get_id(stream_class
));
345 BT_LOGW("Invalid parameter: invalid stream class's ID: "
346 "stream-class-addr=%p, stream-class-name=\"%s\", "
347 "stream-class-id=%" PRId64
", id=%" PRIu64
,
348 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
349 bt_ctf_stream_class_get_id(stream_class
),
355 ret
= bt_ctf_stream_class_set_id_no_check(stream_class
, id
);
357 BT_LOGV("Set stream class's ID: "
358 "addr=%p, name=\"%s\", id=%" PRId64
,
359 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
360 bt_ctf_stream_class_get_id(stream_class
));
367 void event_class_exists(gpointer element
, gpointer query
)
369 struct bt_ctf_event_class
*event_class_a
= element
;
370 struct search_query
*search_query
= query
;
371 struct bt_ctf_event_class
*event_class_b
= search_query
->value
;
374 if (search_query
->value
== element
) {
375 search_query
->found
= 1;
380 * Two event classes cannot share the same ID in a given
383 id_a
= bt_ctf_event_class_get_id(event_class_a
);
384 id_b
= bt_ctf_event_class_get_id(event_class_b
);
386 if (id_a
< 0 || id_b
< 0) {
387 /* at least one ID is not set: will be automatically set later */
392 BT_LOGW("Event class with this ID already exists in the stream class: "
393 "id=%" PRId64
", name=\"%s\"",
394 id_a
, bt_ctf_event_class_get_name(event_class_a
));
395 search_query
->found
= 1;
403 int bt_ctf_stream_class_add_event_class(
404 struct bt_ctf_stream_class
*stream_class
,
405 struct bt_ctf_event_class
*event_class
)
408 int64_t *event_id
= NULL
;
409 struct bt_ctf_trace
*trace
= NULL
;
410 struct bt_ctf_stream_class
*old_stream_class
= NULL
;
411 struct bt_ctf_validation_output validation_output
= { 0 };
412 struct bt_ctf_field_type
*packet_header_type
= NULL
;
413 struct bt_ctf_field_type
*packet_context_type
= NULL
;
414 struct bt_ctf_field_type
*event_header_type
= NULL
;
415 struct bt_ctf_field_type
*stream_event_ctx_type
= NULL
;
416 struct bt_ctf_field_type
*event_context_type
= NULL
;
417 struct bt_ctf_field_type
*event_payload_type
= NULL
;
418 const enum bt_ctf_validation_flag validation_flags
=
419 BT_CTF_VALIDATION_FLAG_EVENT
;
421 if (!stream_class
|| !event_class
) {
422 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
423 "stream-class-addr=%p, event-class-addr=%p",
424 stream_class
, event_class
);
429 BT_LOGD("Adding event class to stream class: "
430 "stream-class-addr=%p, stream-class-name=\"%s\", "
431 "stream-class-id=%" PRId64
", event-class-addr=%p, "
432 "event-class-name=\"%s\", event-class-id=%" PRId64
,
433 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
434 bt_ctf_stream_class_get_id(stream_class
),
436 bt_ctf_event_class_get_name(event_class
),
437 bt_ctf_event_class_get_id(event_class
));
439 trace
= bt_ctf_stream_class_get_trace(stream_class
);
440 if (trace
&& trace
->is_static
) {
445 event_id
= g_new(int64_t, 1);
447 BT_LOGE_STR("Failed to allocate one int64_t.");
452 /* Check for duplicate event classes */
453 struct search_query query
= { .value
= event_class
, .found
= 0 };
454 g_ptr_array_foreach(stream_class
->event_classes
, event_class_exists
,
457 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
462 old_stream_class
= bt_ctf_event_class_get_stream_class(event_class
);
463 if (old_stream_class
) {
464 /* Event class is already associated to a stream class. */
465 BT_LOGW("Event class is already part of another stream class: "
466 "event-class-stream-class-addr=%p, "
467 "event-class-stream-class-name=\"%s\", "
468 "event-class-stream-class-id=%" PRId64
,
470 bt_ctf_stream_class_get_name(old_stream_class
),
471 bt_ctf_stream_class_get_id(old_stream_class
));
478 * If the stream class is associated with a trace, then
479 * both those objects are frozen. Also, this event class
480 * is about to be frozen.
482 * Therefore the event class must be validated here.
483 * The trace and stream class should be valid at this
486 assert(trace
->valid
);
487 assert(stream_class
->valid
);
489 bt_ctf_trace_get_packet_header_type(trace
);
490 packet_context_type
=
491 bt_ctf_stream_class_get_packet_context_type(
494 bt_ctf_stream_class_get_event_header_type(stream_class
);
495 stream_event_ctx_type
=
496 bt_ctf_stream_class_get_event_context_type(
499 bt_ctf_event_class_get_context_type(event_class
);
501 bt_ctf_event_class_get_payload_type(event_class
);
502 ret
= bt_ctf_validate_class_types(
503 trace
->environment
, packet_header_type
,
504 packet_context_type
, event_header_type
,
505 stream_event_ctx_type
, event_context_type
,
506 event_payload_type
, trace
->valid
,
507 stream_class
->valid
, event_class
->valid
,
508 &validation_output
, validation_flags
);
509 BT_PUT(packet_header_type
);
510 BT_PUT(packet_context_type
);
511 BT_PUT(event_header_type
);
512 BT_PUT(stream_event_ctx_type
);
513 BT_PUT(event_context_type
);
514 BT_PUT(event_payload_type
);
518 * This means something went wrong during the
519 * validation process, not that the objects are
522 BT_LOGE("Failed to validate event class: ret=%d", ret
);
526 if ((validation_output
.valid_flags
& validation_flags
) !=
528 /* Invalid event class */
529 BT_LOGW("Invalid trace, stream class, or event class: "
531 validation_output
.valid_flags
);
537 /* Only set an event ID if none was explicitly set before */
538 *event_id
= bt_ctf_event_class_get_id(event_class
);
540 BT_LOGV("Event class has no ID: automatically setting it: "
541 "id=%" PRId64
, stream_class
->next_event_id
);
543 if (bt_ctf_event_class_set_id(event_class
,
544 stream_class
->next_event_id
)) {
545 BT_LOGE("Cannot set event class's ID: id=%" PRId64
,
546 stream_class
->next_event_id
);
550 stream_class
->next_event_id
++;
551 *event_id
= stream_class
->next_event_id
;
554 ret
= bt_ctf_event_class_set_stream_id(event_class
, stream_class
->id
);
556 BT_LOGE("Cannot set event class's stream class ID attribute: ret=%d",
561 bt_object_set_parent(event_class
, stream_class
);
565 * At this point we know that the function will be
566 * successful. Therefore we can replace the event
567 * class's field types with what's in the validation
568 * output structure and mark this event class as valid.
570 bt_ctf_validation_replace_types(NULL
, NULL
, event_class
,
571 &validation_output
, validation_flags
);
572 event_class
->valid
= 1;
575 * Put what was not moved in
576 * bt_ctf_validation_replace_types().
578 bt_ctf_validation_output_put_types(&validation_output
);
581 /* Add to the event classes of the stream class */
582 g_ptr_array_add(stream_class
->event_classes
, event_class
);
583 g_hash_table_insert(stream_class
->event_classes_ht
, event_id
,
587 /* Freeze the event class */
588 bt_ctf_event_class_freeze(event_class
);
590 /* Notifiy listeners of the trace's schema modification. */
592 struct bt_ctf_object obj
= { .object
= event_class
,
593 .type
= BT_CTF_OBJECT_TYPE_EVENT_CLASS
};
595 (void) bt_ctf_trace_object_modification(&obj
, trace
);
598 BT_LOGD("Added event class to stream class: "
599 "stream-class-addr=%p, stream-class-name=\"%s\", "
600 "stream-class-id=%" PRId64
", event-class-addr=%p, "
601 "event-class-name=\"%s\", event-class-id=%" PRId64
,
602 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
603 bt_ctf_stream_class_get_id(stream_class
),
605 bt_ctf_event_class_get_name(event_class
),
606 bt_ctf_event_class_get_id(event_class
));
610 BT_PUT(old_stream_class
);
611 bt_ctf_validation_output_put_types(&validation_output
);
612 assert(!packet_header_type
);
613 assert(!packet_context_type
);
614 assert(!event_header_type
);
615 assert(!stream_event_ctx_type
);
616 assert(!event_context_type
);
617 assert(!event_payload_type
);
623 int64_t bt_ctf_stream_class_get_event_class_count(
624 struct bt_ctf_stream_class
*stream_class
)
629 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
634 ret
= (int64_t) stream_class
->event_classes
->len
;
639 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_index(
640 struct bt_ctf_stream_class
*stream_class
, uint64_t index
)
642 struct bt_ctf_event_class
*event_class
= NULL
;
645 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
649 if (index
>= stream_class
->event_classes
->len
) {
650 BT_LOGW("Invalid parameter: index is out of bounds: "
651 "addr=%p, name=\"%s\", id=%" PRId64
", "
652 "index=%" PRIu64
", count=%u",
653 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
654 bt_ctf_stream_class_get_id(stream_class
),
655 index
, stream_class
->event_classes
->len
);
659 event_class
= g_ptr_array_index(stream_class
->event_classes
, index
);
665 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_id(
666 struct bt_ctf_stream_class
*stream_class
, uint64_t id
)
668 int64_t id_key
= (int64_t) id
;
669 struct bt_ctf_event_class
*event_class
= NULL
;
672 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
677 BT_LOGW("Invalid parameter: invalid event class's ID: "
678 "stream-class-addr=%p, stream-class-name=\"%s\", "
679 "stream-class-id=%" PRId64
", event-class-id=%" PRIu64
,
681 bt_ctf_stream_class_get_name(stream_class
),
682 bt_ctf_stream_class_get_id(stream_class
), id
);
686 event_class
= g_hash_table_lookup(stream_class
->event_classes_ht
,
693 struct bt_ctf_field_type
*bt_ctf_stream_class_get_packet_context_type(
694 struct bt_ctf_stream_class
*stream_class
)
696 struct bt_ctf_field_type
*ret
= NULL
;
699 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
703 bt_get(stream_class
->packet_context_type
);
704 ret
= stream_class
->packet_context_type
;
709 int bt_ctf_stream_class_set_packet_context_type(
710 struct bt_ctf_stream_class
*stream_class
,
711 struct bt_ctf_field_type
*packet_context_type
)
716 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
721 if (stream_class
->frozen
) {
722 BT_LOGW("Invalid parameter: stream class is frozen: "
723 "addr=%p, name=\"%s\", id=%" PRId64
,
724 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
725 bt_ctf_stream_class_get_id(stream_class
));
730 if (packet_context_type
&&
731 bt_ctf_field_type_get_type_id(packet_context_type
) !=
732 BT_CTF_FIELD_TYPE_ID_STRUCT
) {
733 /* A packet context must be a structure. */
734 BT_LOGW("Invalid parameter: stream class's packet context field type must be a structure: "
735 "addr=%p, name=\"%s\", id=%" PRId64
", "
736 "packet-context-ft-addr=%p, packet-context-ft-id=%s",
737 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
738 bt_ctf_stream_class_get_id(stream_class
),
740 bt_ctf_field_type_id_string(
741 bt_ctf_field_type_get_type_id(packet_context_type
)));
746 bt_put(stream_class
->packet_context_type
);
747 bt_get(packet_context_type
);
748 stream_class
->packet_context_type
= packet_context_type
;
749 BT_LOGV("Set stream class's packet context field type: "
750 "addr=%p, name=\"%s\", id=%" PRId64
", "
751 "packet-context-ft-addr=%p",
752 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
753 bt_ctf_stream_class_get_id(stream_class
),
754 packet_context_type
);
760 struct bt_ctf_field_type
*bt_ctf_stream_class_get_event_header_type(
761 struct bt_ctf_stream_class
*stream_class
)
763 struct bt_ctf_field_type
*ret
= NULL
;
766 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
770 if (!stream_class
->event_header_type
) {
771 BT_LOGV("Stream class has no event header field type: "
772 "addr=%p, name=\"%s\", id=%" PRId64
,
773 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
774 bt_ctf_stream_class_get_id(stream_class
));
778 bt_get(stream_class
->event_header_type
);
779 ret
= stream_class
->event_header_type
;
784 int bt_ctf_stream_class_set_event_header_type(
785 struct bt_ctf_stream_class
*stream_class
,
786 struct bt_ctf_field_type
*event_header_type
)
791 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
796 if (stream_class
->frozen
) {
797 BT_LOGW("Invalid parameter: stream class is frozen: "
798 "addr=%p, name=\"%s\", id=%" PRId64
,
799 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
800 bt_ctf_stream_class_get_id(stream_class
));
805 if (event_header_type
&&
806 bt_ctf_field_type_get_type_id(event_header_type
) !=
807 BT_CTF_FIELD_TYPE_ID_STRUCT
) {
808 /* An event header must be a structure. */
809 BT_LOGW("Invalid parameter: stream class's event header field type must be a structure: "
810 "addr=%p, name=\"%s\", id=%" PRId64
", "
811 "event-header-ft-addr=%p, event-header-ft-id=%s",
812 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
813 bt_ctf_stream_class_get_id(stream_class
),
815 bt_ctf_field_type_id_string(
816 bt_ctf_field_type_get_type_id(event_header_type
)));
821 bt_put(stream_class
->event_header_type
);
822 stream_class
->event_header_type
= bt_get(event_header_type
);
823 BT_LOGV("Set stream class's event header field type: "
824 "addr=%p, name=\"%s\", id=%" PRId64
", "
825 "event-header-ft-addr=%p",
826 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
827 bt_ctf_stream_class_get_id(stream_class
),
833 struct bt_ctf_field_type
*bt_ctf_stream_class_get_event_context_type(
834 struct bt_ctf_stream_class
*stream_class
)
836 struct bt_ctf_field_type
*ret
= NULL
;
839 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
843 if (!stream_class
->event_context_type
) {
847 bt_get(stream_class
->event_context_type
);
848 ret
= stream_class
->event_context_type
;
853 int bt_ctf_stream_class_set_event_context_type(
854 struct bt_ctf_stream_class
*stream_class
,
855 struct bt_ctf_field_type
*event_context_type
)
860 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
865 if (stream_class
->frozen
) {
866 BT_LOGW("Invalid parameter: stream class is frozen: "
867 "addr=%p, name=\"%s\", id=%" PRId64
,
868 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
869 bt_ctf_stream_class_get_id(stream_class
));
874 if (event_context_type
&&
875 bt_ctf_field_type_get_type_id(event_context_type
) !=
876 BT_CTF_FIELD_TYPE_ID_STRUCT
) {
877 /* A packet context must be a structure. */
878 BT_LOGW("Invalid parameter: stream class's event context field type must be a structure: "
879 "addr=%p, name=\"%s\", id=%" PRId64
", "
880 "event-context-ft-addr=%p, event-context-ft-id=%s",
881 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
882 bt_ctf_stream_class_get_id(stream_class
),
884 bt_ctf_field_type_id_string(
885 bt_ctf_field_type_get_type_id(event_context_type
)));
890 bt_put(stream_class
->event_context_type
);
891 stream_class
->event_context_type
= bt_get(event_context_type
);
892 BT_LOGV("Set stream class's event context field type: "
893 "addr=%p, name=\"%s\", id=%" PRId64
", "
894 "event-context-ft-addr=%p",
895 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
896 bt_ctf_stream_class_get_id(stream_class
),
902 /* Pre-2.0 CTF writer backward compatibility */
903 void bt_ctf_stream_class_get(struct bt_ctf_stream_class
*stream_class
)
905 bt_get(stream_class
);
908 /* Pre-2.0 CTF writer backward compatibility */
909 void bt_ctf_stream_class_put(struct bt_ctf_stream_class
*stream_class
)
911 bt_put(stream_class
);
915 int64_t get_event_class_count(void *element
)
917 return bt_ctf_stream_class_get_event_class_count(
918 (struct bt_ctf_stream_class
*) element
);
922 void *get_event_class(void *element
, int i
)
924 return bt_ctf_stream_class_get_event_class_by_index(
925 (struct bt_ctf_stream_class
*) element
, i
);
929 int visit_event_class(void *object
, bt_ctf_visitor visitor
,void *data
)
931 struct bt_ctf_object obj
=
933 .type
= BT_CTF_OBJECT_TYPE_EVENT_CLASS
};
935 return visitor(&obj
, data
);
938 int bt_ctf_stream_class_visit(struct bt_ctf_stream_class
*stream_class
,
939 bt_ctf_visitor visitor
, void *data
)
942 struct bt_ctf_object obj
=
943 { .object
= stream_class
,
944 .type
= BT_CTF_OBJECT_TYPE_STREAM_CLASS
};
946 if (!stream_class
|| !visitor
) {
947 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
948 "stream-class-addr=%p, visitor=%p",
949 stream_class
, visitor
);
954 ret
= visitor_helper(&obj
, get_event_class_count
,
956 visit_event_class
, visitor
, data
);
957 BT_LOGV("visitor_helper() returned: ret=%d", ret
);
963 void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class
*stream_class
)
965 if (!stream_class
|| stream_class
->frozen
) {
969 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64
,
970 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
971 bt_ctf_stream_class_get_id(stream_class
));
972 stream_class
->frozen
= 1;
973 bt_ctf_field_type_freeze(stream_class
->event_header_type
);
974 bt_ctf_field_type_freeze(stream_class
->packet_context_type
);
975 bt_ctf_field_type_freeze(stream_class
->event_context_type
);
977 if (stream_class
->clock
) {
978 bt_ctf_clock_class_freeze(stream_class
->clock
->clock_class
);
983 int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class
*stream_class
,
984 struct metadata_context
*context
)
989 BT_LOGD("Serializing stream class's metadata: "
990 "stream-class-addr=%p, stream-class-name=\"%s\", "
991 "stream-class-id=%" PRId64
", metadata-context-addr=%p",
992 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
993 bt_ctf_stream_class_get_id(stream_class
), context
);
994 g_string_assign(context
->field_name
, "");
995 context
->current_indentation_level
= 1;
996 if (!stream_class
->id_set
) {
997 BT_LOGW_STR("Stream class's ID is not set.");
1002 g_string_append_printf(context
->string
,
1003 "stream {\n\tid = %" PRId64
";\n", stream_class
->id
);
1004 if (stream_class
->event_header_type
) {
1005 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
1006 g_string_append(context
->string
, "\tevent.header := ");
1007 ret
= bt_ctf_field_type_serialize(stream_class
->event_header_type
,
1010 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
1014 g_string_append(context
->string
, ";");
1018 if (stream_class
->packet_context_type
) {
1019 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
1020 g_string_append(context
->string
, "\n\n\tpacket.context := ");
1021 ret
= bt_ctf_field_type_serialize(stream_class
->packet_context_type
,
1024 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
1028 g_string_append(context
->string
, ";");
1031 if (stream_class
->event_context_type
) {
1032 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
1033 g_string_append(context
->string
, "\n\n\tevent.context := ");
1034 ret
= bt_ctf_field_type_serialize(
1035 stream_class
->event_context_type
, context
);
1037 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
1041 g_string_append(context
->string
, ";");
1044 g_string_append(context
->string
, "\n};\n\n");
1046 for (i
= 0; i
< stream_class
->event_classes
->len
; i
++) {
1047 struct bt_ctf_event_class
*event_class
=
1048 stream_class
->event_classes
->pdata
[i
];
1050 ret
= bt_ctf_event_class_serialize(event_class
, context
);
1052 BT_LOGW("Cannot serialize event class's metadata: "
1053 "event-class-addr=%p, event-class-name=\"%s\", "
1054 "event-class-id=%" PRId64
,
1056 bt_ctf_event_class_get_name(event_class
),
1057 bt_ctf_event_class_get_id(event_class
));
1062 context
->current_indentation_level
= 0;
1067 void bt_ctf_stream_class_destroy(struct bt_object
*obj
)
1069 struct bt_ctf_stream_class
*stream_class
;
1071 stream_class
= container_of(obj
, struct bt_ctf_stream_class
, base
);
1072 BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64
,
1073 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
1074 bt_ctf_stream_class_get_id(stream_class
));
1075 bt_put(stream_class
->clock
);
1077 if (stream_class
->event_classes_ht
) {
1078 g_hash_table_destroy(stream_class
->event_classes_ht
);
1080 if (stream_class
->event_classes
) {
1081 BT_LOGD_STR("Destroying event classes.");
1082 g_ptr_array_free(stream_class
->event_classes
, TRUE
);
1085 if (stream_class
->name
) {
1086 g_string_free(stream_class
->name
, TRUE
);
1089 BT_LOGD_STR("Putting event header field type.");
1090 bt_put(stream_class
->event_header_type
);
1091 BT_LOGD_STR("Putting packet context field type.");
1092 bt_put(stream_class
->packet_context_type
);
1093 BT_LOGD_STR("Putting event context field type.");
1094 bt_put(stream_class
->event_context_type
);
1095 g_free(stream_class
);
1099 int init_event_header(struct bt_ctf_stream_class
*stream_class
)
1102 struct bt_ctf_field_type
*event_header_type
=
1103 bt_ctf_field_type_structure_create();
1104 struct bt_ctf_field_type
*_uint32_t
=
1105 get_field_type(FIELD_TYPE_ALIAS_UINT32_T
);
1106 struct bt_ctf_field_type
*_uint64_t
=
1107 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
1109 if (!event_header_type
) {
1110 BT_LOGE_STR("Cannot create empty structure field type.");
1115 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
1118 BT_LOGE_STR("Cannot add `id` field to event header field type.");
1122 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
1123 _uint64_t
, "timestamp");
1125 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
1129 BT_MOVE(stream_class
->event_header_type
, event_header_type
);
1132 bt_put(event_header_type
);
1141 int init_packet_context(struct bt_ctf_stream_class
*stream_class
)
1144 struct bt_ctf_field_type
*packet_context_type
=
1145 bt_ctf_field_type_structure_create();
1146 struct bt_ctf_field_type
*_uint64_t
=
1147 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
1148 struct bt_ctf_field_type
*ts_begin_end_uint64_t
;
1150 if (!packet_context_type
) {
1151 BT_LOGE_STR("Cannot create empty structure field type.");
1156 ts_begin_end_uint64_t
= bt_ctf_field_type_copy(_uint64_t
);
1157 if (!ts_begin_end_uint64_t
) {
1158 BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
1164 * We create a stream packet context as proposed in the CTF
1167 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1168 ts_begin_end_uint64_t
, "timestamp_begin");
1170 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
1174 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1175 ts_begin_end_uint64_t
, "timestamp_end");
1177 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
1181 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1182 _uint64_t
, "content_size");
1184 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
1188 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1189 _uint64_t
, "packet_size");
1191 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
1195 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1196 _uint64_t
, "events_discarded");
1198 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
1202 BT_MOVE(stream_class
->packet_context_type
, packet_context_type
);
1205 bt_put(packet_context_type
);
1210 bt_put(ts_begin_end_uint64_t
);
1215 int try_map_clock_class(struct bt_ctf_stream_class
*stream_class
,
1216 struct bt_ctf_field_type
*ft
)
1218 struct bt_ctf_clock_class
*mapped_clock_class
= NULL
;
1222 /* Field does not exist: not an error */
1226 assert(bt_ctf_field_type_is_integer(ft
));
1227 mapped_clock_class
=
1228 bt_ctf_field_type_integer_get_mapped_clock_class(ft
);
1229 if (!mapped_clock_class
) {
1230 if (!stream_class
->clock
) {
1231 BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
1232 "stream-class-addr=%p, stream-class-name=\"%s\", "
1233 "stream-class-id=%" PRId64
", ft-addr=%p",
1234 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
1235 bt_ctf_stream_class_get_id(stream_class
), ft
);
1240 ret
= bt_ctf_field_type_integer_set_mapped_clock_class_no_check(
1241 ft
, stream_class
->clock
->clock_class
);
1243 BT_LOGW("Cannot set field type's mapped clock class: "
1244 "stream-class-addr=%p, stream-class-name=\"%s\", "
1245 "stream-class-id=%" PRId64
", ft-addr=%p",
1246 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
1247 bt_ctf_stream_class_get_id(stream_class
), ft
);
1251 BT_LOGV("Automatically mapped field type to stream class's clock class: "
1252 "stream-class-addr=%p, stream-class-name=\"%s\", "
1253 "stream-class-id=%" PRId64
", ft-addr=%p",
1254 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
1255 bt_ctf_stream_class_get_id(stream_class
), ft
);
1259 bt_put(mapped_clock_class
);
1264 int bt_ctf_stream_class_map_clock_class(
1265 struct bt_ctf_stream_class
*stream_class
,
1266 struct bt_ctf_field_type
*packet_context_type
,
1267 struct bt_ctf_field_type
*event_header_type
)
1269 struct bt_ctf_field_type
*ft
= NULL
;
1272 assert(stream_class
);
1274 if (packet_context_type
) {
1275 ft
= bt_ctf_field_type_structure_get_field_type_by_name(
1276 packet_context_type
, "timestamp_begin");
1277 if (try_map_clock_class(stream_class
, ft
)) {
1278 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
1284 ft
= bt_ctf_field_type_structure_get_field_type_by_name(
1285 packet_context_type
, "timestamp_end");
1286 if (try_map_clock_class(stream_class
, ft
)) {
1287 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
1295 if (event_header_type
) {
1296 ft
= bt_ctf_field_type_structure_get_field_type_by_name(
1297 event_header_type
, "timestamp");
1298 if (try_map_clock_class(stream_class
, ft
)) {
1299 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");