4 * Babeltrace CTF Writer
6 * Copyright 2013 EfficiOS Inc.
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 #include <babeltrace/ctf-writer/clock.h>
30 #include <babeltrace/ctf-ir/clock-internal.h>
31 #include <babeltrace/ctf-writer/event.h>
32 #include <babeltrace/ctf-ir/event-internal.h>
33 #include <babeltrace/ctf-ir/event-types-internal.h>
34 #include <babeltrace/ctf-ir/event-fields-internal.h>
35 #include <babeltrace/ctf-writer/stream.h>
36 #include <babeltrace/ctf-ir/stream-class-internal.h>
37 #include <babeltrace/ctf-writer/functor-internal.h>
38 #include <babeltrace/compiler.h>
39 #include <babeltrace/align.h>
42 void bt_ctf_stream_class_destroy(struct bt_ctf_ref
*ref
);
44 int init_event_header(struct bt_ctf_stream_class
*stream_class
,
45 enum bt_ctf_byte_order byte_order
);
47 int init_packet_context(struct bt_ctf_stream_class
*stream_class
,
48 enum bt_ctf_byte_order byte_order
);
50 struct bt_ctf_stream_class
*bt_ctf_stream_class_create(const char *name
)
52 struct bt_ctf_stream_class
*stream_class
= NULL
;
54 if (!name
|| !strlen(name
)) {
58 stream_class
= g_new0(struct bt_ctf_stream_class
, 1);
63 stream_class
->name
= g_string_new(name
);
64 stream_class
->event_classes
= g_ptr_array_new_with_free_func(
65 (GDestroyNotify
)bt_ctf_event_class_put
);
66 if (!stream_class
->event_classes
) {
70 bt_ctf_ref_init(&stream_class
->ref_count
);
74 bt_ctf_stream_class_destroy(&stream_class
->ref_count
);
80 int bt_ctf_stream_class_set_clock(struct bt_ctf_stream_class
*stream_class
,
81 struct bt_ctf_clock
*clock
)
85 if (!stream_class
|| !clock
|| stream_class
->frozen
) {
90 if (stream_class
->clock
) {
91 bt_ctf_clock_put(stream_class
->clock
);
94 stream_class
->clock
= clock
;
95 bt_ctf_clock_get(clock
);
100 int bt_ctf_stream_class_add_event_class(
101 struct bt_ctf_stream_class
*stream_class
,
102 struct bt_ctf_event_class
*event_class
)
106 if (!stream_class
|| !event_class
) {
111 /* Check for duplicate event classes */
112 struct search_query query
= { .value
= event_class
, .found
= 0 };
113 g_ptr_array_foreach(stream_class
->event_classes
, value_exists
, &query
);
119 if (bt_ctf_event_class_set_id(event_class
,
120 stream_class
->next_event_id
++)) {
121 /* The event is already associated to a stream class */
126 bt_ctf_event_class_get(event_class
);
127 g_ptr_array_add(stream_class
->event_classes
, event_class
);
132 void bt_ctf_stream_class_get(struct bt_ctf_stream_class
*stream_class
)
138 bt_ctf_ref_get(&stream_class
->ref_count
);
141 void bt_ctf_stream_class_put(struct bt_ctf_stream_class
*stream_class
)
147 bt_ctf_ref_put(&stream_class
->ref_count
, bt_ctf_stream_class_destroy
);
151 void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class
*stream_class
)
157 stream_class
->frozen
= 1;
158 bt_ctf_clock_freeze(stream_class
->clock
);
159 g_ptr_array_foreach(stream_class
->event_classes
,
160 (GFunc
)bt_ctf_event_class_freeze
, NULL
);
164 int bt_ctf_stream_class_set_id(struct bt_ctf_stream_class
*stream_class
,
170 (stream_class
->id_set
&& (id
!= stream_class
->id
))) {
175 stream_class
->id
= id
;
176 stream_class
->id_set
= 1;
182 int bt_ctf_stream_class_set_byte_order(struct bt_ctf_stream_class
*stream_class
,
183 enum bt_ctf_byte_order byte_order
)
187 ret
= init_packet_context(stream_class
, byte_order
);
192 ret
= init_event_header(stream_class
, byte_order
);
201 int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class
*stream_class
,
202 struct metadata_context
*context
)
207 g_string_assign(context
->field_name
, "");
208 context
->current_indentation_level
= 1;
209 if (!stream_class
->id_set
) {
214 g_string_append_printf(context
->string
,
215 "stream {\n\tid = %" PRIu32
";\n\tevent.header := ",
217 ret
= bt_ctf_field_type_serialize(stream_class
->event_header_type
,
223 g_string_append(context
->string
, ";\n\n\tpacket.context := ");
224 ret
= bt_ctf_field_type_serialize(stream_class
->packet_context_type
,
230 if (stream_class
->event_context_type
) {
231 g_string_append(context
->string
, ";\n\n\tevent.context := ");
232 ret
= bt_ctf_field_type_serialize(
233 stream_class
->event_context_type
, context
);
239 g_string_append(context
->string
, ";\n};\n\n");
241 /* Assign this stream's ID to every event and serialize them */
242 g_ptr_array_foreach(stream_class
->event_classes
,
243 (GFunc
) bt_ctf_event_class_set_stream_id
,
244 GUINT_TO_POINTER(stream_class
->id
));
245 for (i
= 0; i
< stream_class
->event_classes
->len
; i
++) {
246 struct bt_ctf_event_class
*event_class
=
247 stream_class
->event_classes
->pdata
[i
];
249 ret
= bt_ctf_event_class_set_stream_id(event_class
,
255 ret
= bt_ctf_event_class_serialize(event_class
, context
);
261 context
->current_indentation_level
= 0;
266 void bt_ctf_stream_class_destroy(struct bt_ctf_ref
*ref
)
268 struct bt_ctf_stream_class
*stream_class
;
274 stream_class
= container_of(ref
, struct bt_ctf_stream_class
, ref_count
);
275 bt_ctf_clock_put(stream_class
->clock
);
277 if (stream_class
->event_classes
) {
278 g_ptr_array_free(stream_class
->event_classes
, TRUE
);
281 if (stream_class
->name
) {
282 g_string_free(stream_class
->name
, TRUE
);
285 bt_ctf_field_type_put(stream_class
->event_header_type
);
286 bt_ctf_field_put(stream_class
->event_header
);
287 bt_ctf_field_type_put(stream_class
->packet_context_type
);
288 bt_ctf_field_put(stream_class
->packet_context
);
289 bt_ctf_field_type_put(stream_class
->event_context_type
);
290 bt_ctf_field_put(stream_class
->event_context
);
291 g_free(stream_class
);
295 int init_event_header(struct bt_ctf_stream_class
*stream_class
,
296 enum bt_ctf_byte_order byte_order
)
299 struct bt_ctf_field_type
*event_header_type
=
300 bt_ctf_field_type_structure_create();
301 struct bt_ctf_field_type
*_uint32_t
=
302 get_field_type(FIELD_TYPE_ALIAS_UINT32_T
);
303 struct bt_ctf_field_type
*_uint64_t
=
304 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
306 if (!event_header_type
) {
311 ret
= bt_ctf_field_type_set_byte_order(_uint32_t
, byte_order
);
316 ret
= bt_ctf_field_type_set_byte_order(_uint64_t
, byte_order
);
321 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
327 ret
= bt_ctf_field_type_structure_add_field(event_header_type
,
328 _uint64_t
, "timestamp");
333 stream_class
->event_header_type
= event_header_type
;
334 stream_class
->event_header
= bt_ctf_field_create(
335 stream_class
->event_header_type
);
336 if (!stream_class
->event_header
) {
341 bt_ctf_field_type_put(event_header_type
);
344 bt_ctf_field_type_put(_uint32_t
);
345 bt_ctf_field_type_put(_uint64_t
);
350 int init_packet_context(struct bt_ctf_stream_class
*stream_class
,
351 enum bt_ctf_byte_order byte_order
)
354 struct bt_ctf_field_type
*packet_context_type
=
355 bt_ctf_field_type_structure_create();
356 struct bt_ctf_field_type
*_uint64_t
=
357 get_field_type(FIELD_TYPE_ALIAS_UINT64_T
);
359 if (!packet_context_type
) {
365 * We create a stream packet context as proposed in the CTF
368 ret
= bt_ctf_field_type_set_byte_order(_uint64_t
, byte_order
);
373 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
374 _uint64_t
, "timestamp_begin");
379 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
380 _uint64_t
, "timestamp_end");
385 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
386 _uint64_t
, "content_size");
391 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
392 _uint64_t
, "packet_size");
397 ret
= bt_ctf_field_type_structure_add_field(packet_context_type
,
398 _uint64_t
, "events_discarded");
403 stream_class
->packet_context_type
= packet_context_type
;
404 stream_class
->packet_context
= bt_ctf_field_create(packet_context_type
);
405 if (!stream_class
->packet_context
) {
410 bt_ctf_field_type_put(packet_context_type
);
414 bt_ctf_field_type_put(_uint64_t
);