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 <babeltrace/lib-logging-internal.h>
27 #include <babeltrace/ref.h>
28 #include <babeltrace/ctf-writer/writer-internal.h>
29 #include <babeltrace/ctf-writer/stream-class-internal.h>
30 #include <babeltrace/ctf-writer/field-types-internal.h>
31 #include <babeltrace/ctf-writer/event-internal.h>
32 #include <babeltrace/ctf-writer/event.h>
33 #include <babeltrace/ctf-writer/trace.h>
34 #include <babeltrace/compiler-internal.h>
35 #include <babeltrace/assert-internal.h>
36 #include <babeltrace/assert-pre-internal.h>
40 int init_event_header(struct bt_ctf_stream_class
*stream_class
)
43 struct bt_ctf_field_type
*event_header_type
=
44 bt_ctf_field_type_structure_create();
45 struct bt_ctf_field_type
*_uint32_t
=
46 get_field_type(FIELD_TYPE_ALIAS_UINT32_T
);
47 struct bt_ctf_field_type
*_uint64_t
=
48 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
50 if (!event_header_type
) {
51 BT_LOGE_STR("Cannot create empty structure field type.");
56 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
59 BT_LOGE_STR("Cannot add `id` field to event header field type.");
63 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
64 _uint64_t
, "timestamp");
66 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
70 bt_put(stream_class
->common
.event_header_field_type
);
71 stream_class
->common
.event_header_field_type
=
72 (void *) event_header_type
;
73 event_header_type
= NULL
;
77 bt_put(event_header_type
);
86 int init_packet_context(struct bt_ctf_stream_class
*stream_class
)
89 struct bt_ctf_field_type
*packet_context_type
=
90 bt_ctf_field_type_structure_create();
91 struct bt_ctf_field_type
*_uint64_t
=
92 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
93 struct bt_ctf_field_type
*ts_begin_end_uint64_t
;
95 if (!packet_context_type
) {
96 BT_LOGE_STR("Cannot create empty structure field type.");
101 ts_begin_end_uint64_t
= bt_ctf_field_type_copy(_uint64_t
);
102 if (!ts_begin_end_uint64_t
) {
103 BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
109 * We create a stream packet context as proposed in the CTF
112 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
113 ts_begin_end_uint64_t
, "timestamp_begin");
115 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
119 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
120 ts_begin_end_uint64_t
, "timestamp_end");
122 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
126 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
127 _uint64_t
, "content_size");
129 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
133 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
134 _uint64_t
, "packet_size");
136 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
140 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
141 _uint64_t
, "events_discarded");
143 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
147 bt_put(stream_class
->common
.packet_context_field_type
);
148 stream_class
->common
.packet_context_field_type
=
149 (void *) packet_context_type
;
150 packet_context_type
= NULL
;
154 bt_put(packet_context_type
);
159 bt_put(ts_begin_end_uint64_t
);
164 void bt_ctf_stream_class_destroy(struct bt_object
*obj
)
166 struct bt_ctf_stream_class
*stream_class
;
168 stream_class
= (void *) obj
;
169 BT_LOGD("Destroying CTF writer stream class: addr=%p, name=\"%s\", id=%" PRId64
,
170 stream_class
, bt_ctf_stream_class_get_name(stream_class
),
171 bt_ctf_stream_class_get_id(stream_class
));
172 bt_stream_class_common_finalize(BT_TO_COMMON(stream_class
));
173 bt_put(stream_class
->clock
);
174 g_free(stream_class
);
177 struct bt_ctf_stream_class
*bt_ctf_stream_class_create(const char *name
)
179 struct bt_ctf_stream_class
*stream_class
;
182 BT_LOGD("Creating CTF writer stream class object: name=\"%s\"", name
);
183 stream_class
= g_new0(struct bt_ctf_stream_class
, 1);
185 BT_LOGE_STR("Failed to allocate one CTF writer stream class.");
189 ret
= bt_stream_class_common_initialize(BT_TO_COMMON(stream_class
),
190 name
, bt_ctf_stream_class_destroy
);
192 /* bt_stream_class_common_initialize() logs errors */
196 ret
= init_event_header(stream_class
);
198 BT_LOGE_STR("Cannot initialize stream class's event header field type.");
202 ret
= init_packet_context(stream_class
);
204 BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
208 BT_LOGD("Created CTF writer stream class object: addr=%p, name=\"%s\"",
213 BT_PUT(stream_class
);
218 int try_map_clock_class(struct bt_ctf_stream_class
*stream_class
,
219 struct bt_ctf_field_type
*parent_ft
, const char *field_name
)
221 struct bt_ctf_clock_class
*mapped_clock_class
= NULL
;
223 struct bt_ctf_field_type
*ft
=
224 bt_ctf_field_type_structure_get_field_type_by_name(parent_ft
,
227 BT_ASSERT(stream_class
->clock
);
230 /* Field does not exist: not an error */
234 BT_ASSERT(((struct bt_field_type_common
*) ft
)->id
==
235 BT_FIELD_TYPE_ID_INTEGER
);
237 bt_ctf_field_type_integer_get_mapped_clock_class(ft
);
238 if (!mapped_clock_class
) {
239 struct bt_ctf_field_type
*ft_copy
;
241 if (!stream_class
->clock
) {
242 BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
243 "stream-class-addr=%p, stream-class-name=\"%s\", "
244 "stream-class-id=%" PRId64
", ft-addr=%p",
246 bt_ctf_stream_class_get_name(stream_class
),
247 bt_ctf_stream_class_get_id(stream_class
), ft
);
252 ft_copy
= bt_ctf_field_type_copy(ft
);
254 BT_LOGE("Failed to copy integer field type: ft-addr=%p",
258 ret
= bt_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
260 BT_TO_COMMON(stream_class
->clock
->clock_class
));
263 ret
= bt_field_type_common_structure_replace_field(
264 (void *) parent_ft
, field_name
, (void *) ft_copy
);
266 BT_LOGV("Automatically mapped field type to stream class's clock class: "
267 "stream-class-addr=%p, stream-class-name=\"%s\", "
268 "stream-class-id=%" PRId64
", ft-addr=%p, "
271 bt_ctf_stream_class_get_name(stream_class
),
272 bt_ctf_stream_class_get_id(stream_class
), ft
, ft_copy
);
277 bt_put(mapped_clock_class
);
282 int bt_ctf_stream_class_map_clock_class(
283 struct bt_ctf_stream_class
*stream_class
,
284 struct bt_ctf_field_type
*packet_context_type
,
285 struct bt_ctf_field_type
*event_header_type
)
289 BT_ASSERT(stream_class
);
291 if (!stream_class
->clock
) {
292 /* No clock class to map to */
296 if (packet_context_type
) {
297 if (try_map_clock_class(stream_class
, packet_context_type
,
298 "timestamp_begin")) {
299 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
304 if (try_map_clock_class(stream_class
, packet_context_type
,
306 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
312 if (event_header_type
) {
313 if (try_map_clock_class(stream_class
, event_header_type
,
315 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
325 struct bt_ctf_clock
*bt_ctf_stream_class_get_clock(
326 struct bt_ctf_stream_class
*stream_class
)
328 struct bt_ctf_clock
*clock
= NULL
;
331 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
335 if (!stream_class
->clock
) {
336 BT_LOGV("Stream class has no clock: "
337 "addr=%p, name=\"%s\", id=%" PRId64
,
339 bt_ctf_stream_class_get_name(stream_class
),
340 bt_ctf_stream_class_get_id(stream_class
));
344 clock
= bt_get(stream_class
->clock
);
350 int bt_ctf_stream_class_set_clock(
351 struct bt_ctf_stream_class
*stream_class
,
352 struct bt_ctf_clock
*clock
)
356 if (!stream_class
|| !clock
) {
357 BT_LOGW("Invalid parameter: stream class or clock is NULL: "
358 "stream-class-addr=%p, clock-addr=%p",
359 stream_class
, clock
);
364 if (stream_class
->common
.frozen
) {
365 BT_LOGW("Invalid parameter: stream class is frozen: "
366 "addr=%p, name=\"%s\", id=%" PRId64
,
368 bt_ctf_stream_class_get_name(stream_class
),
369 bt_ctf_stream_class_get_id(stream_class
));
374 /* Replace the current clock of this stream class. */
375 bt_put(stream_class
->clock
);
376 stream_class
->clock
= bt_get(clock
);
377 BT_LOGV("Set stream class's clock: "
378 "addr=%p, name=\"%s\", id=%" PRId64
", "
379 "clock-addr=%p, clock-name=\"%s\"",
381 bt_ctf_stream_class_get_name(stream_class
),
382 bt_ctf_stream_class_get_id(stream_class
),
384 bt_ctf_clock_get_name(stream_class
->clock
));
391 int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class
*stream_class
,
392 struct metadata_context
*context
)
396 struct bt_ctf_trace
*trace
;
397 struct bt_ctf_field_type
*packet_header_type
= NULL
;
399 BT_LOGD("Serializing stream class's metadata: "
400 "stream-class-addr=%p, stream-class-name=\"%s\", "
401 "stream-class-id=%" PRId64
", metadata-context-addr=%p",
403 bt_ctf_stream_class_get_name(stream_class
),
404 bt_ctf_stream_class_get_id(stream_class
), context
);
405 g_string_assign(context
->field_name
, "");
406 context
->current_indentation_level
= 1;
407 if (!stream_class
->common
.id_set
) {
408 BT_LOGW_STR("Stream class's ID is not set.");
413 g_string_append(context
->string
, "stream {\n");
416 * The reference to the trace is only borrowed since the
417 * serialization of the stream class might have been triggered
418 * by the trace's destruction. In such a case, the trace's
419 * reference count would, unexepectedly, go through the sequence
420 * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
423 trace
= BT_FROM_COMMON(bt_stream_class_common_borrow_trace(
424 BT_TO_COMMON(stream_class
)));
426 packet_header_type
= bt_ctf_trace_get_packet_header_field_type(trace
);
428 if (packet_header_type
) {
429 struct bt_ctf_field_type
*stream_id_type
;
432 bt_ctf_field_type_structure_get_field_type_by_name(
433 packet_header_type
, "stream_id");
434 if (stream_id_type
) {
436 * Only set the stream's id if the trace's packet header
437 * contains a stream_id field. This field is only
438 * needed if the trace contains only one stream
441 g_string_append_printf(context
->string
,
442 "\tid = %" PRId64
";\n",
443 stream_class
->common
.id
);
445 bt_put(stream_id_type
);
447 if (stream_class
->common
.event_header_field_type
) {
448 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
449 g_string_append(context
->string
, "\tevent.header := ");
450 ret
= bt_ctf_field_type_serialize_recursive(
451 (void *) stream_class
->common
.event_header_field_type
,
454 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
458 g_string_append(context
->string
, ";");
462 if (stream_class
->common
.packet_context_field_type
) {
463 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
464 g_string_append(context
->string
, "\n\n\tpacket.context := ");
465 ret
= bt_ctf_field_type_serialize_recursive(
466 (void *) stream_class
->common
.packet_context_field_type
,
469 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
473 g_string_append(context
->string
, ";");
476 if (stream_class
->common
.event_context_field_type
) {
477 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
478 g_string_append(context
->string
, "\n\n\tevent.context := ");
479 ret
= bt_ctf_field_type_serialize_recursive(
480 (void *) stream_class
->common
.event_context_field_type
,
483 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
487 g_string_append(context
->string
, ";");
490 g_string_append(context
->string
, "\n};\n\n");
492 for (i
= 0; i
< stream_class
->common
.event_classes
->len
; i
++) {
493 struct bt_ctf_event_class
*event_class
=
494 stream_class
->common
.event_classes
->pdata
[i
];
496 ret
= bt_ctf_event_class_serialize(event_class
, context
);
498 BT_LOGW("Cannot serialize event class's metadata: "
499 "event-class-addr=%p, event-class-name=\"%s\", "
500 "event-class-id=%" PRId64
,
502 bt_ctf_event_class_get_name(event_class
),
503 bt_ctf_event_class_get_id(event_class
));
509 bt_put(packet_header_type
);
510 context
->current_indentation_level
= 0;
514 struct bt_ctf_trace
*bt_ctf_stream_class_get_trace(
515 struct bt_ctf_stream_class
*stream_class
)
517 return bt_get(bt_stream_class_common_borrow_trace(
518 BT_TO_COMMON(stream_class
)));
521 const char *bt_ctf_stream_class_get_name(
522 struct bt_ctf_stream_class
*stream_class
)
524 return bt_stream_class_common_get_name(BT_TO_COMMON(stream_class
));
527 int bt_ctf_stream_class_set_name(
528 struct bt_ctf_stream_class
*stream_class
, const char *name
)
530 return bt_stream_class_common_set_name(BT_TO_COMMON(stream_class
),
534 int64_t bt_ctf_stream_class_get_id(
535 struct bt_ctf_stream_class
*stream_class
)
537 return bt_stream_class_common_get_id(BT_TO_COMMON(stream_class
));
540 int bt_ctf_stream_class_set_id(
541 struct bt_ctf_stream_class
*stream_class
, uint64_t id
)
543 return bt_stream_class_common_set_id(BT_TO_COMMON(stream_class
), id
);
546 struct bt_ctf_field_type
*bt_ctf_stream_class_get_packet_context_type(
547 struct bt_ctf_stream_class
*stream_class
)
550 bt_stream_class_common_borrow_packet_context_field_type(
551 BT_TO_COMMON(stream_class
)));
554 int bt_ctf_stream_class_set_packet_context_type(
555 struct bt_ctf_stream_class
*stream_class
,
556 struct bt_ctf_field_type
*packet_context_type
)
558 return bt_stream_class_common_set_packet_context_field_type(
559 BT_TO_COMMON(stream_class
), (void *) packet_context_type
);
562 struct bt_ctf_field_type
*
563 bt_ctf_stream_class_get_event_header_type(
564 struct bt_ctf_stream_class
*stream_class
)
567 bt_stream_class_common_borrow_event_header_field_type(
568 BT_TO_COMMON(stream_class
)));
571 int bt_ctf_stream_class_set_event_header_type(
572 struct bt_ctf_stream_class
*stream_class
,
573 struct bt_ctf_field_type
*event_header_type
)
575 return bt_stream_class_common_set_event_header_field_type(
576 BT_TO_COMMON(stream_class
), (void *) event_header_type
);
579 struct bt_ctf_field_type
*
580 bt_ctf_stream_class_get_event_context_type(
581 struct bt_ctf_stream_class
*stream_class
)
584 bt_stream_class_common_borrow_event_context_field_type(
585 BT_TO_COMMON(stream_class
)));
588 int bt_ctf_stream_class_set_event_context_type(
589 struct bt_ctf_stream_class
*stream_class
,
590 struct bt_ctf_field_type
*event_context_type
)
592 return bt_stream_class_common_set_event_context_field_type(
593 BT_TO_COMMON(stream_class
), (void *) event_context_type
);
596 int64_t bt_ctf_stream_class_get_event_class_count(
597 struct bt_ctf_stream_class
*stream_class
)
599 return bt_stream_class_common_get_event_class_count(
600 BT_TO_COMMON(stream_class
));
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
)
607 bt_stream_class_common_borrow_event_class_by_index(
608 BT_TO_COMMON(stream_class
), index
));
611 struct bt_ctf_event_class
*bt_ctf_stream_class_get_event_class_by_id(
612 struct bt_ctf_stream_class
*stream_class
, uint64_t id
)
615 bt_stream_class_common_borrow_event_class_by_id(
616 BT_TO_COMMON(stream_class
), id
));
619 int bt_ctf_stream_class_add_event_class(
620 struct bt_ctf_stream_class
*stream_class
,
621 struct bt_ctf_event_class
*event_class
)
623 return bt_stream_class_common_add_event_class(
624 BT_TO_COMMON(stream_class
), BT_TO_COMMON(event_class
),
625 (bt_validation_flag_copy_field_type_func
) bt_ctf_field_type_copy
);