Cleanup: Use a switch case instead of conditionals
[babeltrace.git] / formats / ctf / ir / stream-class.c
CommitLineData
11b0cdc8 1/*
3f043b05 2 * stream-class.c
11b0cdc8 3 *
d2dc44b6 4 * Babeltrace CTF IR - Stream Class
11b0cdc8 5 *
de9dd397 6 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
11b0cdc8
JG
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>
654c1444 38#include <babeltrace/ctf-ir/utils.h>
11b0cdc8
JG
39#include <babeltrace/compiler.h>
40#include <babeltrace/align.h>
41
42static
43void bt_ctf_stream_class_destroy(struct bt_ctf_ref *ref);
44static
45int init_event_header(struct bt_ctf_stream_class *stream_class,
46 enum bt_ctf_byte_order byte_order);
47static
48int init_packet_context(struct bt_ctf_stream_class *stream_class,
49 enum bt_ctf_byte_order byte_order);
50
51struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *name)
52{
12c8a1a3 53 int ret;
11b0cdc8
JG
54 struct bt_ctf_stream_class *stream_class = NULL;
55
654c1444 56 if (!name || !strlen(name) || bt_ctf_validate_identifier(name)) {
11b0cdc8
JG
57 goto error;
58 }
59
60 stream_class = g_new0(struct bt_ctf_stream_class, 1);
61 if (!stream_class) {
62 goto error;
63 }
64
65 stream_class->name = g_string_new(name);
66 stream_class->event_classes = g_ptr_array_new_with_free_func(
67 (GDestroyNotify)bt_ctf_event_class_put);
68 if (!stream_class->event_classes) {
69 goto error_destroy;
70 }
71
12c8a1a3
JG
72 ret = init_packet_context(stream_class, BT_CTF_BYTE_ORDER_NATIVE);
73 if (ret) {
74 goto error_destroy;
75 }
76
11b0cdc8
JG
77 bt_ctf_ref_init(&stream_class->ref_count);
78 return stream_class;
79
80error_destroy:
81 bt_ctf_stream_class_destroy(&stream_class->ref_count);
82 stream_class = NULL;
83error:
84 return stream_class;
85}
86
69dc4535
JG
87const char *bt_ctf_stream_class_get_name(
88 struct bt_ctf_stream_class *stream_class)
89{
90 const char *name = NULL;
91
92 if (!stream_class) {
93 goto end;
94 }
95
96 name = stream_class->name->str;
97end:
98 return name;
99}
100
2f100782
JG
101struct bt_ctf_clock *bt_ctf_stream_class_get_clock(
102 struct bt_ctf_stream_class *stream_class)
103{
104 struct bt_ctf_clock *clock = NULL;
105
106 if (!stream_class || !stream_class->clock) {
107 goto end;
108 }
109
110 clock = stream_class->clock;
111 bt_ctf_clock_get(clock);
112end:
113 return clock;
114}
115
11b0cdc8
JG
116int bt_ctf_stream_class_set_clock(struct bt_ctf_stream_class *stream_class,
117 struct bt_ctf_clock *clock)
118{
119 int ret = 0;
120
121 if (!stream_class || !clock || stream_class->frozen) {
122 ret = -1;
123 goto end;
124 }
125
126 if (stream_class->clock) {
127 bt_ctf_clock_put(stream_class->clock);
128 }
129
130 stream_class->clock = clock;
131 bt_ctf_clock_get(clock);
132end:
133 return ret;
134}
135
2f100782
JG
136int64_t bt_ctf_stream_class_get_id(struct bt_ctf_stream_class *stream_class)
137{
138 int64_t ret;
139
140 if (!stream_class || !stream_class->id_set) {
141 ret = -1;
142 goto end;
143 }
144
145 ret = (int64_t) stream_class->id;
146end:
147 return ret;
148}
149
150int bt_ctf_stream_class_set_id(struct bt_ctf_stream_class *stream_class,
151 uint32_t id)
152{
153 int ret = 0;
154
739a93c7 155 if (!stream_class || stream_class->frozen) {
2f100782
JG
156 ret = -1;
157 goto end;
158 }
159
160 stream_class->id = id;
161 stream_class->id_set = 1;
162end:
163 return ret;
164}
165
11b0cdc8
JG
166int bt_ctf_stream_class_add_event_class(
167 struct bt_ctf_stream_class *stream_class,
168 struct bt_ctf_event_class *event_class)
169{
170 int ret = 0;
2f100782 171 int64_t event_id;
11b0cdc8
JG
172
173 if (!stream_class || !event_class) {
174 ret = -1;
175 goto end;
176 }
177
178 /* Check for duplicate event classes */
179 struct search_query query = { .value = event_class, .found = 0 };
180 g_ptr_array_foreach(stream_class->event_classes, value_exists, &query);
181 if (query.found) {
182 ret = -1;
183 goto end;
184 }
185
2f100782
JG
186 /* Only set an event id if none was explicitly set before */
187 event_id = bt_ctf_event_class_get_id(event_class);
188 if (event_id < 0) {
189 if (bt_ctf_event_class_set_id(event_class,
190 stream_class->next_event_id++)) {
191 ret = -1;
192 goto end;
193 }
194 }
195
196 ret = bt_ctf_event_class_set_stream_class(event_class, stream_class);
197 if (ret) {
11b0cdc8
JG
198 goto end;
199 }
200
201 bt_ctf_event_class_get(event_class);
202 g_ptr_array_add(stream_class->event_classes, event_class);
203end:
204 return ret;
205}
206
074ee56d 207int bt_ctf_stream_class_get_event_class_count(
69dc4535
JG
208 struct bt_ctf_stream_class *stream_class)
209{
074ee56d 210 int ret;
69dc4535
JG
211
212 if (!stream_class) {
213 ret = -1;
214 goto end;
215 }
216
074ee56d 217 ret = (int) stream_class->event_classes->len;
69dc4535
JG
218end:
219 return ret;
220}
221
222struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class(
074ee56d 223 struct bt_ctf_stream_class *stream_class, int index)
69dc4535
JG
224{
225 struct bt_ctf_event_class *event_class = NULL;
226
074ee56d
JG
227 if (!stream_class || index < 0 ||
228 index >= stream_class->event_classes->len) {
69dc4535
JG
229 goto end;
230 }
231
232 event_class = g_ptr_array_index(stream_class->event_classes, index);
233 bt_ctf_event_class_get(event_class);
234end:
235 return event_class;
236}
237
238struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_name(
239 struct bt_ctf_stream_class *stream_class, const char *name)
240{
241 size_t i;
242 GQuark name_quark;
243 struct bt_ctf_event_class *event_class = NULL;
244
245 if (!stream_class || !name) {
246 goto end;
247 }
248
249 name_quark = g_quark_try_string(name);
250 if (!name_quark) {
251 goto end;
252 }
253
254 for (i = 0; i < stream_class->event_classes->len; i++) {
255 struct bt_ctf_event_class *current_event_class =
256 g_ptr_array_index(stream_class->event_classes, i);
257
258 if (name_quark == current_event_class->name) {
259 event_class = current_event_class;
260 bt_ctf_event_class_get(event_class);
261 goto end;
262 }
263 }
264end:
265 return event_class;
266}
267
12c8a1a3
JG
268struct bt_ctf_field_type *bt_ctf_stream_class_get_packet_context_type(
269 struct bt_ctf_stream_class *stream_class)
270{
271 struct bt_ctf_field_type *ret = NULL;
272
273 if (!stream_class) {
274 goto end;
275 }
276
277 assert(stream_class->packet_context_type);
278 bt_ctf_field_type_get(stream_class->packet_context_type);
279 ret = stream_class->packet_context_type;
280end:
281 return ret;
282}
283
284int bt_ctf_stream_class_set_packet_context_type(
285 struct bt_ctf_stream_class *stream_class,
286 struct bt_ctf_field_type *packet_context_type)
287{
288 int ret = 0;
289
0a00bfa1 290 if (!stream_class || !packet_context_type || stream_class->frozen) {
12c8a1a3
JG
291 ret = -1;
292 goto end;
293 }
294
295 assert(stream_class->packet_context_type);
b34f4d90 296 if (bt_ctf_field_type_get_type_id(packet_context_type) !=
12c8a1a3
JG
297 CTF_TYPE_STRUCT) {
298 /* A packet context must be a structure */
299 ret = -1;
300 goto end;
301 }
302
303 bt_ctf_field_type_put(stream_class->packet_context_type);
304 bt_ctf_field_type_get(packet_context_type);
305 stream_class->packet_context_type = packet_context_type;
306end:
307 return ret;
308}
309
af181248
JG
310struct bt_ctf_field_type *bt_ctf_stream_class_get_event_context_type(
311 struct bt_ctf_stream_class *stream_class)
312{
313 struct bt_ctf_field_type *ret = NULL;
314
315 if (!stream_class || !stream_class->event_context_type) {
316 goto end;
317 }
318
319 assert(stream_class->event_context_type);
320 bt_ctf_field_type_get(stream_class->event_context_type);
321 ret = stream_class->event_context_type;
322end:
323 return ret;
324}
325
326int bt_ctf_stream_class_set_event_context_type(
327 struct bt_ctf_stream_class *stream_class,
328 struct bt_ctf_field_type *event_context_type)
329{
330 int ret = 0;
331
332 if (!stream_class || !event_context_type || stream_class->frozen) {
333 ret = -1;
334 goto end;
335 }
336
337 if (bt_ctf_field_type_get_type_id(event_context_type) !=
338 CTF_TYPE_STRUCT) {
339 /* A packet context must be a structure */
340 ret = -1;
341 goto end;
342 }
343
344 bt_ctf_field_type_put(stream_class->event_context_type);
345 bt_ctf_field_type_get(event_context_type);
346 stream_class->event_context_type = event_context_type;
347end:
348 return ret;
349}
350
11b0cdc8
JG
351void bt_ctf_stream_class_get(struct bt_ctf_stream_class *stream_class)
352{
353 if (!stream_class) {
354 return;
355 }
356
357 bt_ctf_ref_get(&stream_class->ref_count);
358}
359
360void bt_ctf_stream_class_put(struct bt_ctf_stream_class *stream_class)
361{
362 if (!stream_class) {
363 return;
364 }
365
366 bt_ctf_ref_put(&stream_class->ref_count, bt_ctf_stream_class_destroy);
367}
368
369BT_HIDDEN
370void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class *stream_class)
371{
c35a1669
JG
372 size_t i;
373
11b0cdc8
JG
374 if (!stream_class) {
375 return;
376 }
377
378 stream_class->frozen = 1;
12c8a1a3 379 bt_ctf_field_type_freeze(stream_class->packet_context_type);
af181248 380 bt_ctf_field_type_freeze(stream_class->event_context_type);
11b0cdc8 381 bt_ctf_clock_freeze(stream_class->clock);
c35a1669
JG
382
383 bt_ctf_field_type_set_native_byte_order(
384 stream_class->event_header_type, stream_class->byte_order);
385 bt_ctf_field_type_set_native_byte_order(
386 stream_class->packet_context_type, stream_class->byte_order);
387 bt_ctf_field_type_set_native_byte_order(
388 stream_class->event_context_type, stream_class->byte_order);
389 for (i = 0; i < stream_class->event_classes->len; i++) {
390 bt_ctf_event_class_set_native_byte_order(
391 g_ptr_array_index(stream_class->event_classes, i),
392 stream_class->byte_order);
393 bt_ctf_event_class_freeze(
394 g_ptr_array_index(stream_class->event_classes, i));
395 }
11b0cdc8
JG
396}
397
11b0cdc8
JG
398BT_HIDDEN
399int bt_ctf_stream_class_set_byte_order(struct bt_ctf_stream_class *stream_class,
400 enum bt_ctf_byte_order byte_order)
401{
402 int ret = 0;
c35a1669 403 int internal_byte_order;
11b0cdc8 404
c35a1669
JG
405 /* Note that "NATIVE" means the trace's endianness, not the host's. */
406 if (!stream_class || byte_order <= BT_CTF_BYTE_ORDER_UNKNOWN ||
407 byte_order > BT_CTF_BYTE_ORDER_NETWORK ||
408 stream_class->frozen) {
409 ret = -1;
410 goto end;
411 }
412
413 switch (byte_order) {
414 case BT_CTF_BYTE_ORDER_NETWORK:
415 case BT_CTF_BYTE_ORDER_BIG_ENDIAN:
416 internal_byte_order = BIG_ENDIAN;
417 break;
418 case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN:
419 internal_byte_order = LITTLE_ENDIAN;
420 break;
421 default:
422 ret = -1;
11b0cdc8
JG
423 goto end;
424 }
c35a1669
JG
425
426 stream_class->byte_order = internal_byte_order;
11b0cdc8
JG
427end:
428 return ret;
429}
430
431BT_HIDDEN
432int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
433 struct metadata_context *context)
434{
2f100782 435 int64_t ret = 0;
11b0cdc8
JG
436 size_t i;
437
438 g_string_assign(context->field_name, "");
439 context->current_indentation_level = 1;
440 if (!stream_class->id_set) {
441 ret = -1;
442 goto end;
443 }
444
445 g_string_append_printf(context->string,
446 "stream {\n\tid = %" PRIu32 ";\n\tevent.header := ",
447 stream_class->id);
448 ret = bt_ctf_field_type_serialize(stream_class->event_header_type,
449 context);
450 if (ret) {
451 goto end;
452 }
453
454 g_string_append(context->string, ";\n\n\tpacket.context := ");
455 ret = bt_ctf_field_type_serialize(stream_class->packet_context_type,
456 context);
457 if (ret) {
458 goto end;
459 }
460
461 if (stream_class->event_context_type) {
462 g_string_append(context->string, ";\n\n\tevent.context := ");
463 ret = bt_ctf_field_type_serialize(
464 stream_class->event_context_type, context);
465 if (ret) {
466 goto end;
467 }
468 }
469
470 g_string_append(context->string, ";\n};\n\n");
11b0cdc8
JG
471 for (i = 0; i < stream_class->event_classes->len; i++) {
472 struct bt_ctf_event_class *event_class =
473 stream_class->event_classes->pdata[i];
474
11b0cdc8
JG
475 ret = bt_ctf_event_class_serialize(event_class, context);
476 if (ret) {
477 goto end;
478 }
479 }
480end:
481 context->current_indentation_level = 0;
482 return ret;
483}
484
485static
486void bt_ctf_stream_class_destroy(struct bt_ctf_ref *ref)
487{
488 struct bt_ctf_stream_class *stream_class;
489
490 if (!ref) {
491 return;
492 }
493
494 stream_class = container_of(ref, struct bt_ctf_stream_class, ref_count);
495 bt_ctf_clock_put(stream_class->clock);
496
497 if (stream_class->event_classes) {
2f100782
JG
498 size_t i;
499
500 /* Unregister this stream class from the event classes */
501 for (i = 0; i < stream_class->event_classes->len; i++) {
502 struct bt_ctf_event_class *event_class =
503 g_ptr_array_index(stream_class->event_classes,
504 i);
505
506 bt_ctf_event_class_set_stream_class(event_class, NULL);
507 }
508
11b0cdc8
JG
509 g_ptr_array_free(stream_class->event_classes, TRUE);
510 }
511
512 if (stream_class->name) {
513 g_string_free(stream_class->name, TRUE);
514 }
515
516 bt_ctf_field_type_put(stream_class->event_header_type);
de876b7f 517 bt_ctf_field_put(stream_class->event_header);
11b0cdc8 518 bt_ctf_field_type_put(stream_class->packet_context_type);
af181248
JG
519 if (stream_class->event_context_type) {
520 bt_ctf_field_type_put(stream_class->event_context_type);
521 }
11b0cdc8
JG
522 g_free(stream_class);
523}
524
525static
526int init_event_header(struct bt_ctf_stream_class *stream_class,
527 enum bt_ctf_byte_order byte_order)
528{
529 int ret = 0;
530 struct bt_ctf_field_type *event_header_type =
531 bt_ctf_field_type_structure_create();
532 struct bt_ctf_field_type *_uint32_t =
533 get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
534 struct bt_ctf_field_type *_uint64_t =
535 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
536
537 if (!event_header_type) {
538 ret = -1;
539 goto end;
540 }
541
11b0cdc8
JG
542 ret = bt_ctf_field_type_structure_add_field(event_header_type,
543 _uint32_t, "id");
544 if (ret) {
545 goto end;
546 }
547
548 ret = bt_ctf_field_type_structure_add_field(event_header_type,
549 _uint64_t, "timestamp");
550 if (ret) {
551 goto end;
552 }
553
554 stream_class->event_header_type = event_header_type;
de876b7f
JG
555 stream_class->event_header = bt_ctf_field_create(
556 stream_class->event_header_type);
557 if (!stream_class->event_header) {
558 ret = -1;
559 }
11b0cdc8
JG
560end:
561 if (ret) {
562 bt_ctf_field_type_put(event_header_type);
563 }
564
565 bt_ctf_field_type_put(_uint32_t);
566 bt_ctf_field_type_put(_uint64_t);
567 return ret;
568}
569
570static
571int init_packet_context(struct bt_ctf_stream_class *stream_class,
572 enum bt_ctf_byte_order byte_order)
573{
574 int ret = 0;
575 struct bt_ctf_field_type *packet_context_type =
576 bt_ctf_field_type_structure_create();
577 struct bt_ctf_field_type *_uint64_t =
578 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
579
580 if (!packet_context_type) {
581 ret = -1;
582 goto end;
583 }
584
585 /*
586 * We create a stream packet context as proposed in the CTF
587 * specification.
588 */
11b0cdc8
JG
589 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
590 _uint64_t, "timestamp_begin");
591 if (ret) {
592 goto end;
593 }
594
595 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
596 _uint64_t, "timestamp_end");
597 if (ret) {
598 goto end;
599 }
600
601 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
602 _uint64_t, "content_size");
603 if (ret) {
604 goto end;
605 }
606
607 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
608 _uint64_t, "packet_size");
609 if (ret) {
610 goto end;
611 }
612
613 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
614 _uint64_t, "events_discarded");
615 if (ret) {
616 goto end;
617 }
618
619 stream_class->packet_context_type = packet_context_type;
11b0cdc8
JG
620end:
621 if (ret) {
622 bt_ctf_field_type_put(packet_context_type);
623 goto end;
624 }
625
626 bt_ctf_field_type_put(_uint64_t);
627 return ret;
628}
This page took 0.051012 seconds and 4 git commands to generate.