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