Add bt_ctf_stream_class_create_empty()
[babeltrace.git] / lib / ctf-ir / stream-class.c
1 /*
2 * stream-class.c
3 *
4 * Babeltrace CTF IR - Stream Class
5 *
6 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
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-writer/clock-internal.h>
31 #include <babeltrace/ctf-ir/clock-class-internal.h>
32 #include <babeltrace/ctf-writer/event.h>
33 #include <babeltrace/ctf-ir/event-class-internal.h>
34 #include <babeltrace/ctf-ir/event-internal.h>
35 #include <babeltrace/ctf-ir/field-types-internal.h>
36 #include <babeltrace/ctf-ir/fields-internal.h>
37 #include <babeltrace/ctf-writer/stream.h>
38 #include <babeltrace/ctf-ir/stream-class-internal.h>
39 #include <babeltrace/ctf-ir/validation-internal.h>
40 #include <babeltrace/ctf-ir/visitor-internal.h>
41 #include <babeltrace/ctf-writer/functor-internal.h>
42 #include <babeltrace/ctf-ir/utils.h>
43 #include <babeltrace/ref.h>
44 #include <babeltrace/compiler-internal.h>
45 #include <babeltrace/align-internal.h>
46 #include <babeltrace/endian-internal.h>
47 #include <inttypes.h>
48 #include <stdint.h>
49
50 static
51 void bt_ctf_stream_class_destroy(struct bt_object *obj);
52 static
53 int init_event_header(struct bt_ctf_stream_class *stream_class);
54 static
55 int init_packet_context(struct bt_ctf_stream_class *stream_class);
56
57 struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *name)
58 {
59 struct bt_ctf_stream_class *stream_class =
60 bt_ctf_stream_class_create_empty(name);
61 int ret;
62
63 if (!stream_class) {
64 goto error;
65 }
66
67 ret = init_event_header(stream_class);
68 if (ret) {
69 goto error;
70 }
71
72 ret = init_packet_context(stream_class);
73 if (ret) {
74 goto error;
75 }
76
77 return stream_class;
78
79 error:
80 BT_PUT(stream_class);
81 return stream_class;
82 }
83
84 struct bt_ctf_stream_class *bt_ctf_stream_class_create_empty(const char *name)
85 {
86 struct bt_ctf_stream_class *stream_class = NULL;
87
88 if (name && bt_ctf_validate_identifier(name)) {
89 goto error;
90 }
91
92 stream_class = g_new0(struct bt_ctf_stream_class, 1);
93 if (!stream_class) {
94 goto error;
95 }
96
97 stream_class->name = g_string_new(name);
98 stream_class->event_classes = g_ptr_array_new_with_free_func(
99 (GDestroyNotify) bt_object_release);
100 if (!stream_class->event_classes) {
101 goto error;
102 }
103
104 stream_class->event_classes_ht = g_hash_table_new_full(g_int64_hash,
105 g_int64_equal, g_free, NULL);
106
107 stream_class->packet_context_type = bt_ctf_field_type_structure_create();
108 if (!stream_class->packet_context_type) {
109 goto error;
110 }
111
112 stream_class->event_header_type = bt_ctf_field_type_structure_create();
113 if (!stream_class->event_header_type) {
114 goto error;
115 }
116
117 stream_class->event_context_type = bt_ctf_field_type_structure_create();
118 if (!stream_class->event_context_type) {
119 goto error;
120 }
121
122 bt_object_init(stream_class, bt_ctf_stream_class_destroy);
123 return stream_class;
124
125 error:
126 BT_PUT(stream_class);
127 return stream_class;
128 }
129
130 struct bt_ctf_trace *bt_ctf_stream_class_get_trace(
131 struct bt_ctf_stream_class *stream_class)
132 {
133 return stream_class ?
134 bt_get(bt_ctf_stream_class_borrow_trace(stream_class)) :
135 NULL;
136 }
137
138 const char *bt_ctf_stream_class_get_name(
139 struct bt_ctf_stream_class *stream_class)
140 {
141 const char *name = NULL;
142
143 if (!stream_class) {
144 goto end;
145 }
146
147 name = stream_class->name->str;
148 end:
149 return name;
150 }
151
152 int bt_ctf_stream_class_set_name(struct bt_ctf_stream_class *stream_class,
153 const char *name)
154 {
155 int ret = 0;
156
157 if (!stream_class || stream_class->frozen) {
158 ret = -1;
159 goto end;
160 }
161
162 g_string_assign(stream_class->name, name);
163 end:
164 return ret;
165 }
166
167 struct bt_ctf_clock *bt_ctf_stream_class_get_clock(
168 struct bt_ctf_stream_class *stream_class)
169 {
170 struct bt_ctf_clock *clock = NULL;
171
172 if (!stream_class || !stream_class->clock) {
173 goto end;
174 }
175
176 clock = bt_get(stream_class->clock);
177 end:
178 return clock;
179 }
180
181 int bt_ctf_stream_class_set_clock(struct bt_ctf_stream_class *stream_class,
182 struct bt_ctf_clock *clock)
183 {
184 int ret = 0;
185 struct bt_ctf_field_type *timestamp_field = NULL;
186
187 if (!stream_class || !clock || stream_class->frozen) {
188 ret = -1;
189 goto end;
190 }
191
192 /*
193 * Look for a "timestamp" integer field type in the stream
194 * class's event header field type and map the stream class's
195 * clock's class to that field type if there's no current
196 * mapping.
197 */
198 timestamp_field = bt_ctf_field_type_structure_get_field_type_by_name(
199 stream_class->event_header_type, "timestamp");
200 if (timestamp_field) {
201 struct bt_ctf_clock_class *mapped_clock_class =
202 bt_ctf_field_type_integer_get_mapped_clock_class(
203 timestamp_field);
204
205 if (!mapped_clock_class) {
206 ret = bt_ctf_field_type_integer_set_mapped_clock_class(
207 timestamp_field, clock->clock_class);
208 if (ret) {
209 goto end;
210 }
211 }
212
213 BT_PUT(mapped_clock_class);
214 }
215
216 /* Replace the current clock of this stream class. */
217 bt_put(stream_class->clock);
218 stream_class->clock = bt_get(clock);
219
220 end:
221 bt_put(timestamp_field);
222 return ret;
223 }
224
225 int64_t bt_ctf_stream_class_get_id(struct bt_ctf_stream_class *stream_class)
226 {
227 int64_t ret;
228
229 if (!stream_class || !stream_class->id_set) {
230 ret = (int64_t) -1;
231 goto end;
232 }
233
234 ret = stream_class->id;
235 end:
236 return ret;
237 }
238
239 BT_HIDDEN
240 int _bt_ctf_stream_class_set_id(
241 struct bt_ctf_stream_class *stream_class, int64_t id)
242 {
243 stream_class->id = id;
244 stream_class->id_set = 1;
245 return 0;
246 }
247
248 struct event_class_set_stream_class_id_data {
249 int64_t stream_class_id;
250 int ret;
251 };
252
253 static
254 void event_class_set_stream_id(gpointer event_class, gpointer data)
255 {
256 struct event_class_set_stream_class_id_data *typed_data = data;
257
258 typed_data->ret |= bt_ctf_event_class_set_stream_id(event_class,
259 typed_data->stream_class_id);
260 }
261
262 BT_HIDDEN
263 int bt_ctf_stream_class_set_id_no_check(
264 struct bt_ctf_stream_class *stream_class, int64_t id)
265 {
266 int ret = 0;
267 struct event_class_set_stream_class_id_data data =
268 { .stream_class_id = id, .ret = 0 };
269
270 /*
271 * Make sure all event classes have their "stream_id" attribute
272 * set to this value.
273 */
274 g_ptr_array_foreach(stream_class->event_classes,
275 event_class_set_stream_id, &data);
276 ret = data.ret;
277 if (ret) {
278 goto end;
279 }
280
281 ret = _bt_ctf_stream_class_set_id(stream_class, id);
282 if (ret) {
283 goto end;
284 }
285 end:
286 return ret;
287 }
288
289 int bt_ctf_stream_class_set_id(struct bt_ctf_stream_class *stream_class,
290 uint64_t id_param)
291 {
292 int ret = 0;
293 int64_t id = (int64_t) id_param;
294
295 if (!stream_class || stream_class->frozen || id < 0) {
296 ret = -1;
297 goto end;
298 }
299
300 ret = bt_ctf_stream_class_set_id_no_check(stream_class, id);
301 end:
302 return ret;
303 }
304
305 static
306 void event_class_exists(gpointer element, gpointer query)
307 {
308 struct bt_ctf_event_class *event_class_a = element;
309 struct search_query *search_query = query;
310 struct bt_ctf_event_class *event_class_b = search_query->value;
311 int64_t id_a, id_b;
312
313 if (search_query->value == element) {
314 search_query->found = 1;
315 goto end;
316 }
317
318 /*
319 * Two event classes cannot share the same ID in a given
320 * stream class.
321 */
322 id_a = bt_ctf_event_class_get_id(event_class_a);
323 id_b = bt_ctf_event_class_get_id(event_class_b);
324
325 if (id_a < 0 || id_b < 0) {
326 /* at least one ID is not set: will be automatically set later */
327 goto end;
328 }
329
330 if (id_a == id_b) {
331 search_query->found = 1;
332 goto end;
333 }
334
335 end:
336 return;
337 }
338
339 int bt_ctf_stream_class_add_event_class(
340 struct bt_ctf_stream_class *stream_class,
341 struct bt_ctf_event_class *event_class)
342 {
343 int ret = 0;
344 int64_t *event_id = NULL;
345 struct bt_ctf_trace *trace = NULL;
346 struct bt_ctf_stream_class *old_stream_class = NULL;
347 struct bt_ctf_validation_output validation_output = { 0 };
348 struct bt_ctf_field_type *packet_header_type = NULL;
349 struct bt_ctf_field_type *packet_context_type = NULL;
350 struct bt_ctf_field_type *event_header_type = NULL;
351 struct bt_ctf_field_type *stream_event_ctx_type = NULL;
352 struct bt_ctf_field_type *event_context_type = NULL;
353 struct bt_ctf_field_type *event_payload_type = NULL;
354 const enum bt_ctf_validation_flag validation_flags =
355 BT_CTF_VALIDATION_FLAG_EVENT;
356
357 if (!stream_class || !event_class) {
358 ret = -1;
359 goto end;
360 }
361
362 trace = bt_ctf_stream_class_get_trace(stream_class);
363 if (trace && trace->is_static) {
364 ret = -1;
365 goto end;
366 }
367
368 event_id = g_new(int64_t, 1);
369 if (!event_id) {
370 ret = -1;
371 goto end;
372 }
373
374 /* Check for duplicate event classes */
375 struct search_query query = { .value = event_class, .found = 0 };
376 g_ptr_array_foreach(stream_class->event_classes, event_class_exists,
377 &query);
378 if (query.found) {
379 ret = -1;
380 goto end;
381 }
382
383 old_stream_class = bt_ctf_event_class_get_stream_class(event_class);
384 if (old_stream_class) {
385 /* Event class is already associated to a stream class. */
386 ret = -1;
387 goto end;
388 }
389
390 if (trace) {
391 /*
392 * If the stream class is associated with a trace, then
393 * both those objects are frozen. Also, this event class
394 * is about to be frozen.
395 *
396 * Therefore the event class must be validated here.
397 * The trace and stream class should be valid at this
398 * point.
399 */
400 assert(trace->valid);
401 assert(stream_class->valid);
402 packet_header_type =
403 bt_ctf_trace_get_packet_header_type(trace);
404 packet_context_type =
405 bt_ctf_stream_class_get_packet_context_type(
406 stream_class);
407 event_header_type =
408 bt_ctf_stream_class_get_event_header_type(stream_class);
409 stream_event_ctx_type =
410 bt_ctf_stream_class_get_event_context_type(
411 stream_class);
412 event_context_type =
413 bt_ctf_event_class_get_context_type(event_class);
414 event_payload_type =
415 bt_ctf_event_class_get_payload_type(event_class);
416 ret = bt_ctf_validate_class_types(
417 trace->environment, packet_header_type,
418 packet_context_type, event_header_type,
419 stream_event_ctx_type, event_context_type,
420 event_payload_type, trace->valid,
421 stream_class->valid, event_class->valid,
422 &validation_output, validation_flags);
423 BT_PUT(packet_header_type);
424 BT_PUT(packet_context_type);
425 BT_PUT(event_header_type);
426 BT_PUT(stream_event_ctx_type);
427 BT_PUT(event_context_type);
428 BT_PUT(event_payload_type);
429
430 if (ret) {
431 /*
432 * This means something went wrong during the
433 * validation process, not that the objects are
434 * invalid.
435 */
436 goto end;
437 }
438
439 if ((validation_output.valid_flags & validation_flags) !=
440 validation_flags) {
441 /* Invalid event class */
442 ret = -1;
443 goto end;
444 }
445 }
446
447 /* Only set an event ID if none was explicitly set before */
448 *event_id = bt_ctf_event_class_get_id(event_class);
449 if (*event_id < 0) {
450 if (bt_ctf_event_class_set_id(event_class,
451 stream_class->next_event_id++)) {
452 ret = -1;
453 goto end;
454 }
455 *event_id = stream_class->next_event_id;
456 }
457
458 ret = bt_ctf_event_class_set_stream_id(event_class, stream_class->id);
459 if (ret) {
460 goto end;
461 }
462
463 bt_object_set_parent(event_class, stream_class);
464
465 if (trace) {
466 /*
467 * At this point we know that the function will be
468 * successful. Therefore we can replace the event
469 * class's field types with what's in the validation
470 * output structure and mark this event class as valid.
471 */
472 bt_ctf_validation_replace_types(NULL, NULL, event_class,
473 &validation_output, validation_flags);
474 event_class->valid = 1;
475
476 /*
477 * Put what was not moved in
478 * bt_ctf_validation_replace_types().
479 */
480 bt_ctf_validation_output_put_types(&validation_output);
481 }
482
483 /* Add to the event classes of the stream class */
484 g_ptr_array_add(stream_class->event_classes, event_class);
485 g_hash_table_insert(stream_class->event_classes_ht, event_id,
486 event_class);
487 event_id = NULL;
488
489 /* Freeze the event class */
490 bt_ctf_event_class_freeze(event_class);
491
492 /* Notifiy listeners of the trace's schema modification. */
493 if (trace) {
494 struct bt_ctf_object obj = { .object = event_class,
495 .type = BT_CTF_OBJECT_TYPE_EVENT_CLASS };
496
497 (void) bt_ctf_trace_object_modification(&obj, trace);
498 }
499 end:
500 BT_PUT(trace);
501 BT_PUT(old_stream_class);
502 bt_ctf_validation_output_put_types(&validation_output);
503 assert(!packet_header_type);
504 assert(!packet_context_type);
505 assert(!event_header_type);
506 assert(!stream_event_ctx_type);
507 assert(!event_context_type);
508 assert(!event_payload_type);
509 g_free(event_id);
510
511 return ret;
512 }
513
514 int64_t bt_ctf_stream_class_get_event_class_count(
515 struct bt_ctf_stream_class *stream_class)
516 {
517 int64_t ret;
518
519 if (!stream_class) {
520 ret = (int64_t) -1;
521 goto end;
522 }
523
524 ret = (int64_t) stream_class->event_classes->len;
525 end:
526 return ret;
527 }
528
529 struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_index(
530 struct bt_ctf_stream_class *stream_class, uint64_t index)
531 {
532 struct bt_ctf_event_class *event_class = NULL;
533
534 if (!stream_class || index >= stream_class->event_classes->len) {
535 goto end;
536 }
537
538 event_class = g_ptr_array_index(stream_class->event_classes, index);
539 bt_get(event_class);
540 end:
541 return event_class;
542 }
543
544 struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_id(
545 struct bt_ctf_stream_class *stream_class, uint64_t id)
546 {
547 int64_t id_key = (int64_t) id;
548 struct bt_ctf_event_class *event_class = NULL;
549
550 if (!stream_class || id_key < 0) {
551 goto end;
552 }
553
554 event_class = g_hash_table_lookup(stream_class->event_classes_ht,
555 &id_key);
556 bt_get(event_class);
557 end:
558 return event_class;
559 }
560
561 struct bt_ctf_field_type *bt_ctf_stream_class_get_packet_context_type(
562 struct bt_ctf_stream_class *stream_class)
563 {
564 struct bt_ctf_field_type *ret = NULL;
565
566 if (!stream_class) {
567 goto end;
568 }
569
570 bt_get(stream_class->packet_context_type);
571 ret = stream_class->packet_context_type;
572 end:
573 return ret;
574 }
575
576 int bt_ctf_stream_class_set_packet_context_type(
577 struct bt_ctf_stream_class *stream_class,
578 struct bt_ctf_field_type *packet_context_type)
579 {
580 int ret = 0;
581
582 if (!stream_class || stream_class->frozen) {
583 ret = -1;
584 goto end;
585 }
586
587 if (packet_context_type &&
588 bt_ctf_field_type_get_type_id(packet_context_type) !=
589 BT_CTF_FIELD_TYPE_ID_STRUCT) {
590 /* A packet context must be a structure. */
591 ret = -1;
592 goto end;
593 }
594
595 bt_put(stream_class->packet_context_type);
596 bt_get(packet_context_type);
597 stream_class->packet_context_type = packet_context_type;
598 end:
599 return ret;
600 }
601
602 struct bt_ctf_field_type *bt_ctf_stream_class_get_event_header_type(
603 struct bt_ctf_stream_class *stream_class)
604 {
605 struct bt_ctf_field_type *ret = NULL;
606
607 if (!stream_class || !stream_class->event_header_type) {
608 goto end;
609 }
610
611 bt_get(stream_class->event_header_type);
612 ret = stream_class->event_header_type;
613 end:
614 return ret;
615 }
616
617 int bt_ctf_stream_class_set_event_header_type(
618 struct bt_ctf_stream_class *stream_class,
619 struct bt_ctf_field_type *event_header_type)
620 {
621 int ret = 0;
622
623 if (!stream_class || stream_class->frozen) {
624 ret = -1;
625 goto end;
626 }
627
628 if (event_header_type &&
629 bt_ctf_field_type_get_type_id(event_header_type) !=
630 BT_CTF_FIELD_TYPE_ID_STRUCT) {
631 /* An event header must be a structure. */
632 ret = -1;
633 goto end;
634 }
635
636 bt_put(stream_class->event_header_type);
637 stream_class->event_header_type = bt_get(event_header_type);
638 end:
639 return ret;
640 }
641
642 struct bt_ctf_field_type *bt_ctf_stream_class_get_event_context_type(
643 struct bt_ctf_stream_class *stream_class)
644 {
645 struct bt_ctf_field_type *ret = NULL;
646
647 if (!stream_class || !stream_class->event_context_type) {
648 goto end;
649 }
650
651 bt_get(stream_class->event_context_type);
652 ret = stream_class->event_context_type;
653 end:
654 return ret;
655 }
656
657 int bt_ctf_stream_class_set_event_context_type(
658 struct bt_ctf_stream_class *stream_class,
659 struct bt_ctf_field_type *event_context_type)
660 {
661 int ret = 0;
662
663 if (!stream_class || stream_class->frozen) {
664 ret = -1;
665 goto end;
666 }
667
668 if (event_context_type &&
669 bt_ctf_field_type_get_type_id(event_context_type) !=
670 BT_CTF_FIELD_TYPE_ID_STRUCT) {
671 /* A packet context must be a structure. */
672 ret = -1;
673 goto end;
674 }
675
676 bt_put(stream_class->event_context_type);
677 stream_class->event_context_type = bt_get(event_context_type);
678 end:
679 return ret;
680 }
681
682 void bt_ctf_stream_class_get(struct bt_ctf_stream_class *stream_class)
683 {
684 bt_get(stream_class);
685 }
686
687 void bt_ctf_stream_class_put(struct bt_ctf_stream_class *stream_class)
688 {
689 bt_put(stream_class);
690 }
691
692 static
693 int64_t get_event_class_count(void *element)
694 {
695 return bt_ctf_stream_class_get_event_class_count(
696 (struct bt_ctf_stream_class *) element);
697 }
698
699 static
700 void *get_event_class(void *element, int i)
701 {
702 return bt_ctf_stream_class_get_event_class_by_index(
703 (struct bt_ctf_stream_class *) element, i);
704 }
705
706 static
707 int visit_event_class(void *object, bt_ctf_visitor visitor,void *data)
708 {
709 struct bt_ctf_object obj =
710 { .object = object,
711 .type = BT_CTF_OBJECT_TYPE_EVENT_CLASS };
712
713 return visitor(&obj, data);
714 }
715
716 int bt_ctf_stream_class_visit(struct bt_ctf_stream_class *stream_class,
717 bt_ctf_visitor visitor, void *data)
718 {
719 int ret;
720 struct bt_ctf_object obj =
721 { .object = stream_class,
722 .type = BT_CTF_OBJECT_TYPE_STREAM_CLASS };
723
724 if (!stream_class || !visitor) {
725 ret = -1;
726 goto end;
727 }
728
729 ret = visitor_helper(&obj, get_event_class_count,
730 get_event_class,
731 visit_event_class, visitor, data);
732 end:
733 return ret;
734 }
735
736 BT_HIDDEN
737 void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class *stream_class)
738 {
739 if (!stream_class) {
740 return;
741 }
742
743 stream_class->frozen = 1;
744 bt_ctf_field_type_freeze(stream_class->event_header_type);
745 bt_ctf_field_type_freeze(stream_class->packet_context_type);
746 bt_ctf_field_type_freeze(stream_class->event_context_type);
747
748 if (stream_class->clock) {
749 bt_ctf_clock_class_freeze(stream_class->clock->clock_class);
750 }
751 }
752
753 BT_HIDDEN
754 int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
755 struct metadata_context *context)
756 {
757 int ret = 0;
758 size_t i;
759
760 g_string_assign(context->field_name, "");
761 context->current_indentation_level = 1;
762 if (!stream_class->id_set) {
763 ret = -1;
764 goto end;
765 }
766
767 g_string_append_printf(context->string,
768 "stream {\n\tid = %" PRId64 ";\n\tevent.header := ",
769 stream_class->id);
770 ret = bt_ctf_field_type_serialize(stream_class->event_header_type,
771 context);
772 if (ret) {
773 goto end;
774 }
775
776 if (stream_class->packet_context_type) {
777 g_string_append(context->string, ";\n\n\tpacket.context := ");
778 ret = bt_ctf_field_type_serialize(stream_class->packet_context_type,
779 context);
780 if (ret) {
781 goto end;
782 }
783 }
784
785 if (stream_class->event_context_type) {
786 g_string_append(context->string, ";\n\n\tevent.context := ");
787 ret = bt_ctf_field_type_serialize(
788 stream_class->event_context_type, context);
789 if (ret) {
790 goto end;
791 }
792 }
793
794 g_string_append(context->string, ";\n};\n\n");
795 for (i = 0; i < stream_class->event_classes->len; i++) {
796 struct bt_ctf_event_class *event_class =
797 stream_class->event_classes->pdata[i];
798
799 ret = bt_ctf_event_class_serialize(event_class, context);
800 if (ret) {
801 goto end;
802 }
803 }
804 end:
805 context->current_indentation_level = 0;
806 return ret;
807 }
808
809 static
810 void bt_ctf_stream_class_destroy(struct bt_object *obj)
811 {
812 struct bt_ctf_stream_class *stream_class;
813
814 stream_class = container_of(obj, struct bt_ctf_stream_class, base);
815 bt_put(stream_class->clock);
816
817 if (stream_class->event_classes_ht) {
818 g_hash_table_destroy(stream_class->event_classes_ht);
819 }
820 if (stream_class->event_classes) {
821 g_ptr_array_free(stream_class->event_classes, TRUE);
822 }
823
824 if (stream_class->name) {
825 g_string_free(stream_class->name, TRUE);
826 }
827
828 bt_put(stream_class->event_header_type);
829 bt_put(stream_class->packet_context_type);
830 bt_put(stream_class->event_context_type);
831 g_free(stream_class);
832 }
833
834 static
835 int init_event_header(struct bt_ctf_stream_class *stream_class)
836 {
837 int ret = 0;
838 struct bt_ctf_field_type *event_header_type =
839 bt_ctf_field_type_structure_create();
840 struct bt_ctf_field_type *_uint32_t =
841 get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
842 struct bt_ctf_field_type *_uint64_t =
843 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
844
845 if (!event_header_type) {
846 ret = -1;
847 goto end;
848 }
849
850 ret = bt_ctf_field_type_structure_add_field(event_header_type,
851 _uint32_t, "id");
852 if (ret) {
853 goto end;
854 }
855
856 ret = bt_ctf_field_type_structure_add_field(event_header_type,
857 _uint64_t, "timestamp");
858 if (ret) {
859 goto end;
860 }
861
862 BT_MOVE(stream_class->event_header_type, event_header_type);
863 end:
864 if (ret) {
865 bt_put(event_header_type);
866 }
867
868 bt_put(_uint32_t);
869 bt_put(_uint64_t);
870 return ret;
871 }
872
873 static
874 int init_packet_context(struct bt_ctf_stream_class *stream_class)
875 {
876 int ret = 0;
877 struct bt_ctf_field_type *packet_context_type =
878 bt_ctf_field_type_structure_create();
879 struct bt_ctf_field_type *_uint64_t =
880 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
881
882 if (!packet_context_type) {
883 ret = -1;
884 goto end;
885 }
886
887 /*
888 * We create a stream packet context as proposed in the CTF
889 * specification.
890 */
891 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
892 _uint64_t, "timestamp_begin");
893 if (ret) {
894 goto end;
895 }
896
897 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
898 _uint64_t, "timestamp_end");
899 if (ret) {
900 goto end;
901 }
902
903 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
904 _uint64_t, "content_size");
905 if (ret) {
906 goto end;
907 }
908
909 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
910 _uint64_t, "packet_size");
911 if (ret) {
912 goto end;
913 }
914
915 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
916 _uint64_t, "events_discarded");
917 if (ret) {
918 goto end;
919 }
920
921 BT_MOVE(stream_class->packet_context_type, packet_context_type);
922 end:
923 if (ret) {
924 bt_put(packet_context_type);
925 goto end;
926 }
927
928 bt_put(_uint64_t);
929 return ret;
930 }
This page took 0.047864 seconds and 5 git commands to generate.