2 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 #define BT_LOG_TAG "CTF-WRITER-STREAM-CLASS"
25 #include <babeltrace2/lib-logging-internal.h>
27 #include <babeltrace2/assert-pre-internal.h>
28 #include <babeltrace2/align-internal.h>
29 #include <babeltrace2/assert-internal.h>
30 #include <babeltrace2/compiler-internal.h>
31 #include <babeltrace2/ctf-writer/clock-class-internal.h>
32 #include <babeltrace2/ctf-writer/event-class-internal.h>
33 #include <babeltrace2/ctf-writer/event-internal.h>
34 #include <babeltrace2/ctf-writer/event.h>
35 #include <babeltrace2/ctf-writer/field-types-internal.h>
36 #include <babeltrace2/ctf-writer/field-wrapper-internal.h>
37 #include <babeltrace2/ctf-writer/fields-internal.h>
38 #include <babeltrace2/ctf-writer/stream-class-internal.h>
39 #include <babeltrace2/ctf-writer/trace.h>
40 #include <babeltrace2/ctf-writer/utils-internal.h>
41 #include <babeltrace2/ctf-writer/utils.h>
42 #include <babeltrace2/ctf-writer/validation-internal.h>
43 #include <babeltrace2/ctf-writer/visitor-internal.h>
44 #include <babeltrace2/ctf-writer/writer-internal.h>
45 #include <babeltrace2/endian-internal.h>
46 #include <babeltrace2/ctf-writer/object.h>
52 int bt_ctf_stream_class_common_initialize(struct bt_ctf_stream_class_common
*stream_class
,
53 const char *name
, bt_ctf_object_release_func release_func
)
55 BT_LOGD("Initializing common stream class object: name=\"%s\"", name
);
57 bt_ctf_object_init_shared_with_parent(&stream_class
->base
, release_func
);
58 stream_class
->name
= g_string_new(name
);
59 stream_class
->event_classes
= g_ptr_array_new_with_free_func(
60 (GDestroyNotify
) bt_ctf_object_try_spec_release
);
61 if (!stream_class
->event_classes
) {
62 BT_LOGE_STR("Failed to allocate a GPtrArray.");
66 stream_class
->event_classes_ht
= g_hash_table_new_full(g_int64_hash
,
67 g_int64_equal
, g_free
, NULL
);
68 if (!stream_class
->event_classes_ht
) {
69 BT_LOGE_STR("Failed to allocate a GHashTable.");
73 BT_LOGD("Initialized common stream class object: addr=%p, name=\"%s\"",
82 void bt_ctf_stream_class_common_finalize(struct bt_ctf_stream_class_common
*stream_class
)
84 BT_LOGD("Finalizing common stream class: addr=%p, name=\"%s\", id=%" PRId64
,
85 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
86 bt_ctf_stream_class_common_get_id(stream_class
));
87 bt_ctf_object_put_ref(stream_class
->clock_class
);
89 if (stream_class
->event_classes_ht
) {
90 g_hash_table_destroy(stream_class
->event_classes_ht
);
92 if (stream_class
->event_classes
) {
93 BT_LOGD_STR("Destroying event classes.");
94 g_ptr_array_free(stream_class
->event_classes
, TRUE
);
97 if (stream_class
->name
) {
98 g_string_free(stream_class
->name
, TRUE
);
101 BT_LOGD_STR("Putting event header field type.");
102 bt_ctf_object_put_ref(stream_class
->event_header_field_type
);
103 BT_LOGD_STR("Putting packet context field type.");
104 bt_ctf_object_put_ref(stream_class
->packet_context_field_type
);
105 BT_LOGD_STR("Putting event context field type.");
106 bt_ctf_object_put_ref(stream_class
->event_context_field_type
);
110 void event_class_exists(gpointer element
, gpointer query
)
112 struct bt_ctf_event_class_common
*event_class_a
= element
;
113 struct bt_ctf_search_query
*search_query
= query
;
114 struct bt_ctf_event_class_common
*event_class_b
= search_query
->value
;
117 if (search_query
->value
== element
) {
118 search_query
->found
= 1;
123 * Two event classes cannot share the same ID in a given
126 id_a
= bt_ctf_event_class_common_get_id(event_class_a
);
127 id_b
= bt_ctf_event_class_common_get_id(event_class_b
);
129 if (id_a
< 0 || id_b
< 0) {
130 /* at least one ID is not set: will be automatically set later */
135 BT_LOGW("Event class with this ID already exists in the stream class: "
136 "id=%" PRId64
", name=\"%s\"",
137 id_a
, bt_ctf_event_class_common_get_name(event_class_a
));
138 search_query
->found
= 1;
147 int bt_ctf_stream_class_common_add_event_class(
148 struct bt_ctf_stream_class_common
*stream_class
,
149 struct bt_ctf_event_class_common
*event_class
,
150 bt_ctf_validation_flag_copy_field_type_func copy_field_type_func
)
153 int64_t *event_id
= NULL
;
154 struct bt_ctf_trace_common
*trace
= NULL
;
155 struct bt_ctf_stream_class_common
*old_stream_class
= NULL
;
156 struct bt_ctf_validation_output validation_output
= { 0 };
157 struct bt_ctf_field_type_common
*packet_header_type
= NULL
;
158 struct bt_ctf_field_type_common
*packet_context_type
= NULL
;
159 struct bt_ctf_field_type_common
*event_header_type
= NULL
;
160 struct bt_ctf_field_type_common
*stream_event_ctx_type
= NULL
;
161 struct bt_ctf_field_type_common
*event_context_type
= NULL
;
162 struct bt_ctf_field_type_common
*event_payload_type
= NULL
;
163 const enum bt_ctf_validation_flag validation_flags
=
164 BT_CTF_VALIDATION_FLAG_EVENT
;
165 struct bt_ctf_clock_class
*expected_clock_class
= NULL
;
167 BT_ASSERT(copy_field_type_func
);
169 if (!stream_class
|| !event_class
) {
170 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
171 "stream-class-addr=%p, event-class-addr=%p",
172 stream_class
, event_class
);
177 BT_LOGD("Adding event class to stream class: "
178 "stream-class-addr=%p, stream-class-name=\"%s\", "
179 "stream-class-id=%" PRId64
", event-class-addr=%p, "
180 "event-class-name=\"%s\", event-class-id=%" PRId64
,
181 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
182 bt_ctf_stream_class_common_get_id(stream_class
),
184 bt_ctf_event_class_common_get_name(event_class
),
185 bt_ctf_event_class_common_get_id(event_class
));
186 trace
= bt_ctf_stream_class_common_borrow_trace(stream_class
);
188 if (stream_class
->frozen
) {
190 * We only check that the event class to be added has a
191 * single class which matches the stream class's
192 * expected clock class if the stream class is frozen.
193 * If it's not, then this event class is added "as is"
194 * and the validation will be performed when calling
195 * either bt_ctf_trace_add_stream_class() or
196 * bt_ctf_event_create(). This is because the stream class's
197 * field types (packet context, event header, event
198 * context) could change before the next call to one of
199 * those two functions.
201 expected_clock_class
= bt_ctf_object_get_ref(stream_class
->clock_class
);
204 * At this point, `expected_clock_class` can be NULL,
205 * and bt_ctf_event_class_validate_single_clock_class()
208 ret
= bt_ctf_event_class_common_validate_single_clock_class(
209 event_class
, &expected_clock_class
);
211 BT_LOGW("Event class contains a field type which is not "
212 "recursively mapped to its stream class's "
213 "expected clock class: "
214 "stream-class-addr=%p, "
215 "stream-class-id=%" PRId64
", "
216 "stream-class-name=\"%s\", "
217 "expected-clock-class-addr=%p, "
218 "expected-clock-class-name=\"%s\"",
220 bt_ctf_stream_class_common_get_id(stream_class
),
221 bt_ctf_stream_class_common_get_name(stream_class
),
222 expected_clock_class
,
223 expected_clock_class
?
224 bt_ctf_clock_class_get_name(expected_clock_class
) :
230 event_id
= g_new(int64_t, 1);
232 BT_LOGE_STR("Failed to allocate one int64_t.");
237 /* Check for duplicate event classes */
238 struct bt_ctf_search_query query
= { .value
= event_class
, .found
= 0 };
239 g_ptr_array_foreach(stream_class
->event_classes
, event_class_exists
,
242 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
247 old_stream_class
= bt_ctf_event_class_common_borrow_stream_class(event_class
);
248 if (old_stream_class
) {
249 /* Event class is already associated to a stream class. */
250 BT_LOGW("Event class is already part of another stream class: "
251 "event-class-stream-class-addr=%p, "
252 "event-class-stream-class-name=\"%s\", "
253 "event-class-stream-class-id=%" PRId64
,
255 bt_ctf_stream_class_common_get_name(old_stream_class
),
256 bt_ctf_stream_class_common_get_id(old_stream_class
));
263 * If the stream class is associated with a trace, then
264 * both those objects are frozen. Also, this event class
265 * is about to be frozen.
267 * Therefore the event class must be validated here.
268 * The trace and stream class should be valid at this
271 BT_ASSERT(trace
->valid
);
272 BT_ASSERT(stream_class
->valid
);
274 bt_ctf_trace_common_borrow_packet_header_field_type(trace
);
275 packet_context_type
=
276 bt_ctf_stream_class_common_borrow_packet_context_field_type(
279 bt_ctf_stream_class_common_borrow_event_header_field_type(
281 stream_event_ctx_type
=
282 bt_ctf_stream_class_common_borrow_event_context_field_type(
285 bt_ctf_event_class_common_borrow_context_field_type(
288 bt_ctf_event_class_common_borrow_payload_field_type(
290 ret
= bt_ctf_validate_class_types(
291 trace
->environment
, packet_header_type
,
292 packet_context_type
, event_header_type
,
293 stream_event_ctx_type
, event_context_type
,
294 event_payload_type
, trace
->valid
,
295 stream_class
->valid
, event_class
->valid
,
296 &validation_output
, validation_flags
,
297 copy_field_type_func
);
301 * This means something went wrong during the
302 * validation process, not that the objects are
305 BT_LOGE("Failed to validate event class: ret=%d", ret
);
309 if ((validation_output
.valid_flags
& validation_flags
) !=
311 /* Invalid event class */
312 BT_LOGW("Invalid trace, stream class, or event class: "
314 validation_output
.valid_flags
);
320 /* Only set an event ID if none was explicitly set before */
321 *event_id
= bt_ctf_event_class_common_get_id(event_class
);
323 BT_LOGV("Event class has no ID: automatically setting it: "
324 "id=%" PRId64
, stream_class
->next_event_id
);
326 if (bt_ctf_event_class_common_set_id(event_class
,
327 stream_class
->next_event_id
)) {
328 BT_LOGE("Cannot set event class's ID: id=%" PRId64
,
329 stream_class
->next_event_id
);
333 stream_class
->next_event_id
++;
334 *event_id
= stream_class
->next_event_id
;
337 bt_ctf_object_set_parent(&event_class
->base
, &stream_class
->base
);
341 * At this point we know that the function will be
342 * successful. Therefore we can replace the event
343 * class's field types with what's in the validation
344 * output structure and mark this event class as valid.
346 bt_ctf_validation_replace_types(NULL
, NULL
, event_class
,
347 &validation_output
, validation_flags
);
348 event_class
->valid
= 1;
351 * Put what was not moved in
352 * bt_ctf_validation_replace_types().
354 bt_ctf_validation_output_put_types(&validation_output
);
357 /* Add to the event classes of the stream class */
358 g_ptr_array_add(stream_class
->event_classes
, event_class
);
359 g_hash_table_insert(stream_class
->event_classes_ht
, event_id
,
363 /* Freeze the event class */
364 bt_ctf_event_class_common_freeze(event_class
);
367 * It is safe to set the stream class's unique clock class
368 * now if the stream class is frozen.
370 if (stream_class
->frozen
&& expected_clock_class
) {
371 BT_ASSERT(!stream_class
->clock_class
||
372 stream_class
->clock_class
== expected_clock_class
);
373 BT_CTF_OBJECT_MOVE_REF(stream_class
->clock_class
, expected_clock_class
);
376 BT_LOGD("Added event class to stream class: "
377 "stream-class-addr=%p, stream-class-name=\"%s\", "
378 "stream-class-id=%" PRId64
", event-class-addr=%p, "
379 "event-class-name=\"%s\", event-class-id=%" PRId64
,
380 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
381 bt_ctf_stream_class_common_get_id(stream_class
),
383 bt_ctf_event_class_common_get_name(event_class
),
384 bt_ctf_event_class_common_get_id(event_class
));
387 bt_ctf_validation_output_put_types(&validation_output
);
388 bt_ctf_object_put_ref(expected_clock_class
);
394 int64_t get_event_class_count(void *element
)
396 return bt_ctf_stream_class_get_event_class_count(
397 (struct bt_ctf_stream_class
*) element
);
401 void *get_event_class(void *element
, int i
)
403 return bt_ctf_stream_class_get_event_class_by_index(
404 (struct bt_ctf_stream_class
*) element
, i
);
408 int visit_event_class(void *object
, bt_ctf_visitor visitor
,void *data
)
410 struct bt_ctf_visitor_object obj
= {
412 .type
= BT_CTF_VISITOR_OBJECT_TYPE_EVENT_CLASS
415 return visitor(&obj
, data
);
419 int bt_ctf_stream_class_common_visit(struct bt_ctf_stream_class_common
*stream_class
,
420 bt_ctf_visitor visitor
, void *data
)
423 struct bt_ctf_visitor_object obj
= {
424 .object
= stream_class
,
425 .type
= BT_CTF_VISITOR_OBJECT_TYPE_STREAM_CLASS
428 if (!stream_class
|| !visitor
) {
429 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
430 "stream-class-addr=%p, visitor=%p",
431 stream_class
, visitor
);
436 ret
= bt_ctf_visitor_helper(&obj
, get_event_class_count
,
438 visit_event_class
, visitor
, data
);
439 BT_LOGV("bt_ctf_visitor_helper() returned: ret=%d", ret
);
446 int bt_ctf_stream_class_visit(struct bt_ctf_stream_class
*stream_class
,
447 bt_ctf_visitor visitor
, void *data
)
449 return bt_ctf_stream_class_common_visit(BT_CTF_FROM_COMMON(stream_class
),
454 void bt_ctf_stream_class_common_freeze(struct bt_ctf_stream_class_common
*stream_class
)
456 if (!stream_class
|| stream_class
->frozen
) {
460 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64
,
461 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
462 bt_ctf_stream_class_common_get_id(stream_class
));
463 stream_class
->frozen
= 1;
464 bt_ctf_field_type_common_freeze(stream_class
->event_header_field_type
);
465 bt_ctf_field_type_common_freeze(stream_class
->packet_context_field_type
);
466 bt_ctf_field_type_common_freeze(stream_class
->event_context_field_type
);
467 bt_ctf_clock_class_freeze(stream_class
->clock_class
);
471 int bt_ctf_stream_class_common_validate_single_clock_class(
472 struct bt_ctf_stream_class_common
*stream_class
,
473 struct bt_ctf_clock_class
**expected_clock_class
)
478 BT_ASSERT(stream_class
);
479 BT_ASSERT(expected_clock_class
);
480 ret
= bt_ctf_field_type_common_validate_single_clock_class(
481 stream_class
->packet_context_field_type
,
482 expected_clock_class
);
484 BT_LOGW("Stream class's packet context field type "
485 "is not recursively mapped to the "
486 "expected clock class: "
487 "stream-class-addr=%p, "
488 "stream-class-name=\"%s\", "
489 "stream-class-id=%" PRId64
", "
492 bt_ctf_stream_class_common_get_name(stream_class
),
494 stream_class
->packet_context_field_type
);
498 ret
= bt_ctf_field_type_common_validate_single_clock_class(
499 stream_class
->event_header_field_type
,
500 expected_clock_class
);
502 BT_LOGW("Stream class's event header field type "
503 "is not recursively mapped to the "
504 "expected clock class: "
505 "stream-class-addr=%p, "
506 "stream-class-name=\"%s\", "
507 "stream-class-id=%" PRId64
", "
510 bt_ctf_stream_class_common_get_name(stream_class
),
512 stream_class
->event_header_field_type
);
516 ret
= bt_ctf_field_type_common_validate_single_clock_class(
517 stream_class
->event_context_field_type
,
518 expected_clock_class
);
520 BT_LOGW("Stream class's event context field type "
521 "is not recursively mapped to the "
522 "expected clock class: "
523 "stream-class-addr=%p, "
524 "stream-class-name=\"%s\", "
525 "stream-class-id=%" PRId64
", "
528 bt_ctf_stream_class_common_get_name(stream_class
),
530 stream_class
->event_context_field_type
);
534 for (i
= 0; i
< stream_class
->event_classes
->len
; i
++) {
535 struct bt_ctf_event_class_common
*event_class
=
536 g_ptr_array_index(stream_class
->event_classes
, i
);
538 BT_ASSERT(event_class
);
539 ret
= bt_ctf_event_class_common_validate_single_clock_class(
540 event_class
, expected_clock_class
);
542 BT_LOGW("Stream class's event class contains a "
543 "field type which is not recursively mapped to "
544 "the expected clock class: "
545 "stream-class-addr=%p, "
546 "stream-class-name=\"%s\", "
547 "stream-class-id=%" PRId64
,
549 bt_ctf_stream_class_common_get_name(stream_class
),
560 int init_event_header(struct bt_ctf_stream_class
*stream_class
)
563 struct bt_ctf_field_type
*event_header_type
=
564 bt_ctf_field_type_structure_create();
565 struct bt_ctf_field_type
*_uint32_t
=
566 get_field_type(FIELD_TYPE_ALIAS_UINT32_T
);
567 struct bt_ctf_field_type
*_uint64_t
=
568 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
570 if (!event_header_type
) {
571 BT_LOGE_STR("Cannot create empty structure field type.");
576 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
579 BT_LOGE_STR("Cannot add `id` field to event header field type.");
583 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
584 _uint64_t
, "timestamp");
586 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
590 bt_ctf_object_put_ref(stream_class
->common
.event_header_field_type
);
591 stream_class
->common
.event_header_field_type
=
592 (void *) event_header_type
;
593 event_header_type
= NULL
;
597 bt_ctf_object_put_ref(event_header_type
);
600 bt_ctf_object_put_ref(_uint32_t
);
601 bt_ctf_object_put_ref(_uint64_t
);
606 int init_packet_context(struct bt_ctf_stream_class
*stream_class
)
609 struct bt_ctf_field_type
*packet_context_type
=
610 bt_ctf_field_type_structure_create();
611 struct bt_ctf_field_type
*_uint64_t
=
612 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
613 struct bt_ctf_field_type
*ts_begin_end_uint64_t
;
615 if (!packet_context_type
) {
616 BT_LOGE_STR("Cannot create empty structure field type.");
621 ts_begin_end_uint64_t
= bt_ctf_field_type_copy(_uint64_t
);
622 if (!ts_begin_end_uint64_t
) {
623 BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
629 * We create a stream packet context as proposed in the CTF
632 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
633 ts_begin_end_uint64_t
, "timestamp_begin");
635 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
639 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
640 ts_begin_end_uint64_t
, "timestamp_end");
642 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
646 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
647 _uint64_t
, "content_size");
649 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
653 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
654 _uint64_t
, "packet_size");
656 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
660 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
661 _uint64_t
, "events_discarded");
663 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
667 bt_ctf_object_put_ref(stream_class
->common
.packet_context_field_type
);
668 stream_class
->common
.packet_context_field_type
=
669 (void *) packet_context_type
;
670 packet_context_type
= NULL
;
674 bt_ctf_object_put_ref(packet_context_type
);
678 bt_ctf_object_put_ref(_uint64_t
);
679 bt_ctf_object_put_ref(ts_begin_end_uint64_t
);
684 void bt_ctf_stream_class_destroy(struct bt_ctf_object
*obj
)
686 struct bt_ctf_stream_class
*stream_class
;
688 stream_class
= (void *) obj
;
689 BT_LOGD("Destroying CTF writer stream class: addr=%p, name=\"%s\", id=%" PRId64
,
690 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
691 bt_ctf_stream_class_get_id(stream_class
));
692 bt_ctf_stream_class_common_finalize(BT_CTF_TO_COMMON(stream_class
));
693 bt_ctf_object_put_ref(stream_class
->clock
);
694 g_free(stream_class
);
697 struct bt_ctf_stream_class
*bt_ctf_stream_class_create(const char *name
)
699 struct bt_ctf_stream_class
*stream_class
;
702 BT_LOGD("Creating CTF writer stream class object: name=\"%s\"", name
);
703 stream_class
= g_new0(struct bt_ctf_stream_class
, 1);
705 BT_LOGE_STR("Failed to allocate one CTF writer stream class.");
709 ret
= bt_ctf_stream_class_common_initialize(BT_CTF_TO_COMMON(stream_class
),
710 name
, bt_ctf_stream_class_destroy
);
712 /* bt_ctf_stream_class_common_initialize() logs errors */
716 ret
= init_event_header(stream_class
);
718 BT_LOGE_STR("Cannot initialize stream class's event header field type.");
722 ret
= init_packet_context(stream_class
);
724 BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
728 BT_LOGD("Created CTF writer stream class object: addr=%p, name=\"%s\"",
733 BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_class
);
738 int try_map_clock_class(struct bt_ctf_stream_class
*stream_class
,
739 struct bt_ctf_field_type
*parent_ft
, const char *field_name
)
741 struct bt_ctf_clock_class
*mapped_clock_class
= NULL
;
743 struct bt_ctf_field_type
*ft
=
744 bt_ctf_field_type_structure_get_field_type_by_name(parent_ft
,
747 BT_ASSERT(stream_class
->clock
);
750 /* Field does not exist: not an error */
754 BT_ASSERT(((struct bt_ctf_field_type_common
*) ft
)->id
==
755 BT_CTF_FIELD_TYPE_ID_INTEGER
);
757 bt_ctf_field_type_integer_get_mapped_clock_class(ft
);
758 if (!mapped_clock_class
) {
759 struct bt_ctf_field_type
*ft_copy
;
761 if (!stream_class
->clock
) {
762 BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
763 "stream-class-addr=%p, stream-class-name=\"%s\", "
764 "stream-class-id=%" PRId64
", ft-addr=%p",
766 bt_ctf_stream_class_get_name(stream_class
),
767 bt_ctf_stream_class_get_id(stream_class
), ft
);
772 ft_copy
= bt_ctf_field_type_copy(ft
);
774 BT_LOGE("Failed to copy integer field type: ft-addr=%p",
778 ret
= bt_ctf_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
779 (void *) ft_copy
, stream_class
->clock
->clock_class
);
782 ret
= bt_ctf_field_type_common_structure_replace_field(
783 (void *) parent_ft
, field_name
, (void *) ft_copy
);
784 bt_ctf_object_put_ref(ft_copy
);
785 BT_LOGV("Automatically mapped field type to stream class's clock class: "
786 "stream-class-addr=%p, stream-class-name=\"%s\", "
787 "stream-class-id=%" PRId64
", ft-addr=%p, "
790 bt_ctf_stream_class_get_name(stream_class
),
791 bt_ctf_stream_class_get_id(stream_class
), ft
, ft_copy
);
795 bt_ctf_object_put_ref(ft
);
796 bt_ctf_object_put_ref(mapped_clock_class
);
801 int bt_ctf_stream_class_map_clock_class(
802 struct bt_ctf_stream_class
*stream_class
,
803 struct bt_ctf_field_type
*packet_context_type
,
804 struct bt_ctf_field_type
*event_header_type
)
808 BT_ASSERT(stream_class
);
810 if (!stream_class
->clock
) {
811 /* No clock class to map to */
815 if (packet_context_type
) {
816 if (try_map_clock_class(stream_class
, packet_context_type
,
817 "timestamp_begin")) {
818 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
823 if (try_map_clock_class(stream_class
, packet_context_type
,
825 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
831 if (event_header_type
) {
832 if (try_map_clock_class(stream_class
, event_header_type
,
834 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
844 struct bt_ctf_clock
*bt_ctf_stream_class_get_clock(
845 struct bt_ctf_stream_class
*stream_class
)
847 struct bt_ctf_clock
*clock
= NULL
;
850 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
854 if (!stream_class
->clock
) {
855 BT_LOGV("Stream class has no clock: "
856 "addr=%p, name=\"%s\", id=%" PRId64
,
858 bt_ctf_stream_class_get_name(stream_class
),
859 bt_ctf_stream_class_get_id(stream_class
));
863 clock
= bt_ctf_object_get_ref(stream_class
->clock
);
869 int bt_ctf_stream_class_set_clock(
870 struct bt_ctf_stream_class
*stream_class
,
871 struct bt_ctf_clock
*clock
)
875 if (!stream_class
|| !clock
) {
876 BT_LOGW("Invalid parameter: stream class or clock is NULL: "
877 "stream-class-addr=%p, clock-addr=%p",
878 stream_class
, clock
);
883 if (stream_class
->common
.frozen
) {
884 BT_LOGW("Invalid parameter: stream class is frozen: "
885 "addr=%p, name=\"%s\", id=%" PRId64
,
887 bt_ctf_stream_class_get_name(stream_class
),
888 bt_ctf_stream_class_get_id(stream_class
));
893 /* Replace the current clock of this stream class. */
894 bt_ctf_object_put_ref(stream_class
->clock
);
895 stream_class
->clock
= bt_ctf_object_get_ref(clock
);
896 BT_LOGV("Set stream class's clock: "
897 "addr=%p, name=\"%s\", id=%" PRId64
", "
898 "clock-addr=%p, clock-name=\"%s\"",
900 bt_ctf_stream_class_get_name(stream_class
),
901 bt_ctf_stream_class_get_id(stream_class
),
903 bt_ctf_clock_get_name(stream_class
->clock
));
910 int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class
*stream_class
,
911 struct metadata_context
*context
)
915 struct bt_ctf_trace
*trace
;
916 struct bt_ctf_field_type
*packet_header_type
= NULL
;
918 BT_LOGD("Serializing stream class's metadata: "
919 "stream-class-addr=%p, stream-class-name=\"%s\", "
920 "stream-class-id=%" PRId64
", metadata-context-addr=%p",
922 bt_ctf_stream_class_get_name(stream_class
),
923 bt_ctf_stream_class_get_id(stream_class
), context
);
924 g_string_assign(context
->field_name
, "");
925 context
->current_indentation_level
= 1;
926 if (!stream_class
->common
.id_set
) {
927 BT_LOGW_STR("Stream class's ID is not set.");
932 g_string_append(context
->string
, "stream {\n");
935 * The reference to the trace is only borrowed since the
936 * serialization of the stream class might have been triggered
937 * by the trace's destruction. In such a case, the trace's
938 * reference count would, unexepectedly, go through the sequence
939 * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
942 trace
= BT_CTF_FROM_COMMON(bt_ctf_stream_class_common_borrow_trace(
943 BT_CTF_TO_COMMON(stream_class
)));
945 packet_header_type
= bt_ctf_trace_get_packet_header_field_type(trace
);
947 if (packet_header_type
) {
948 struct bt_ctf_field_type
*stream_id_type
;
951 bt_ctf_field_type_structure_get_field_type_by_name(
952 packet_header_type
, "stream_id");
953 if (stream_id_type
) {
955 * Only set the stream's id if the trace's packet header
956 * contains a stream_id field. This field is only
957 * needed if the trace contains only one stream
960 g_string_append_printf(context
->string
,
961 "\tid = %" PRId64
";\n",
962 stream_class
->common
.id
);
964 bt_ctf_object_put_ref(stream_id_type
);
966 if (stream_class
->common
.event_header_field_type
) {
967 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
968 g_string_append(context
->string
, "\tevent.header := ");
969 ret
= bt_ctf_field_type_serialize_recursive(
970 (void *) stream_class
->common
.event_header_field_type
,
973 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
977 g_string_append(context
->string
, ";");
981 if (stream_class
->common
.packet_context_field_type
) {
982 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
983 g_string_append(context
->string
, "\n\n\tpacket.context := ");
984 ret
= bt_ctf_field_type_serialize_recursive(
985 (void *) stream_class
->common
.packet_context_field_type
,
988 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
992 g_string_append(context
->string
, ";");
995 if (stream_class
->common
.event_context_field_type
) {
996 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
997 g_string_append(context
->string
, "\n\n\tevent.context := ");
998 ret
= bt_ctf_field_type_serialize_recursive(
999 (void *) stream_class
->common
.event_context_field_type
,
1002 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
1006 g_string_append(context
->string
, ";");
1009 g_string_append(context
->string
, "\n};\n\n");
1011 for (i
= 0; i
< stream_class
->common
.event_classes
->len
; i
++) {
1012 struct bt_ctf_event_class
*event_class
=
1013 stream_class
->common
.event_classes
->pdata
[i
];
1015 ret
= bt_ctf_event_class_serialize(event_class
, context
);
1017 BT_LOGW("Cannot serialize event class's metadata: "
1018 "event-class-addr=%p, event-class-name=\"%s\", "
1019 "event-class-id=%" PRId64
,
1021 bt_ctf_event_class_get_name(event_class
),
1022 bt_ctf_event_class_get_id(event_class
));
1028 bt_ctf_object_put_ref(packet_header_type
);
1029 context
->current_indentation_level
= 0;
1033 struct bt_ctf_trace
*bt_ctf_stream_class_get_trace(
1034 struct bt_ctf_stream_class
*stream_class
)
1036 return bt_ctf_object_get_ref(bt_ctf_stream_class_common_borrow_trace(
1037 BT_CTF_TO_COMMON(stream_class
)));
1040 const char *bt_ctf_stream_class_get_name(
1041 struct bt_ctf_stream_class
*stream_class
)
1043 return bt_ctf_stream_class_common_get_name(BT_CTF_TO_COMMON(stream_class
));
1046 int bt_ctf_stream_class_set_name(
1047 struct bt_ctf_stream_class
*stream_class
, const char *name
)
1049 return bt_ctf_stream_class_common_set_name(BT_CTF_TO_COMMON(stream_class
),
1053 int64_t bt_ctf_stream_class_get_id(
1054 struct bt_ctf_stream_class
*stream_class
)
1056 return bt_ctf_stream_class_common_get_id(BT_CTF_TO_COMMON(stream_class
));
1059 int bt_ctf_stream_class_set_id(
1060 struct bt_ctf_stream_class
*stream_class
, uint64_t id
)
1062 return bt_ctf_stream_class_common_set_id(BT_CTF_TO_COMMON(stream_class
), id
);
1065 struct bt_ctf_field_type
*bt_ctf_stream_class_get_packet_context_type(
1066 struct bt_ctf_stream_class
*stream_class
)
1068 return bt_ctf_object_get_ref(
1069 bt_ctf_stream_class_common_borrow_packet_context_field_type(
1070 BT_CTF_TO_COMMON(stream_class
)));
1073 int bt_ctf_stream_class_set_packet_context_type(
1074 struct bt_ctf_stream_class
*stream_class
,
1075 struct bt_ctf_field_type
*packet_context_type
)
1077 return bt_ctf_stream_class_common_set_packet_context_field_type(
1078 BT_CTF_TO_COMMON(stream_class
), (void *) packet_context_type
);
1081 struct bt_ctf_field_type
*
1082 bt_ctf_stream_class_get_event_header_type(
1083 struct bt_ctf_stream_class
*stream_class
)
1085 return bt_ctf_object_get_ref(
1086 bt_ctf_stream_class_common_borrow_event_header_field_type(
1087 BT_CTF_TO_COMMON(stream_class
)));
1090 int bt_ctf_stream_class_set_event_header_type(
1091 struct bt_ctf_stream_class
*stream_class
,
1092 struct bt_ctf_field_type
*event_header_type
)
1094 return bt_ctf_stream_class_common_set_event_header_field_type(
1095 BT_CTF_TO_COMMON(stream_class
), (void *) event_header_type
);
1098 struct bt_ctf_field_type
*
1099 bt_ctf_stream_class_get_event_context_type(
1100 struct bt_ctf_stream_class
*stream_class
)
1102 return bt_ctf_object_get_ref(
1103 bt_ctf_stream_class_common_borrow_event_context_field_type(
1104 BT_CTF_TO_COMMON(stream_class
)));
1107 int bt_ctf_stream_class_set_event_context_type(
1108 struct bt_ctf_stream_class
*stream_class
,
1109 struct bt_ctf_field_type
*event_context_type
)
1111 return bt_ctf_stream_class_common_set_event_context_field_type(
1112 BT_CTF_TO_COMMON(stream_class
), (void *) event_context_type
);
1115 int64_t bt_ctf_stream_class_get_event_class_count(
1116 struct bt_ctf_stream_class
*stream_class
)
1118 return bt_ctf_stream_class_common_get_event_class_count(
1119 BT_CTF_TO_COMMON(stream_class
));
1122 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_index(
1123 struct bt_ctf_stream_class
*stream_class
, uint64_t index
)
1125 return bt_ctf_object_get_ref(
1126 bt_ctf_stream_class_common_borrow_event_class_by_index(
1127 BT_CTF_TO_COMMON(stream_class
), index
));
1130 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_id(
1131 struct bt_ctf_stream_class
*stream_class
, uint64_t id
)
1133 return bt_ctf_object_get_ref(
1134 bt_ctf_stream_class_common_borrow_event_class_by_id(
1135 BT_CTF_TO_COMMON(stream_class
), id
));
1138 int bt_ctf_stream_class_add_event_class(
1139 struct bt_ctf_stream_class
*stream_class
,
1140 struct bt_ctf_event_class
*event_class
)
1142 return bt_ctf_stream_class_common_add_event_class(
1143 BT_CTF_TO_COMMON(stream_class
), BT_CTF_TO_COMMON(event_class
),
1144 (bt_ctf_validation_flag_copy_field_type_func
) bt_ctf_field_type_copy
);