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 int bt_ctf_stream_class_set_id_no_check(
288 struct bt_ctf_stream_class
*stream_class
, int64_t id
)
290 _bt_ctf_stream_class_set_id(stream_class
, id
);
294 int bt_ctf_stream_class_set_id(struct bt_ctf_stream_class
*stream_class
,
298 int64_t id
= (int64_t) id_param
;
301 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
306 if (stream_class
->frozen
) {
307 BT_LOGW("Invalid parameter: stream class is frozen: "
308 "addr=%p, name=\"%s\", id=%" PRId64
,
309 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
310 bt_ctf_stream_class_get_id(stream_class
));
316 BT_LOGW("Invalid parameter: invalid stream class's ID: "
317 "stream-class-addr=%p, stream-class-name=\"%s\", "
318 "stream-class-id=%" PRId64
", id=%" PRIu64
,
319 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
320 bt_ctf_stream_class_get_id(stream_class
),
326 ret
= bt_ctf_stream_class_set_id_no_check(stream_class
, id
);
328 BT_LOGV("Set stream class's ID: "
329 "addr=%p, name=\"%s\", id=%" PRId64
,
330 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
331 bt_ctf_stream_class_get_id(stream_class
));
338 void event_class_exists(gpointer element
, gpointer query
)
340 struct bt_ctf_event_class
*event_class_a
= element
;
341 struct search_query
*search_query
= query
;
342 struct bt_ctf_event_class
*event_class_b
= search_query
->value
;
345 if (search_query
->value
== element
) {
346 search_query
->found
= 1;
351 * Two event classes cannot share the same ID in a given
354 id_a
= bt_ctf_event_class_get_id(event_class_a
);
355 id_b
= bt_ctf_event_class_get_id(event_class_b
);
357 if (id_a
< 0 || id_b
< 0) {
358 /* at least one ID is not set: will be automatically set later */
363 BT_LOGW("Event class with this ID already exists in the stream class: "
364 "id=%" PRId64
", name=\"%s\"",
365 id_a
, bt_ctf_event_class_get_name(event_class_a
));
366 search_query
->found
= 1;
374 int bt_ctf_stream_class_add_event_class(
375 struct bt_ctf_stream_class
*stream_class
,
376 struct bt_ctf_event_class
*event_class
)
379 int64_t *event_id
= NULL
;
380 struct bt_ctf_trace
*trace
= NULL
;
381 struct bt_ctf_stream_class
*old_stream_class
= NULL
;
382 struct bt_ctf_validation_output validation_output
= { 0 };
383 struct bt_ctf_field_type
*packet_header_type
= NULL
;
384 struct bt_ctf_field_type
*packet_context_type
= NULL
;
385 struct bt_ctf_field_type
*event_header_type
= NULL
;
386 struct bt_ctf_field_type
*stream_event_ctx_type
= NULL
;
387 struct bt_ctf_field_type
*event_context_type
= NULL
;
388 struct bt_ctf_field_type
*event_payload_type
= NULL
;
389 const enum bt_ctf_validation_flag validation_flags
=
390 BT_CTF_VALIDATION_FLAG_EVENT
;
392 if (!stream_class
|| !event_class
) {
393 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
394 "stream-class-addr=%p, event-class-addr=%p",
395 stream_class
, event_class
);
400 BT_LOGD("Adding event class to stream class: "
401 "stream-class-addr=%p, stream-class-name=\"%s\", "
402 "stream-class-id=%" PRId64
", event-class-addr=%p, "
403 "event-class-name=\"%s\", event-class-id=%" PRId64
,
404 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
405 bt_ctf_stream_class_get_id(stream_class
),
407 bt_ctf_event_class_get_name(event_class
),
408 bt_ctf_event_class_get_id(event_class
));
410 trace
= bt_ctf_stream_class_get_trace(stream_class
);
411 if (trace
&& trace
->is_static
) {
416 event_id
= g_new(int64_t, 1);
418 BT_LOGE_STR("Failed to allocate one int64_t.");
423 /* Check for duplicate event classes */
424 struct search_query query
= { .value
= event_class
, .found
= 0 };
425 g_ptr_array_foreach(stream_class
->event_classes
, event_class_exists
,
428 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
433 old_stream_class
= bt_ctf_event_class_get_stream_class(event_class
);
434 if (old_stream_class
) {
435 /* Event class is already associated to a stream class. */
436 BT_LOGW("Event class is already part of another stream class: "
437 "event-class-stream-class-addr=%p, "
438 "event-class-stream-class-name=\"%s\", "
439 "event-class-stream-class-id=%" PRId64
,
441 bt_ctf_stream_class_get_name(old_stream_class
),
442 bt_ctf_stream_class_get_id(old_stream_class
));
449 * If the stream class is associated with a trace, then
450 * both those objects are frozen. Also, this event class
451 * is about to be frozen.
453 * Therefore the event class must be validated here.
454 * The trace and stream class should be valid at this
457 assert(trace
->valid
);
458 assert(stream_class
->valid
);
460 bt_ctf_trace_get_packet_header_type(trace
);
461 packet_context_type
=
462 bt_ctf_stream_class_get_packet_context_type(
465 bt_ctf_stream_class_get_event_header_type(stream_class
);
466 stream_event_ctx_type
=
467 bt_ctf_stream_class_get_event_context_type(
470 bt_ctf_event_class_get_context_type(event_class
);
472 bt_ctf_event_class_get_payload_type(event_class
);
473 ret
= bt_ctf_validate_class_types(
474 trace
->environment
, packet_header_type
,
475 packet_context_type
, event_header_type
,
476 stream_event_ctx_type
, event_context_type
,
477 event_payload_type
, trace
->valid
,
478 stream_class
->valid
, event_class
->valid
,
479 &validation_output
, validation_flags
);
480 BT_PUT(packet_header_type
);
481 BT_PUT(packet_context_type
);
482 BT_PUT(event_header_type
);
483 BT_PUT(stream_event_ctx_type
);
484 BT_PUT(event_context_type
);
485 BT_PUT(event_payload_type
);
489 * This means something went wrong during the
490 * validation process, not that the objects are
493 BT_LOGE("Failed to validate event class: ret=%d", ret
);
497 if ((validation_output
.valid_flags
& validation_flags
) !=
499 /* Invalid event class */
500 BT_LOGW("Invalid trace, stream class, or event class: "
502 validation_output
.valid_flags
);
508 /* Only set an event ID if none was explicitly set before */
509 *event_id
= bt_ctf_event_class_get_id(event_class
);
511 BT_LOGV("Event class has no ID: automatically setting it: "
512 "id=%" PRId64
, stream_class
->next_event_id
);
514 if (bt_ctf_event_class_set_id(event_class
,
515 stream_class
->next_event_id
)) {
516 BT_LOGE("Cannot set event class's ID: id=%" PRId64
,
517 stream_class
->next_event_id
);
521 stream_class
->next_event_id
++;
522 *event_id
= stream_class
->next_event_id
;
525 bt_object_set_parent(event_class
, stream_class
);
529 * At this point we know that the function will be
530 * successful. Therefore we can replace the event
531 * class's field types with what's in the validation
532 * output structure and mark this event class as valid.
534 bt_ctf_validation_replace_types(NULL
, NULL
, event_class
,
535 &validation_output
, validation_flags
);
536 event_class
->valid
= 1;
539 * Put what was not moved in
540 * bt_ctf_validation_replace_types().
542 bt_ctf_validation_output_put_types(&validation_output
);
545 /* Add to the event classes of the stream class */
546 g_ptr_array_add(stream_class
->event_classes
, event_class
);
547 g_hash_table_insert(stream_class
->event_classes_ht
, event_id
,
551 /* Freeze the event class */
552 bt_ctf_event_class_freeze(event_class
);
554 /* Notifiy listeners of the trace's schema modification. */
556 struct bt_ctf_object obj
= { .object
= event_class
,
557 .type
= BT_CTF_OBJECT_TYPE_EVENT_CLASS
};
559 (void) bt_ctf_trace_object_modification(&obj
, trace
);
562 BT_LOGD("Added event class to stream class: "
563 "stream-class-addr=%p, stream-class-name=\"%s\", "
564 "stream-class-id=%" PRId64
", event-class-addr=%p, "
565 "event-class-name=\"%s\", event-class-id=%" PRId64
,
566 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
567 bt_ctf_stream_class_get_id(stream_class
),
569 bt_ctf_event_class_get_name(event_class
),
570 bt_ctf_event_class_get_id(event_class
));
574 BT_PUT(old_stream_class
);
575 bt_ctf_validation_output_put_types(&validation_output
);
576 assert(!packet_header_type
);
577 assert(!packet_context_type
);
578 assert(!event_header_type
);
579 assert(!stream_event_ctx_type
);
580 assert(!event_context_type
);
581 assert(!event_payload_type
);
587 int64_t bt_ctf_stream_class_get_event_class_count(
588 struct bt_ctf_stream_class
*stream_class
)
593 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
598 ret
= (int64_t) stream_class
->event_classes
->len
;
603 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_index(
604 struct bt_ctf_stream_class
*stream_class
, uint64_t index
)
606 struct bt_ctf_event_class
*event_class
= NULL
;
609 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
613 if (index
>= stream_class
->event_classes
->len
) {
614 BT_LOGW("Invalid parameter: index is out of bounds: "
615 "addr=%p, name=\"%s\", id=%" PRId64
", "
616 "index=%" PRIu64
", count=%u",
617 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
618 bt_ctf_stream_class_get_id(stream_class
),
619 index
, stream_class
->event_classes
->len
);
623 event_class
= g_ptr_array_index(stream_class
->event_classes
, index
);
629 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_id(
630 struct bt_ctf_stream_class
*stream_class
, uint64_t id
)
632 int64_t id_key
= (int64_t) id
;
633 struct bt_ctf_event_class
*event_class
= NULL
;
636 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
641 BT_LOGW("Invalid parameter: invalid event class's ID: "
642 "stream-class-addr=%p, stream-class-name=\"%s\", "
643 "stream-class-id=%" PRId64
", event-class-id=%" PRIu64
,
645 bt_ctf_stream_class_get_name(stream_class
),
646 bt_ctf_stream_class_get_id(stream_class
), id
);
650 event_class
= g_hash_table_lookup(stream_class
->event_classes_ht
,
657 struct bt_ctf_field_type
*bt_ctf_stream_class_get_packet_context_type(
658 struct bt_ctf_stream_class
*stream_class
)
660 struct bt_ctf_field_type
*ret
= NULL
;
663 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
667 bt_get(stream_class
->packet_context_type
);
668 ret
= stream_class
->packet_context_type
;
673 int bt_ctf_stream_class_set_packet_context_type(
674 struct bt_ctf_stream_class
*stream_class
,
675 struct bt_ctf_field_type
*packet_context_type
)
680 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
685 if (stream_class
->frozen
) {
686 BT_LOGW("Invalid parameter: stream class is frozen: "
687 "addr=%p, name=\"%s\", id=%" PRId64
,
688 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
689 bt_ctf_stream_class_get_id(stream_class
));
694 if (packet_context_type
&&
695 bt_ctf_field_type_get_type_id(packet_context_type
) !=
696 BT_CTF_FIELD_TYPE_ID_STRUCT
) {
697 /* A packet context must be a structure. */
698 BT_LOGW("Invalid parameter: stream class's packet context field type must be a structure: "
699 "addr=%p, name=\"%s\", id=%" PRId64
", "
700 "packet-context-ft-addr=%p, packet-context-ft-id=%s",
701 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
702 bt_ctf_stream_class_get_id(stream_class
),
704 bt_ctf_field_type_id_string(
705 bt_ctf_field_type_get_type_id(packet_context_type
)));
710 bt_put(stream_class
->packet_context_type
);
711 bt_get(packet_context_type
);
712 stream_class
->packet_context_type
= packet_context_type
;
713 BT_LOGV("Set stream class's packet context field type: "
714 "addr=%p, name=\"%s\", id=%" PRId64
", "
715 "packet-context-ft-addr=%p",
716 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
717 bt_ctf_stream_class_get_id(stream_class
),
718 packet_context_type
);
724 struct bt_ctf_field_type
*bt_ctf_stream_class_get_event_header_type(
725 struct bt_ctf_stream_class
*stream_class
)
727 struct bt_ctf_field_type
*ret
= NULL
;
730 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
734 if (!stream_class
->event_header_type
) {
735 BT_LOGV("Stream class has no event header field type: "
736 "addr=%p, name=\"%s\", id=%" PRId64
,
737 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
738 bt_ctf_stream_class_get_id(stream_class
));
742 bt_get(stream_class
->event_header_type
);
743 ret
= stream_class
->event_header_type
;
748 int bt_ctf_stream_class_set_event_header_type(
749 struct bt_ctf_stream_class
*stream_class
,
750 struct bt_ctf_field_type
*event_header_type
)
755 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
760 if (stream_class
->frozen
) {
761 BT_LOGW("Invalid parameter: stream class is frozen: "
762 "addr=%p, name=\"%s\", id=%" PRId64
,
763 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
764 bt_ctf_stream_class_get_id(stream_class
));
769 if (event_header_type
&&
770 bt_ctf_field_type_get_type_id(event_header_type
) !=
771 BT_CTF_FIELD_TYPE_ID_STRUCT
) {
772 /* An event header must be a structure. */
773 BT_LOGW("Invalid parameter: stream class's event header field type must be a structure: "
774 "addr=%p, name=\"%s\", id=%" PRId64
", "
775 "event-header-ft-addr=%p, event-header-ft-id=%s",
776 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
777 bt_ctf_stream_class_get_id(stream_class
),
779 bt_ctf_field_type_id_string(
780 bt_ctf_field_type_get_type_id(event_header_type
)));
785 bt_put(stream_class
->event_header_type
);
786 stream_class
->event_header_type
= bt_get(event_header_type
);
787 BT_LOGV("Set stream class's event header field type: "
788 "addr=%p, name=\"%s\", id=%" PRId64
", "
789 "event-header-ft-addr=%p",
790 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
791 bt_ctf_stream_class_get_id(stream_class
),
797 struct bt_ctf_field_type
*bt_ctf_stream_class_get_event_context_type(
798 struct bt_ctf_stream_class
*stream_class
)
800 struct bt_ctf_field_type
*ret
= NULL
;
803 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
807 if (!stream_class
->event_context_type
) {
811 bt_get(stream_class
->event_context_type
);
812 ret
= stream_class
->event_context_type
;
817 int bt_ctf_stream_class_set_event_context_type(
818 struct bt_ctf_stream_class
*stream_class
,
819 struct bt_ctf_field_type
*event_context_type
)
824 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
829 if (stream_class
->frozen
) {
830 BT_LOGW("Invalid parameter: stream class is frozen: "
831 "addr=%p, name=\"%s\", id=%" PRId64
,
832 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
833 bt_ctf_stream_class_get_id(stream_class
));
838 if (event_context_type
&&
839 bt_ctf_field_type_get_type_id(event_context_type
) !=
840 BT_CTF_FIELD_TYPE_ID_STRUCT
) {
841 /* A packet context must be a structure. */
842 BT_LOGW("Invalid parameter: stream class's event context field type must be a structure: "
843 "addr=%p, name=\"%s\", id=%" PRId64
", "
844 "event-context-ft-addr=%p, event-context-ft-id=%s",
845 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
846 bt_ctf_stream_class_get_id(stream_class
),
848 bt_ctf_field_type_id_string(
849 bt_ctf_field_type_get_type_id(event_context_type
)));
854 bt_put(stream_class
->event_context_type
);
855 stream_class
->event_context_type
= bt_get(event_context_type
);
856 BT_LOGV("Set stream class's event context field type: "
857 "addr=%p, name=\"%s\", id=%" PRId64
", "
858 "event-context-ft-addr=%p",
859 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
860 bt_ctf_stream_class_get_id(stream_class
),
866 /* Pre-2.0 CTF writer backward compatibility */
867 void bt_ctf_stream_class_get(struct bt_ctf_stream_class
*stream_class
)
869 bt_get(stream_class
);
872 /* Pre-2.0 CTF writer backward compatibility */
873 void bt_ctf_stream_class_put(struct bt_ctf_stream_class
*stream_class
)
875 bt_put(stream_class
);
879 int64_t get_event_class_count(void *element
)
881 return bt_ctf_stream_class_get_event_class_count(
882 (struct bt_ctf_stream_class
*) element
);
886 void *get_event_class(void *element
, int i
)
888 return bt_ctf_stream_class_get_event_class_by_index(
889 (struct bt_ctf_stream_class
*) element
, i
);
893 int visit_event_class(void *object
, bt_ctf_visitor visitor
,void *data
)
895 struct bt_ctf_object obj
=
897 .type
= BT_CTF_OBJECT_TYPE_EVENT_CLASS
};
899 return visitor(&obj
, data
);
902 int bt_ctf_stream_class_visit(struct bt_ctf_stream_class
*stream_class
,
903 bt_ctf_visitor visitor
, void *data
)
906 struct bt_ctf_object obj
=
907 { .object
= stream_class
,
908 .type
= BT_CTF_OBJECT_TYPE_STREAM_CLASS
};
910 if (!stream_class
|| !visitor
) {
911 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
912 "stream-class-addr=%p, visitor=%p",
913 stream_class
, visitor
);
918 ret
= visitor_helper(&obj
, get_event_class_count
,
920 visit_event_class
, visitor
, data
);
921 BT_LOGV("visitor_helper() returned: ret=%d", ret
);
927 void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class
*stream_class
)
929 if (!stream_class
|| stream_class
->frozen
) {
933 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64
,
934 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
935 bt_ctf_stream_class_get_id(stream_class
));
936 stream_class
->frozen
= 1;
937 bt_ctf_field_type_freeze(stream_class
->event_header_type
);
938 bt_ctf_field_type_freeze(stream_class
->packet_context_type
);
939 bt_ctf_field_type_freeze(stream_class
->event_context_type
);
941 if (stream_class
->clock
) {
942 bt_ctf_clock_class_freeze(stream_class
->clock
->clock_class
);
947 int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class
*stream_class
,
948 struct metadata_context
*context
)
952 struct bt_ctf_trace
*trace
;
953 struct bt_ctf_field_type
*packet_header_type
= NULL
;
955 BT_LOGD("Serializing stream class's metadata: "
956 "stream-class-addr=%p, stream-class-name=\"%s\", "
957 "stream-class-id=%" PRId64
", metadata-context-addr=%p",
958 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
959 bt_ctf_stream_class_get_id(stream_class
), context
);
960 g_string_assign(context
->field_name
, "");
961 context
->current_indentation_level
= 1;
962 if (!stream_class
->id_set
) {
963 BT_LOGW_STR("Stream class's ID is not set.");
968 g_string_append(context
->string
, "stream {\n");
971 * The reference to the trace is only borrowed since the
972 * serialization of the stream class might have been triggered
973 * by the trace's destruction. In such a case, the trace's
974 * reference count would, unexepectedly, go through the sequence
975 * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
978 trace
= bt_ctf_stream_class_borrow_trace(stream_class
);
980 packet_header_type
= bt_ctf_trace_get_packet_header_type(trace
);
982 if (packet_header_type
) {
983 struct bt_ctf_field_type
*stream_id_type
;
986 bt_ctf_field_type_structure_get_field_type_by_name(
987 packet_header_type
, "stream_id");
988 if (stream_id_type
) {
990 * Only set the stream's id if the trace's packet header
991 * contains a stream_id field. This field is only
992 * needed if the trace contains only one stream
995 g_string_append_printf(context
->string
,
996 "\tid = %" PRId64
";\n", stream_class
->id
);
998 bt_put(stream_id_type
);
1000 if (stream_class
->event_header_type
) {
1001 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
1002 g_string_append(context
->string
, "\tevent.header := ");
1003 ret
= bt_ctf_field_type_serialize(stream_class
->event_header_type
,
1006 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
1010 g_string_append(context
->string
, ";");
1014 if (stream_class
->packet_context_type
) {
1015 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
1016 g_string_append(context
->string
, "\n\n\tpacket.context := ");
1017 ret
= bt_ctf_field_type_serialize(stream_class
->packet_context_type
,
1020 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
1024 g_string_append(context
->string
, ";");
1027 if (stream_class
->event_context_type
) {
1028 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
1029 g_string_append(context
->string
, "\n\n\tevent.context := ");
1030 ret
= bt_ctf_field_type_serialize(
1031 stream_class
->event_context_type
, context
);
1033 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
1037 g_string_append(context
->string
, ";");
1040 g_string_append(context
->string
, "\n};\n\n");
1042 for (i
= 0; i
< stream_class
->event_classes
->len
; i
++) {
1043 struct bt_ctf_event_class
*event_class
=
1044 stream_class
->event_classes
->pdata
[i
];
1046 ret
= bt_ctf_event_class_serialize(event_class
, context
);
1048 BT_LOGW("Cannot serialize event class's metadata: "
1049 "event-class-addr=%p, event-class-name=\"%s\", "
1050 "event-class-id=%" PRId64
,
1052 bt_ctf_event_class_get_name(event_class
),
1053 bt_ctf_event_class_get_id(event_class
));
1058 bt_put(packet_header_type
);
1059 context
->current_indentation_level
= 0;
1064 void bt_ctf_stream_class_destroy(struct bt_object
*obj
)
1066 struct bt_ctf_stream_class
*stream_class
;
1068 stream_class
= container_of(obj
, struct bt_ctf_stream_class
, base
);
1069 BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64
,
1070 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
1071 bt_ctf_stream_class_get_id(stream_class
));
1072 bt_put(stream_class
->clock
);
1074 if (stream_class
->event_classes_ht
) {
1075 g_hash_table_destroy(stream_class
->event_classes_ht
);
1077 if (stream_class
->event_classes
) {
1078 BT_LOGD_STR("Destroying event classes.");
1079 g_ptr_array_free(stream_class
->event_classes
, TRUE
);
1082 if (stream_class
->name
) {
1083 g_string_free(stream_class
->name
, TRUE
);
1086 BT_LOGD_STR("Putting event header field type.");
1087 bt_put(stream_class
->event_header_type
);
1088 BT_LOGD_STR("Putting packet context field type.");
1089 bt_put(stream_class
->packet_context_type
);
1090 BT_LOGD_STR("Putting event context field type.");
1091 bt_put(stream_class
->event_context_type
);
1092 g_free(stream_class
);
1096 int init_event_header(struct bt_ctf_stream_class
*stream_class
)
1099 struct bt_ctf_field_type
*event_header_type
=
1100 bt_ctf_field_type_structure_create();
1101 struct bt_ctf_field_type
*_uint32_t
=
1102 get_field_type(FIELD_TYPE_ALIAS_UINT32_T
);
1103 struct bt_ctf_field_type
*_uint64_t
=
1104 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
1106 if (!event_header_type
) {
1107 BT_LOGE_STR("Cannot create empty structure field type.");
1112 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
1115 BT_LOGE_STR("Cannot add `id` field to event header field type.");
1119 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
1120 _uint64_t
, "timestamp");
1122 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
1126 BT_MOVE(stream_class
->event_header_type
, event_header_type
);
1129 bt_put(event_header_type
);
1138 int init_packet_context(struct bt_ctf_stream_class
*stream_class
)
1141 struct bt_ctf_field_type
*packet_context_type
=
1142 bt_ctf_field_type_structure_create();
1143 struct bt_ctf_field_type
*_uint64_t
=
1144 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
1145 struct bt_ctf_field_type
*ts_begin_end_uint64_t
;
1147 if (!packet_context_type
) {
1148 BT_LOGE_STR("Cannot create empty structure field type.");
1153 ts_begin_end_uint64_t
= bt_ctf_field_type_copy(_uint64_t
);
1154 if (!ts_begin_end_uint64_t
) {
1155 BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
1161 * We create a stream packet context as proposed in the CTF
1164 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1165 ts_begin_end_uint64_t
, "timestamp_begin");
1167 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
1171 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1172 ts_begin_end_uint64_t
, "timestamp_end");
1174 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
1178 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1179 _uint64_t
, "content_size");
1181 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
1185 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1186 _uint64_t
, "packet_size");
1188 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
1192 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
1193 _uint64_t
, "events_discarded");
1195 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
1199 BT_MOVE(stream_class
->packet_context_type
, packet_context_type
);
1202 bt_put(packet_context_type
);
1207 bt_put(ts_begin_end_uint64_t
);
1212 int try_map_clock_class(struct bt_ctf_stream_class
*stream_class
,
1213 struct bt_ctf_field_type
*ft
)
1215 struct bt_ctf_clock_class
*mapped_clock_class
= NULL
;
1219 /* Field does not exist: not an error */
1223 assert(bt_ctf_field_type_is_integer(ft
));
1224 mapped_clock_class
=
1225 bt_ctf_field_type_integer_get_mapped_clock_class(ft
);
1226 if (!mapped_clock_class
) {
1227 if (!stream_class
->clock
) {
1228 BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
1229 "stream-class-addr=%p, stream-class-name=\"%s\", "
1230 "stream-class-id=%" PRId64
", ft-addr=%p",
1231 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
1232 bt_ctf_stream_class_get_id(stream_class
), ft
);
1237 ret
= bt_ctf_field_type_integer_set_mapped_clock_class_no_check(
1238 ft
, stream_class
->clock
->clock_class
);
1240 BT_LOGW("Cannot set field type's mapped clock class: "
1241 "stream-class-addr=%p, stream-class-name=\"%s\", "
1242 "stream-class-id=%" PRId64
", ft-addr=%p",
1243 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
1244 bt_ctf_stream_class_get_id(stream_class
), ft
);
1248 BT_LOGV("Automatically mapped field type to stream class's clock class: "
1249 "stream-class-addr=%p, stream-class-name=\"%s\", "
1250 "stream-class-id=%" PRId64
", ft-addr=%p",
1251 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
1252 bt_ctf_stream_class_get_id(stream_class
), ft
);
1256 bt_put(mapped_clock_class
);
1261 int bt_ctf_stream_class_map_clock_class(
1262 struct bt_ctf_stream_class
*stream_class
,
1263 struct bt_ctf_field_type
*packet_context_type
,
1264 struct bt_ctf_field_type
*event_header_type
)
1266 struct bt_ctf_field_type
*ft
= NULL
;
1269 assert(stream_class
);
1271 if (packet_context_type
) {
1272 ft
= bt_ctf_field_type_structure_get_field_type_by_name(
1273 packet_context_type
, "timestamp_begin");
1274 if (try_map_clock_class(stream_class
, ft
)) {
1275 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
1281 ft
= bt_ctf_field_type_structure_get_field_type_by_name(
1282 packet_context_type
, "timestamp_end");
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_end` field's mapped clock class.");
1292 if (event_header_type
) {
1293 ft
= bt_ctf_field_type_structure_get_field_type_by_name(
1294 event_header_type
, "timestamp");
1295 if (try_map_clock_class(stream_class
, ft
)) {
1296 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");