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"
30 #include <babeltrace2-ctf-writer/event.h>
31 #include <babeltrace2-ctf-writer/object.h>
32 #include <babeltrace2-ctf-writer/trace.h>
33 #include <babeltrace2-ctf-writer/utils.h>
35 #include "common/align.h"
36 #include "common/assert.h"
37 #include "compat/compiler.h"
38 #include "compat/endian.h"
40 #include "assert-pre.h"
41 #include "clock-class.h"
42 #include "event-class.h"
45 #include "field-types.h"
46 #include "field-wrapper.h"
47 #include "stream-class.h"
49 #include "validation.h"
54 int bt_ctf_stream_class_common_initialize(struct bt_ctf_stream_class_common
*stream_class
,
55 const char *name
, bt_ctf_object_release_func release_func
)
57 BT_LOGD("Initializing common stream class object: name=\"%s\"", name
);
59 bt_ctf_object_init_shared_with_parent(&stream_class
->base
, release_func
);
60 stream_class
->name
= g_string_new(name
);
61 stream_class
->event_classes
= g_ptr_array_new_with_free_func(
62 (GDestroyNotify
) bt_ctf_object_try_spec_release
);
63 if (!stream_class
->event_classes
) {
64 BT_LOGE_STR("Failed to allocate a GPtrArray.");
68 stream_class
->event_classes_ht
= g_hash_table_new_full(g_int64_hash
,
69 g_int64_equal
, g_free
, NULL
);
70 if (!stream_class
->event_classes_ht
) {
71 BT_LOGE_STR("Failed to allocate a GHashTable.");
75 BT_LOGD("Initialized common stream class object: addr=%p, name=\"%s\"",
84 void bt_ctf_stream_class_common_finalize(struct bt_ctf_stream_class_common
*stream_class
)
86 BT_LOGD("Finalizing common stream class: addr=%p, name=\"%s\", id=%" PRId64
,
87 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
88 bt_ctf_stream_class_common_get_id(stream_class
));
89 bt_ctf_object_put_ref(stream_class
->clock_class
);
91 if (stream_class
->event_classes_ht
) {
92 g_hash_table_destroy(stream_class
->event_classes_ht
);
94 if (stream_class
->event_classes
) {
95 BT_LOGD_STR("Destroying event classes.");
96 g_ptr_array_free(stream_class
->event_classes
, TRUE
);
99 if (stream_class
->name
) {
100 g_string_free(stream_class
->name
, TRUE
);
103 BT_LOGD_STR("Putting event header field type.");
104 bt_ctf_object_put_ref(stream_class
->event_header_field_type
);
105 BT_LOGD_STR("Putting packet context field type.");
106 bt_ctf_object_put_ref(stream_class
->packet_context_field_type
);
107 BT_LOGD_STR("Putting event context field type.");
108 bt_ctf_object_put_ref(stream_class
->event_context_field_type
);
112 void event_class_exists(gpointer element
, gpointer query
)
114 struct bt_ctf_event_class_common
*event_class_a
= element
;
115 struct bt_ctf_search_query
*search_query
= query
;
116 struct bt_ctf_event_class_common
*event_class_b
= search_query
->value
;
119 if (search_query
->value
== element
) {
120 search_query
->found
= 1;
125 * Two event classes cannot share the same ID in a given
128 id_a
= bt_ctf_event_class_common_get_id(event_class_a
);
129 id_b
= bt_ctf_event_class_common_get_id(event_class_b
);
131 if (id_a
< 0 || id_b
< 0) {
132 /* at least one ID is not set: will be automatically set later */
137 BT_LOGW("Event class with this ID already exists in the stream class: "
138 "id=%" PRId64
", name=\"%s\"",
139 id_a
, bt_ctf_event_class_common_get_name(event_class_a
));
140 search_query
->found
= 1;
149 int bt_ctf_stream_class_common_add_event_class(
150 struct bt_ctf_stream_class_common
*stream_class
,
151 struct bt_ctf_event_class_common
*event_class
,
152 bt_ctf_validation_flag_copy_field_type_func copy_field_type_func
)
155 int64_t *event_id
= NULL
;
156 struct bt_ctf_trace_common
*trace
= NULL
;
157 struct bt_ctf_stream_class_common
*old_stream_class
= NULL
;
158 struct bt_ctf_validation_output validation_output
= { 0 };
159 struct bt_ctf_field_type_common
*packet_header_type
= NULL
;
160 struct bt_ctf_field_type_common
*packet_context_type
= NULL
;
161 struct bt_ctf_field_type_common
*event_header_type
= NULL
;
162 struct bt_ctf_field_type_common
*stream_event_ctx_type
= NULL
;
163 struct bt_ctf_field_type_common
*event_context_type
= NULL
;
164 struct bt_ctf_field_type_common
*event_payload_type
= NULL
;
165 const enum bt_ctf_validation_flag validation_flags
=
166 BT_CTF_VALIDATION_FLAG_EVENT
;
167 struct bt_ctf_clock_class
*expected_clock_class
= NULL
;
168 struct bt_ctf_search_query query
= { .value
= event_class
, .found
= 0 };
170 BT_ASSERT_DBG(copy_field_type_func
);
172 if (!stream_class
|| !event_class
) {
173 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
174 "stream-class-addr=%p, event-class-addr=%p",
175 stream_class
, event_class
);
180 BT_LOGD("Adding event class to stream class: "
181 "stream-class-addr=%p, stream-class-name=\"%s\", "
182 "stream-class-id=%" PRId64
", event-class-addr=%p, "
183 "event-class-name=\"%s\", event-class-id=%" PRId64
,
184 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
185 bt_ctf_stream_class_common_get_id(stream_class
),
187 bt_ctf_event_class_common_get_name(event_class
),
188 bt_ctf_event_class_common_get_id(event_class
));
189 trace
= bt_ctf_stream_class_common_borrow_trace(stream_class
);
191 if (stream_class
->frozen
) {
193 * We only check that the event class to be added has a
194 * single class which matches the stream class's
195 * expected clock class if the stream class is frozen.
196 * If it's not, then this event class is added "as is"
197 * and the validation will be performed when calling
198 * either bt_ctf_trace_add_stream_class() or
199 * bt_ctf_event_create(). This is because the stream class's
200 * field types (packet context, event header, event
201 * context) could change before the next call to one of
202 * those two functions.
204 expected_clock_class
= bt_ctf_object_get_ref(stream_class
->clock_class
);
207 * At this point, `expected_clock_class` can be NULL,
208 * and bt_ctf_event_class_validate_single_clock_class()
211 ret
= bt_ctf_event_class_common_validate_single_clock_class(
212 event_class
, &expected_clock_class
);
214 BT_LOGW("Event class contains a field type which is not "
215 "recursively mapped to its stream class's "
216 "expected clock class: "
217 "stream-class-addr=%p, "
218 "stream-class-id=%" PRId64
", "
219 "stream-class-name=\"%s\", "
220 "expected-clock-class-addr=%p, "
221 "expected-clock-class-name=\"%s\"",
223 bt_ctf_stream_class_common_get_id(stream_class
),
224 bt_ctf_stream_class_common_get_name(stream_class
),
225 expected_clock_class
,
226 expected_clock_class
?
227 bt_ctf_clock_class_get_name(expected_clock_class
) :
233 event_id
= g_new(int64_t, 1);
235 BT_LOGE_STR("Failed to allocate one int64_t.");
240 /* Check for duplicate event classes */
241 g_ptr_array_foreach(stream_class
->event_classes
, event_class_exists
,
244 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
249 old_stream_class
= bt_ctf_event_class_common_borrow_stream_class(event_class
);
250 if (old_stream_class
) {
251 /* Event class is already associated to a stream class. */
252 BT_LOGW("Event class is already part of another stream class: "
253 "event-class-stream-class-addr=%p, "
254 "event-class-stream-class-name=\"%s\", "
255 "event-class-stream-class-id=%" PRId64
,
257 bt_ctf_stream_class_common_get_name(old_stream_class
),
258 bt_ctf_stream_class_common_get_id(old_stream_class
));
265 * If the stream class is associated with a trace, then
266 * both those objects are frozen. Also, this event class
267 * is about to be frozen.
269 * Therefore the event class must be validated here.
270 * The trace and stream class should be valid at this
273 BT_ASSERT_DBG(trace
->valid
);
274 BT_ASSERT_DBG(stream_class
->valid
);
276 bt_ctf_trace_common_borrow_packet_header_field_type(trace
);
277 packet_context_type
=
278 bt_ctf_stream_class_common_borrow_packet_context_field_type(
281 bt_ctf_stream_class_common_borrow_event_header_field_type(
283 stream_event_ctx_type
=
284 bt_ctf_stream_class_common_borrow_event_context_field_type(
287 bt_ctf_event_class_common_borrow_context_field_type(
290 bt_ctf_event_class_common_borrow_payload_field_type(
292 ret
= bt_ctf_validate_class_types(
293 trace
->environment
, packet_header_type
,
294 packet_context_type
, event_header_type
,
295 stream_event_ctx_type
, event_context_type
,
296 event_payload_type
, trace
->valid
,
297 stream_class
->valid
, event_class
->valid
,
298 &validation_output
, validation_flags
,
299 copy_field_type_func
);
303 * This means something went wrong during the
304 * validation process, not that the objects are
307 BT_LOGE("Failed to validate event class: ret=%d", ret
);
311 if ((validation_output
.valid_flags
& validation_flags
) !=
313 /* Invalid event class */
314 BT_LOGW("Invalid trace, stream class, or event class: "
316 validation_output
.valid_flags
);
322 /* Only set an event ID if none was explicitly set before */
323 *event_id
= bt_ctf_event_class_common_get_id(event_class
);
325 BT_LOGT("Event class has no ID: automatically setting it: "
326 "id=%" PRId64
, stream_class
->next_event_id
);
328 if (bt_ctf_event_class_common_set_id(event_class
,
329 stream_class
->next_event_id
)) {
330 BT_LOGE("Cannot set event class's ID: id=%" PRId64
,
331 stream_class
->next_event_id
);
335 stream_class
->next_event_id
++;
336 *event_id
= stream_class
->next_event_id
;
339 bt_ctf_object_set_parent(&event_class
->base
, &stream_class
->base
);
343 * At this point we know that the function will be
344 * successful. Therefore we can replace the event
345 * class's field types with what's in the validation
346 * output structure and mark this event class as valid.
348 bt_ctf_validation_replace_types(NULL
, NULL
, event_class
,
349 &validation_output
, validation_flags
);
350 event_class
->valid
= 1;
353 * Put what was not moved in
354 * bt_ctf_validation_replace_types().
356 bt_ctf_validation_output_put_types(&validation_output
);
359 /* Add to the event classes of the stream class */
360 g_ptr_array_add(stream_class
->event_classes
, event_class
);
361 g_hash_table_insert(stream_class
->event_classes_ht
, event_id
,
365 /* Freeze the event class */
366 bt_ctf_event_class_common_freeze(event_class
);
369 * It is safe to set the stream class's unique clock class
370 * now if the stream class is frozen.
372 if (stream_class
->frozen
&& expected_clock_class
) {
373 BT_ASSERT_DBG(!stream_class
->clock_class
||
374 stream_class
->clock_class
== expected_clock_class
);
375 BT_CTF_OBJECT_MOVE_REF(stream_class
->clock_class
, expected_clock_class
);
378 BT_LOGD("Added event class to stream class: "
379 "stream-class-addr=%p, stream-class-name=\"%s\", "
380 "stream-class-id=%" PRId64
", event-class-addr=%p, "
381 "event-class-name=\"%s\", event-class-id=%" PRId64
,
382 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
383 bt_ctf_stream_class_common_get_id(stream_class
),
385 bt_ctf_event_class_common_get_name(event_class
),
386 bt_ctf_event_class_common_get_id(event_class
));
389 bt_ctf_validation_output_put_types(&validation_output
);
390 bt_ctf_object_put_ref(expected_clock_class
);
396 int64_t get_event_class_count(void *element
)
398 return bt_ctf_stream_class_get_event_class_count(
399 (struct bt_ctf_stream_class
*) element
);
403 void *get_event_class(void *element
, int i
)
405 return bt_ctf_stream_class_get_event_class_by_index(
406 (struct bt_ctf_stream_class
*) element
, i
);
410 int visit_event_class(void *object
, bt_ctf_visitor visitor
,void *data
)
412 struct bt_ctf_visitor_object obj
= {
414 .type
= BT_CTF_VISITOR_OBJECT_TYPE_EVENT_CLASS
417 return visitor(&obj
, data
);
421 int bt_ctf_stream_class_common_visit(struct bt_ctf_stream_class_common
*stream_class
,
422 bt_ctf_visitor visitor
, void *data
)
425 struct bt_ctf_visitor_object obj
= {
426 .object
= stream_class
,
427 .type
= BT_CTF_VISITOR_OBJECT_TYPE_STREAM_CLASS
430 if (!stream_class
|| !visitor
) {
431 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
432 "stream-class-addr=%p, visitor=%p",
433 stream_class
, visitor
);
438 ret
= bt_ctf_visitor_helper(&obj
, get_event_class_count
,
440 visit_event_class
, visitor
, data
);
441 BT_LOGT("bt_ctf_visitor_helper() returned: ret=%d", ret
);
448 int bt_ctf_stream_class_visit(struct bt_ctf_stream_class
*stream_class
,
449 bt_ctf_visitor visitor
, void *data
)
451 return bt_ctf_stream_class_common_visit(BT_CTF_FROM_COMMON(stream_class
),
456 void bt_ctf_stream_class_common_freeze(struct bt_ctf_stream_class_common
*stream_class
)
458 if (!stream_class
|| stream_class
->frozen
) {
462 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64
,
463 stream_class
, bt_ctf_stream_class_common_get_name(stream_class
),
464 bt_ctf_stream_class_common_get_id(stream_class
));
465 stream_class
->frozen
= 1;
466 bt_ctf_field_type_common_freeze(stream_class
->event_header_field_type
);
467 bt_ctf_field_type_common_freeze(stream_class
->packet_context_field_type
);
468 bt_ctf_field_type_common_freeze(stream_class
->event_context_field_type
);
469 bt_ctf_clock_class_freeze(stream_class
->clock_class
);
473 int bt_ctf_stream_class_common_validate_single_clock_class(
474 struct bt_ctf_stream_class_common
*stream_class
,
475 struct bt_ctf_clock_class
**expected_clock_class
)
480 BT_ASSERT_DBG(stream_class
);
481 BT_ASSERT_DBG(expected_clock_class
);
482 ret
= bt_ctf_field_type_common_validate_single_clock_class(
483 stream_class
->packet_context_field_type
,
484 expected_clock_class
);
486 BT_LOGW("Stream class's packet context field type "
487 "is not recursively mapped to the "
488 "expected clock class: "
489 "stream-class-addr=%p, "
490 "stream-class-name=\"%s\", "
491 "stream-class-id=%" PRId64
", "
494 bt_ctf_stream_class_common_get_name(stream_class
),
496 stream_class
->packet_context_field_type
);
500 ret
= bt_ctf_field_type_common_validate_single_clock_class(
501 stream_class
->event_header_field_type
,
502 expected_clock_class
);
504 BT_LOGW("Stream class's event header field type "
505 "is not recursively mapped to the "
506 "expected clock class: "
507 "stream-class-addr=%p, "
508 "stream-class-name=\"%s\", "
509 "stream-class-id=%" PRId64
", "
512 bt_ctf_stream_class_common_get_name(stream_class
),
514 stream_class
->event_header_field_type
);
518 ret
= bt_ctf_field_type_common_validate_single_clock_class(
519 stream_class
->event_context_field_type
,
520 expected_clock_class
);
522 BT_LOGW("Stream class's event context field type "
523 "is not recursively mapped to the "
524 "expected clock class: "
525 "stream-class-addr=%p, "
526 "stream-class-name=\"%s\", "
527 "stream-class-id=%" PRId64
", "
530 bt_ctf_stream_class_common_get_name(stream_class
),
532 stream_class
->event_context_field_type
);
536 for (i
= 0; i
< stream_class
->event_classes
->len
; i
++) {
537 struct bt_ctf_event_class_common
*event_class
=
538 g_ptr_array_index(stream_class
->event_classes
, i
);
540 BT_ASSERT_DBG(event_class
);
541 ret
= bt_ctf_event_class_common_validate_single_clock_class(
542 event_class
, expected_clock_class
);
544 BT_LOGW("Stream class's event class contains a "
545 "field type which is not recursively mapped to "
546 "the expected clock class: "
547 "stream-class-addr=%p, "
548 "stream-class-name=\"%s\", "
549 "stream-class-id=%" PRId64
,
551 bt_ctf_stream_class_common_get_name(stream_class
),
562 int init_event_header(struct bt_ctf_stream_class
*stream_class
)
565 struct bt_ctf_field_type
*event_header_type
=
566 bt_ctf_field_type_structure_create();
567 struct bt_ctf_field_type
*_uint32_t
=
568 get_field_type(FIELD_TYPE_ALIAS_UINT32_T
);
569 struct bt_ctf_field_type
*_uint64_t
=
570 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
572 if (!event_header_type
) {
573 BT_LOGE_STR("Cannot create empty structure field type.");
578 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
581 BT_LOGE_STR("Cannot add `id` field to event header field type.");
585 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
586 _uint64_t
, "timestamp");
588 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
592 bt_ctf_object_put_ref(stream_class
->common
.event_header_field_type
);
593 stream_class
->common
.event_header_field_type
=
594 (void *) event_header_type
;
595 event_header_type
= NULL
;
599 bt_ctf_object_put_ref(event_header_type
);
602 bt_ctf_object_put_ref(_uint32_t
);
603 bt_ctf_object_put_ref(_uint64_t
);
608 int init_packet_context(struct bt_ctf_stream_class
*stream_class
)
611 struct bt_ctf_field_type
*packet_context_type
=
612 bt_ctf_field_type_structure_create();
613 struct bt_ctf_field_type
*_uint64_t
=
614 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
615 struct bt_ctf_field_type
*ts_begin_end_uint64_t
= NULL
;
617 if (!packet_context_type
) {
618 BT_LOGE_STR("Cannot create empty structure field type.");
623 ts_begin_end_uint64_t
= bt_ctf_field_type_copy(_uint64_t
);
624 if (!ts_begin_end_uint64_t
) {
625 BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
631 * We create a stream packet context as proposed in the CTF
634 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
635 ts_begin_end_uint64_t
, "timestamp_begin");
637 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
641 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
642 ts_begin_end_uint64_t
, "timestamp_end");
644 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
648 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
649 _uint64_t
, "content_size");
651 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
655 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
656 _uint64_t
, "packet_size");
658 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
662 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
663 _uint64_t
, "events_discarded");
665 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
669 bt_ctf_object_put_ref(stream_class
->common
.packet_context_field_type
);
670 stream_class
->common
.packet_context_field_type
=
671 (void *) packet_context_type
;
672 packet_context_type
= NULL
;
676 bt_ctf_object_put_ref(packet_context_type
);
680 bt_ctf_object_put_ref(_uint64_t
);
681 bt_ctf_object_put_ref(ts_begin_end_uint64_t
);
686 void bt_ctf_stream_class_destroy(struct bt_ctf_object
*obj
)
688 struct bt_ctf_stream_class
*stream_class
;
690 stream_class
= (void *) obj
;
691 BT_LOGD("Destroying CTF writer stream class: addr=%p, name=\"%s\", id=%" PRId64
,
692 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
693 bt_ctf_stream_class_get_id(stream_class
));
694 bt_ctf_stream_class_common_finalize(BT_CTF_TO_COMMON(stream_class
));
695 bt_ctf_object_put_ref(stream_class
->clock
);
696 g_free(stream_class
);
699 struct bt_ctf_stream_class
*bt_ctf_stream_class_create(const char *name
)
701 struct bt_ctf_stream_class
*stream_class
;
704 BT_LOGD("Creating CTF writer stream class object: name=\"%s\"", name
);
705 stream_class
= g_new0(struct bt_ctf_stream_class
, 1);
707 BT_LOGE_STR("Failed to allocate one CTF writer stream class.");
711 ret
= bt_ctf_stream_class_common_initialize(BT_CTF_TO_COMMON(stream_class
),
712 name
, bt_ctf_stream_class_destroy
);
714 /* bt_ctf_stream_class_common_initialize() logs errors */
718 ret
= init_event_header(stream_class
);
720 BT_LOGE_STR("Cannot initialize stream class's event header field type.");
724 ret
= init_packet_context(stream_class
);
726 BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
730 BT_LOGD("Created CTF writer stream class object: addr=%p, name=\"%s\"",
735 BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_class
);
740 int try_map_clock_class(struct bt_ctf_stream_class
*stream_class
,
741 struct bt_ctf_field_type
*parent_ft
, const char *field_name
)
743 struct bt_ctf_clock_class
*mapped_clock_class
= NULL
;
745 struct bt_ctf_field_type
*ft
=
746 bt_ctf_field_type_structure_get_field_type_by_name(parent_ft
,
749 BT_ASSERT_DBG(stream_class
->clock
);
752 /* Field does not exist: not an error */
756 BT_ASSERT_DBG(((struct bt_ctf_field_type_common
*) ft
)->id
==
757 BT_CTF_FIELD_TYPE_ID_INTEGER
);
759 bt_ctf_field_type_integer_get_mapped_clock_class(ft
);
760 if (!mapped_clock_class
) {
761 struct bt_ctf_field_type
*ft_copy
;
763 if (!stream_class
->clock
) {
764 BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
765 "stream-class-addr=%p, stream-class-name=\"%s\", "
766 "stream-class-id=%" PRId64
", ft-addr=%p",
768 bt_ctf_stream_class_get_name(stream_class
),
769 bt_ctf_stream_class_get_id(stream_class
), ft
);
774 ft_copy
= bt_ctf_field_type_copy(ft
);
776 BT_LOGE("Failed to copy integer field type: ft-addr=%p",
782 ret
= bt_ctf_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
783 (void *) ft_copy
, stream_class
->clock
->clock_class
);
784 BT_ASSERT_DBG(ret
== 0);
786 ret
= bt_ctf_field_type_common_structure_replace_field(
787 (void *) parent_ft
, field_name
, (void *) ft_copy
);
788 bt_ctf_object_put_ref(ft_copy
);
789 BT_LOGT("Automatically mapped field type to stream class's clock class: "
790 "stream-class-addr=%p, stream-class-name=\"%s\", "
791 "stream-class-id=%" PRId64
", ft-addr=%p, "
794 bt_ctf_stream_class_get_name(stream_class
),
795 bt_ctf_stream_class_get_id(stream_class
), ft
, ft_copy
);
799 bt_ctf_object_put_ref(ft
);
800 bt_ctf_object_put_ref(mapped_clock_class
);
805 int bt_ctf_stream_class_map_clock_class(
806 struct bt_ctf_stream_class
*stream_class
,
807 struct bt_ctf_field_type
*packet_context_type
,
808 struct bt_ctf_field_type
*event_header_type
)
812 BT_ASSERT_DBG(stream_class
);
814 if (!stream_class
->clock
) {
815 /* No clock class to map to */
819 if (packet_context_type
) {
820 if (try_map_clock_class(stream_class
, packet_context_type
,
821 "timestamp_begin")) {
822 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
827 if (try_map_clock_class(stream_class
, packet_context_type
,
829 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
835 if (event_header_type
) {
836 if (try_map_clock_class(stream_class
, event_header_type
,
838 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
848 struct bt_ctf_clock
*bt_ctf_stream_class_get_clock(
849 struct bt_ctf_stream_class
*stream_class
)
851 struct bt_ctf_clock
*clock
= NULL
;
854 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
858 if (!stream_class
->clock
) {
859 BT_LOGT("Stream class has no clock: "
860 "addr=%p, name=\"%s\", id=%" PRId64
,
862 bt_ctf_stream_class_get_name(stream_class
),
863 bt_ctf_stream_class_get_id(stream_class
));
867 clock
= bt_ctf_object_get_ref(stream_class
->clock
);
873 int bt_ctf_stream_class_set_clock(
874 struct bt_ctf_stream_class
*stream_class
,
875 struct bt_ctf_clock
*clock
)
879 if (!stream_class
|| !clock
) {
880 BT_LOGW("Invalid parameter: stream class or clock is NULL: "
881 "stream-class-addr=%p, clock-addr=%p",
882 stream_class
, clock
);
887 if (stream_class
->common
.frozen
) {
888 BT_LOGW("Invalid parameter: stream class is frozen: "
889 "addr=%p, name=\"%s\", id=%" PRId64
,
891 bt_ctf_stream_class_get_name(stream_class
),
892 bt_ctf_stream_class_get_id(stream_class
));
897 /* Replace the current clock of this stream class. */
898 bt_ctf_object_put_ref(stream_class
->clock
);
899 stream_class
->clock
= bt_ctf_object_get_ref(clock
);
900 BT_LOGT("Set stream class's clock: "
901 "addr=%p, name=\"%s\", id=%" PRId64
", "
902 "clock-addr=%p, clock-name=\"%s\"",
904 bt_ctf_stream_class_get_name(stream_class
),
905 bt_ctf_stream_class_get_id(stream_class
),
907 bt_ctf_clock_get_name(stream_class
->clock
));
914 int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class
*stream_class
,
915 struct metadata_context
*context
)
919 struct bt_ctf_trace
*trace
;
920 struct bt_ctf_field_type
*packet_header_type
= NULL
;
922 BT_LOGD("Serializing stream class's metadata: "
923 "stream-class-addr=%p, stream-class-name=\"%s\", "
924 "stream-class-id=%" PRId64
", metadata-context-addr=%p",
926 bt_ctf_stream_class_get_name(stream_class
),
927 bt_ctf_stream_class_get_id(stream_class
), context
);
928 g_string_assign(context
->field_name
, "");
929 context
->current_indentation_level
= 1;
930 if (!stream_class
->common
.id_set
) {
931 BT_LOGW_STR("Stream class's ID is not set.");
936 g_string_append(context
->string
, "stream {\n");
939 * The reference to the trace is only borrowed since the
940 * serialization of the stream class might have been triggered
941 * by the trace's destruction. In such a case, the trace's
942 * reference count would, unexepectedly, go through the sequence
943 * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
946 trace
= BT_CTF_FROM_COMMON(bt_ctf_stream_class_common_borrow_trace(
947 BT_CTF_TO_COMMON(stream_class
)));
948 BT_ASSERT_DBG(trace
);
949 packet_header_type
= bt_ctf_trace_get_packet_header_field_type(trace
);
951 if (packet_header_type
) {
952 struct bt_ctf_field_type
*stream_id_type
;
955 bt_ctf_field_type_structure_get_field_type_by_name(
956 packet_header_type
, "stream_id");
957 if (stream_id_type
) {
959 * Only set the stream's id if the trace's packet header
960 * contains a stream_id field. This field is only
961 * needed if the trace contains only one stream
964 g_string_append_printf(context
->string
,
965 "\tid = %" PRId64
";\n",
966 stream_class
->common
.id
);
968 bt_ctf_object_put_ref(stream_id_type
);
970 if (stream_class
->common
.event_header_field_type
) {
971 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
972 g_string_append(context
->string
, "\tevent.header := ");
973 ret
= bt_ctf_field_type_serialize_recursive(
974 (void *) stream_class
->common
.event_header_field_type
,
977 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
981 g_string_append(context
->string
, ";");
985 if (stream_class
->common
.packet_context_field_type
) {
986 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
987 g_string_append(context
->string
, "\n\n\tpacket.context := ");
988 ret
= bt_ctf_field_type_serialize_recursive(
989 (void *) stream_class
->common
.packet_context_field_type
,
992 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
996 g_string_append(context
->string
, ";");
999 if (stream_class
->common
.event_context_field_type
) {
1000 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
1001 g_string_append(context
->string
, "\n\n\tevent.context := ");
1002 ret
= bt_ctf_field_type_serialize_recursive(
1003 (void *) stream_class
->common
.event_context_field_type
,
1006 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
1010 g_string_append(context
->string
, ";");
1013 g_string_append(context
->string
, "\n};\n\n");
1015 for (i
= 0; i
< stream_class
->common
.event_classes
->len
; i
++) {
1016 struct bt_ctf_event_class
*event_class
=
1017 stream_class
->common
.event_classes
->pdata
[i
];
1019 ret
= bt_ctf_event_class_serialize(event_class
, context
);
1021 BT_LOGW("Cannot serialize event class's metadata: "
1022 "event-class-addr=%p, event-class-name=\"%s\", "
1023 "event-class-id=%" PRId64
,
1025 bt_ctf_event_class_get_name(event_class
),
1026 bt_ctf_event_class_get_id(event_class
));
1032 bt_ctf_object_put_ref(packet_header_type
);
1033 context
->current_indentation_level
= 0;
1037 struct bt_ctf_trace
*bt_ctf_stream_class_get_trace(
1038 struct bt_ctf_stream_class
*stream_class
)
1040 return bt_ctf_object_get_ref(bt_ctf_stream_class_common_borrow_trace(
1041 BT_CTF_TO_COMMON(stream_class
)));
1044 const char *bt_ctf_stream_class_get_name(
1045 struct bt_ctf_stream_class
*stream_class
)
1047 return bt_ctf_stream_class_common_get_name(BT_CTF_TO_COMMON(stream_class
));
1050 int bt_ctf_stream_class_set_name(
1051 struct bt_ctf_stream_class
*stream_class
, const char *name
)
1053 return bt_ctf_stream_class_common_set_name(BT_CTF_TO_COMMON(stream_class
),
1057 int64_t bt_ctf_stream_class_get_id(
1058 struct bt_ctf_stream_class
*stream_class
)
1060 return bt_ctf_stream_class_common_get_id(BT_CTF_TO_COMMON(stream_class
));
1063 int bt_ctf_stream_class_set_id(
1064 struct bt_ctf_stream_class
*stream_class
, uint64_t id
)
1066 return bt_ctf_stream_class_common_set_id(BT_CTF_TO_COMMON(stream_class
), id
);
1069 struct bt_ctf_field_type
*bt_ctf_stream_class_get_packet_context_type(
1070 struct bt_ctf_stream_class
*stream_class
)
1072 return bt_ctf_object_get_ref(
1073 bt_ctf_stream_class_common_borrow_packet_context_field_type(
1074 BT_CTF_TO_COMMON(stream_class
)));
1077 int bt_ctf_stream_class_set_packet_context_type(
1078 struct bt_ctf_stream_class
*stream_class
,
1079 struct bt_ctf_field_type
*packet_context_type
)
1081 return bt_ctf_stream_class_common_set_packet_context_field_type(
1082 BT_CTF_TO_COMMON(stream_class
), (void *) packet_context_type
);
1085 struct bt_ctf_field_type
*
1086 bt_ctf_stream_class_get_event_header_type(
1087 struct bt_ctf_stream_class
*stream_class
)
1089 return bt_ctf_object_get_ref(
1090 bt_ctf_stream_class_common_borrow_event_header_field_type(
1091 BT_CTF_TO_COMMON(stream_class
)));
1094 int bt_ctf_stream_class_set_event_header_type(
1095 struct bt_ctf_stream_class
*stream_class
,
1096 struct bt_ctf_field_type
*event_header_type
)
1098 return bt_ctf_stream_class_common_set_event_header_field_type(
1099 BT_CTF_TO_COMMON(stream_class
), (void *) event_header_type
);
1102 struct bt_ctf_field_type
*
1103 bt_ctf_stream_class_get_event_context_type(
1104 struct bt_ctf_stream_class
*stream_class
)
1106 return bt_ctf_object_get_ref(
1107 bt_ctf_stream_class_common_borrow_event_context_field_type(
1108 BT_CTF_TO_COMMON(stream_class
)));
1111 int bt_ctf_stream_class_set_event_context_type(
1112 struct bt_ctf_stream_class
*stream_class
,
1113 struct bt_ctf_field_type
*event_context_type
)
1115 return bt_ctf_stream_class_common_set_event_context_field_type(
1116 BT_CTF_TO_COMMON(stream_class
), (void *) event_context_type
);
1119 int64_t bt_ctf_stream_class_get_event_class_count(
1120 struct bt_ctf_stream_class
*stream_class
)
1122 return bt_ctf_stream_class_common_get_event_class_count(
1123 BT_CTF_TO_COMMON(stream_class
));
1126 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_index(
1127 struct bt_ctf_stream_class
*stream_class
, uint64_t index
)
1129 return bt_ctf_object_get_ref(
1130 bt_ctf_stream_class_common_borrow_event_class_by_index(
1131 BT_CTF_TO_COMMON(stream_class
), index
));
1134 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_id(
1135 struct bt_ctf_stream_class
*stream_class
, uint64_t id
)
1137 return bt_ctf_object_get_ref(
1138 bt_ctf_stream_class_common_borrow_event_class_by_id(
1139 BT_CTF_TO_COMMON(stream_class
), id
));
1142 int bt_ctf_stream_class_add_event_class(
1143 struct bt_ctf_stream_class
*stream_class
,
1144 struct bt_ctf_event_class
*event_class
)
1146 return bt_ctf_stream_class_common_add_event_class(
1147 BT_CTF_TO_COMMON(stream_class
), BT_CTF_TO_COMMON(event_class
),
1148 (bt_ctf_validation_flag_copy_field_type_func
) bt_ctf_field_type_copy
);