Split the CTF-Writer implementation in IR and Writer parts
[babeltrace.git] / formats / ctf / ir / stream-class.c
CommitLineData
11b0cdc8
JG
1/*
2 * stream.c
3 *
4 * Babeltrace CTF Writer
5 *
6 * Copyright 2013 EfficiOS Inc.
7 *
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 *
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:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
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
26 * SOFTWARE.
27 */
28
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>
40
41static
42void bt_ctf_stream_class_destroy(struct bt_ctf_ref *ref);
43static
44int init_event_header(struct bt_ctf_stream_class *stream_class,
45 enum bt_ctf_byte_order byte_order);
46static
47int init_packet_context(struct bt_ctf_stream_class *stream_class,
48 enum bt_ctf_byte_order byte_order);
49
50struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *name)
51{
52 struct bt_ctf_stream_class *stream_class = NULL;
53
54 if (!name || !strlen(name)) {
55 goto error;
56 }
57
58 stream_class = g_new0(struct bt_ctf_stream_class, 1);
59 if (!stream_class) {
60 goto error;
61 }
62
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) {
67 goto error_destroy;
68 }
69
70 bt_ctf_ref_init(&stream_class->ref_count);
71 return stream_class;
72
73error_destroy:
74 bt_ctf_stream_class_destroy(&stream_class->ref_count);
75 stream_class = NULL;
76error:
77 return stream_class;
78}
79
80int bt_ctf_stream_class_set_clock(struct bt_ctf_stream_class *stream_class,
81 struct bt_ctf_clock *clock)
82{
83 int ret = 0;
84
85 if (!stream_class || !clock || stream_class->frozen) {
86 ret = -1;
87 goto end;
88 }
89
90 if (stream_class->clock) {
91 bt_ctf_clock_put(stream_class->clock);
92 }
93
94 stream_class->clock = clock;
95 bt_ctf_clock_get(clock);
96end:
97 return ret;
98}
99
100int bt_ctf_stream_class_add_event_class(
101 struct bt_ctf_stream_class *stream_class,
102 struct bt_ctf_event_class *event_class)
103{
104 int ret = 0;
105
106 if (!stream_class || !event_class) {
107 ret = -1;
108 goto end;
109 }
110
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);
114 if (query.found) {
115 ret = -1;
116 goto end;
117 }
118
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 */
122 ret = -1;
123 goto end;
124 }
125
126 bt_ctf_event_class_get(event_class);
127 g_ptr_array_add(stream_class->event_classes, event_class);
128end:
129 return ret;
130}
131
132void bt_ctf_stream_class_get(struct bt_ctf_stream_class *stream_class)
133{
134 if (!stream_class) {
135 return;
136 }
137
138 bt_ctf_ref_get(&stream_class->ref_count);
139}
140
141void bt_ctf_stream_class_put(struct bt_ctf_stream_class *stream_class)
142{
143 if (!stream_class) {
144 return;
145 }
146
147 bt_ctf_ref_put(&stream_class->ref_count, bt_ctf_stream_class_destroy);
148}
149
150BT_HIDDEN
151void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class *stream_class)
152{
153 if (!stream_class) {
154 return;
155 }
156
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);
161}
162
163BT_HIDDEN
164int bt_ctf_stream_class_set_id(struct bt_ctf_stream_class *stream_class,
165 uint32_t id)
166{
167 int ret = 0;
168
169 if (!stream_class ||
170 (stream_class->id_set && (id != stream_class->id))) {
171 ret = -1;
172 goto end;
173 }
174
175 stream_class->id = id;
176 stream_class->id_set = 1;
177end:
178 return ret;
179}
180
181BT_HIDDEN
182int bt_ctf_stream_class_set_byte_order(struct bt_ctf_stream_class *stream_class,
183 enum bt_ctf_byte_order byte_order)
184{
185 int ret = 0;
186
187 ret = init_packet_context(stream_class, byte_order);
188 if (ret) {
189 goto end;
190 }
191
192 ret = init_event_header(stream_class, byte_order);
193 if (ret) {
194 goto end;
195 }
196end:
197 return ret;
198}
199
200BT_HIDDEN
201int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
202 struct metadata_context *context)
203{
204 int ret = 0;
205 size_t i;
206
207 g_string_assign(context->field_name, "");
208 context->current_indentation_level = 1;
209 if (!stream_class->id_set) {
210 ret = -1;
211 goto end;
212 }
213
214 g_string_append_printf(context->string,
215 "stream {\n\tid = %" PRIu32 ";\n\tevent.header := ",
216 stream_class->id);
217 ret = bt_ctf_field_type_serialize(stream_class->event_header_type,
218 context);
219 if (ret) {
220 goto end;
221 }
222
223 g_string_append(context->string, ";\n\n\tpacket.context := ");
224 ret = bt_ctf_field_type_serialize(stream_class->packet_context_type,
225 context);
226 if (ret) {
227 goto end;
228 }
229
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);
234 if (ret) {
235 goto end;
236 }
237 }
238
239 g_string_append(context->string, ";\n};\n\n");
240
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];
248
249 ret = bt_ctf_event_class_set_stream_id(event_class,
250 stream_class->id);
251 if (ret) {
252 goto end;
253 }
254
255 ret = bt_ctf_event_class_serialize(event_class, context);
256 if (ret) {
257 goto end;
258 }
259 }
260end:
261 context->current_indentation_level = 0;
262 return ret;
263}
264
265static
266void bt_ctf_stream_class_destroy(struct bt_ctf_ref *ref)
267{
268 struct bt_ctf_stream_class *stream_class;
269
270 if (!ref) {
271 return;
272 }
273
274 stream_class = container_of(ref, struct bt_ctf_stream_class, ref_count);
275 bt_ctf_clock_put(stream_class->clock);
276
277 if (stream_class->event_classes) {
278 g_ptr_array_free(stream_class->event_classes, TRUE);
279 }
280
281 if (stream_class->name) {
282 g_string_free(stream_class->name, TRUE);
283 }
284
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);
292}
293
294static
295int init_event_header(struct bt_ctf_stream_class *stream_class,
296 enum bt_ctf_byte_order byte_order)
297{
298 int ret = 0;
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);
305
306 if (!event_header_type) {
307 ret = -1;
308 goto end;
309 }
310
311 ret = bt_ctf_field_type_set_byte_order(_uint32_t, byte_order);
312 if (ret) {
313 goto end;
314 }
315
316 ret = bt_ctf_field_type_set_byte_order(_uint64_t, byte_order);
317 if (ret) {
318 goto end;
319 }
320
321 ret = bt_ctf_field_type_structure_add_field(event_header_type,
322 _uint32_t, "id");
323 if (ret) {
324 goto end;
325 }
326
327 ret = bt_ctf_field_type_structure_add_field(event_header_type,
328 _uint64_t, "timestamp");
329 if (ret) {
330 goto end;
331 }
332
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) {
337 ret = -1;
338 }
339end:
340 if (ret) {
341 bt_ctf_field_type_put(event_header_type);
342 }
343
344 bt_ctf_field_type_put(_uint32_t);
345 bt_ctf_field_type_put(_uint64_t);
346 return ret;
347}
348
349static
350int init_packet_context(struct bt_ctf_stream_class *stream_class,
351 enum bt_ctf_byte_order byte_order)
352{
353 int ret = 0;
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);
358
359 if (!packet_context_type) {
360 ret = -1;
361 goto end;
362 }
363
364 /*
365 * We create a stream packet context as proposed in the CTF
366 * specification.
367 */
368 ret = bt_ctf_field_type_set_byte_order(_uint64_t, byte_order);
369 if (ret) {
370 goto end;
371 }
372
373 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
374 _uint64_t, "timestamp_begin");
375 if (ret) {
376 goto end;
377 }
378
379 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
380 _uint64_t, "timestamp_end");
381 if (ret) {
382 goto end;
383 }
384
385 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
386 _uint64_t, "content_size");
387 if (ret) {
388 goto end;
389 }
390
391 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
392 _uint64_t, "packet_size");
393 if (ret) {
394 goto end;
395 }
396
397 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
398 _uint64_t, "events_discarded");
399 if (ret) {
400 goto end;
401 }
402
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) {
406 ret = -1;
407 }
408end:
409 if (ret) {
410 bt_ctf_field_type_put(packet_context_type);
411 goto end;
412 }
413
414 bt_ctf_field_type_put(_uint64_t);
415 return ret;
416}
This page took 0.037152 seconds and 4 git commands to generate.