ir: add bt_ctf_event_set_payload_field()
[babeltrace.git] / formats / ctf / ir / event.c
1 /*
2 * event.c
3 *
4 * Babeltrace CTF IR - Event
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/event.h>
30 #include <babeltrace/ctf-writer/event-types.h>
31 #include <babeltrace/ctf-writer/event-fields.h>
32 #include <babeltrace/ctf-ir/event-fields-internal.h>
33 #include <babeltrace/ctf-ir/event-types-internal.h>
34 #include <babeltrace/ctf-ir/event-internal.h>
35 #include <babeltrace/ctf-ir/stream-class.h>
36 #include <babeltrace/ctf-ir/stream-class-internal.h>
37 #include <babeltrace/ctf-ir/trace-internal.h>
38 #include <babeltrace/ctf-ir/utils.h>
39 #include <babeltrace/ctf-ir/attributes-internal.h>
40 #include <babeltrace/compiler.h>
41
42 static
43 void bt_ctf_event_class_destroy(struct bt_ctf_ref *ref);
44 static
45 void bt_ctf_event_destroy(struct bt_ctf_ref *ref);
46 static
47 int set_integer_field_value(struct bt_ctf_field *field, uint64_t value);
48
49 struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name)
50 {
51 int ret;
52 struct bt_object *obj = NULL;
53 struct bt_ctf_event_class *event_class = NULL;
54
55 if (bt_ctf_validate_identifier(name)) {
56 goto error;
57 }
58
59 event_class = g_new0(struct bt_ctf_event_class, 1);
60 if (!event_class) {
61 goto error;
62 }
63
64 bt_ctf_ref_init(&event_class->ref_count);
65 event_class->fields = bt_ctf_field_type_structure_create();
66 if (!event_class->fields) {
67 goto error;
68 }
69
70 event_class->attributes = bt_ctf_attributes_create();
71 if (!event_class->attributes) {
72 goto error;
73 }
74
75 obj = bt_object_integer_create_init(-1);
76 if (!obj) {
77 goto error;
78 }
79
80 ret = bt_ctf_attributes_set_field_value(event_class->attributes,
81 "id", obj);
82 if (ret) {
83 goto error;
84 }
85
86 BT_OBJECT_PUT(obj);
87
88 obj = bt_object_string_create_init(name);
89 if (!obj) {
90 goto error;
91 }
92
93 ret = bt_ctf_attributes_set_field_value(event_class->attributes,
94 "name", obj);
95 if (ret) {
96 goto error;
97 }
98
99 BT_OBJECT_PUT(obj);
100
101 return event_class;
102
103 error:
104 if (event_class) {
105 bt_ctf_event_class_put(event_class);
106 }
107
108 BT_OBJECT_PUT(obj);
109
110 return NULL;
111 }
112
113 const char *bt_ctf_event_class_get_name(struct bt_ctf_event_class *event_class)
114 {
115 struct bt_object *obj = NULL;
116 const char *name = NULL;
117
118 if (!event_class) {
119 goto end;
120 }
121
122 obj = bt_ctf_attributes_get_field_value(event_class->attributes,
123 BT_CTF_EVENT_CLASS_ATTR_NAME_INDEX);
124 if (!obj) {
125 goto end;
126 }
127
128 if (bt_object_string_get(obj, &name)) {
129 name = NULL;
130 }
131
132 end:
133 BT_OBJECT_PUT(obj);
134
135 return name;
136 }
137
138 int64_t bt_ctf_event_class_get_id(struct bt_ctf_event_class *event_class)
139 {
140 struct bt_object *obj = NULL;
141 int64_t ret = 0;
142
143 if (!event_class) {
144 ret = -1;
145 goto end;
146 }
147
148 obj = bt_ctf_attributes_get_field_value(event_class->attributes,
149 BT_CTF_EVENT_CLASS_ATTR_ID_INDEX);
150 if (!obj) {
151 goto end;
152 }
153
154 if (bt_object_integer_get(obj, &ret)) {
155 ret = -1;
156 }
157
158 if (ret < 0) {
159 /* means ID is not set */
160 ret = -1;
161 goto end;
162 }
163
164 end:
165 BT_OBJECT_PUT(obj);
166
167 return ret;
168 }
169
170 int bt_ctf_event_class_set_id(struct bt_ctf_event_class *event_class,
171 uint32_t id)
172 {
173 int ret = 0;
174 struct bt_object *obj = NULL;
175
176 if (!event_class) {
177 ret = -1;
178 goto end;
179 }
180
181 if (event_class->stream_class) {
182 /*
183 * We don't allow changing the id if the event class has already
184 * been added to a stream class.
185 */
186 ret = -1;
187 goto end;
188 }
189
190 obj = bt_ctf_attributes_get_field_value(event_class->attributes,
191 BT_CTF_EVENT_CLASS_ATTR_ID_INDEX);
192 if (!obj) {
193 goto end;
194 }
195
196 if (bt_object_integer_set(obj, id)) {
197 ret = -1;
198 goto end;
199 }
200
201 end:
202 BT_OBJECT_PUT(obj);
203
204 return ret;
205 }
206
207 int bt_ctf_event_class_set_attribute(
208 struct bt_ctf_event_class *event_class, const char *name,
209 struct bt_object *value)
210 {
211 int ret = 0;
212
213 if (!event_class || !name || !value || event_class->frozen) {
214 ret = -1;
215 goto end;
216 }
217
218 if (!strcmp(name, "id") || !strcmp(name, "loglevel")) {
219 if (!bt_object_is_integer(value)) {
220 ret = -1;
221 goto end;
222 }
223 } else if (!strcmp(name, "name") || !strcmp(name, "model.emf.uri")) {
224 if (!bt_object_is_string(value)) {
225 ret = -1;
226 goto end;
227 }
228 } else {
229 /* unknown attribute */
230 ret = -1;
231 goto end;
232 }
233
234 /* "id" special case: >= 0 */
235 if (!strcmp(name, "id")) {
236 int64_t val;
237
238 ret = bt_object_integer_get(value, &val);
239
240 if (ret) {
241 goto end;
242 }
243
244 if (val < 0) {
245 ret = -1;
246 goto end;
247 }
248 }
249
250 ret = bt_ctf_attributes_set_field_value(event_class->attributes,
251 name, value);
252
253 end:
254 return ret;
255 }
256
257 int bt_ctf_event_class_get_attribute_count(
258 struct bt_ctf_event_class *event_class)
259 {
260 int ret = 0;
261
262 if (!event_class) {
263 ret = -1;
264 goto end;
265 }
266
267 ret = bt_ctf_attributes_get_count(event_class->attributes);
268
269 end:
270 return ret;
271 }
272
273 const char *
274 bt_ctf_event_class_get_attribute_name(
275 struct bt_ctf_event_class *event_class, int index)
276 {
277 const char *ret;
278
279 if (!event_class) {
280 ret = NULL;
281 goto end;
282 }
283
284 ret = bt_ctf_attributes_get_field_name(event_class->attributes, index);
285
286 end:
287 return ret;
288 }
289
290 struct bt_object *
291 bt_ctf_event_class_get_attribute_value(struct bt_ctf_event_class *event_class,
292 int index)
293 {
294 struct bt_object *ret;
295
296 if (!event_class) {
297 ret = NULL;
298 goto end;
299 }
300
301 ret = bt_ctf_attributes_get_field_value(event_class->attributes, index);
302
303 end:
304 return ret;
305 }
306
307 struct bt_object *
308 bt_ctf_event_class_get_attribute_value_by_name(
309 struct bt_ctf_event_class *event_class, const char *name)
310 {
311 struct bt_object *ret;
312
313 if (!event_class || !name) {
314 ret = NULL;
315 goto end;
316 }
317
318 ret = bt_ctf_attributes_get_field_value_by_name(event_class->attributes,
319 name);
320
321 end:
322 return ret;
323
324 }
325
326 struct bt_ctf_stream_class *bt_ctf_event_class_get_stream_class(
327 struct bt_ctf_event_class *event_class)
328 {
329 struct bt_ctf_stream_class *stream_class = NULL;
330
331 if (!event_class) {
332 goto end;
333 }
334
335 stream_class = event_class->stream_class;
336 bt_ctf_stream_class_get(stream_class);
337 end:
338 return stream_class;
339 }
340
341 struct bt_ctf_field_type *bt_ctf_event_class_get_payload_type(
342 struct bt_ctf_event_class *event_class)
343 {
344 struct bt_ctf_field_type *payload = NULL;
345
346 if (!event_class) {
347 goto end;
348 }
349
350 bt_ctf_field_type_get(event_class->fields);
351 payload = event_class->fields;
352 end:
353 return payload;
354 }
355
356 int bt_ctf_event_class_set_payload_type(struct bt_ctf_event_class *event_class,
357 struct bt_ctf_field_type *payload)
358 {
359 int ret = 0;
360
361 if (!event_class || !payload ||
362 bt_ctf_field_type_get_type_id(payload) != CTF_TYPE_STRUCT) {
363 ret = -1;
364 goto end;
365 }
366
367 bt_ctf_field_type_get(payload);
368 bt_ctf_field_type_put(event_class->fields);
369 event_class->fields = payload;
370 end:
371 return ret;
372 }
373
374 int bt_ctf_event_class_add_field(struct bt_ctf_event_class *event_class,
375 struct bt_ctf_field_type *type,
376 const char *name)
377 {
378 int ret = 0;
379
380 if (!event_class || !type || bt_ctf_validate_identifier(name) ||
381 event_class->frozen) {
382 ret = -1;
383 goto end;
384 }
385
386 if (bt_ctf_field_type_get_type_id(event_class->fields) !=
387 CTF_TYPE_STRUCT) {
388 ret = -1;
389 goto end;
390 }
391
392 ret = bt_ctf_field_type_structure_add_field(event_class->fields,
393 type, name);
394 end:
395 return ret;
396 }
397
398 int bt_ctf_event_class_get_field_count(
399 struct bt_ctf_event_class *event_class)
400 {
401 int ret;
402
403 if (!event_class) {
404 ret = -1;
405 goto end;
406 }
407
408 if (bt_ctf_field_type_get_type_id(event_class->fields) !=
409 CTF_TYPE_STRUCT) {
410 ret = -1;
411 goto end;
412 }
413
414 ret = bt_ctf_field_type_structure_get_field_count(event_class->fields);
415 end:
416 return ret;
417 }
418
419 int bt_ctf_event_class_get_field(struct bt_ctf_event_class *event_class,
420 const char **field_name, struct bt_ctf_field_type **field_type,
421 int index)
422 {
423 int ret;
424
425 if (!event_class || index < 0) {
426 ret = -1;
427 goto end;
428 }
429
430 if (bt_ctf_field_type_get_type_id(event_class->fields) !=
431 CTF_TYPE_STRUCT) {
432 ret = -1;
433 goto end;
434 }
435
436 ret = bt_ctf_field_type_structure_get_field(event_class->fields,
437 field_name, field_type, index);
438 end:
439 return ret;
440 }
441
442 struct bt_ctf_field_type *bt_ctf_event_class_get_field_by_name(
443 struct bt_ctf_event_class *event_class, const char *name)
444 {
445 GQuark name_quark;
446 struct bt_ctf_field_type *field_type = NULL;
447
448 if (!event_class || !name) {
449 goto end;
450 }
451
452 if (bt_ctf_field_type_get_type_id(event_class->fields) !=
453 CTF_TYPE_STRUCT) {
454 goto end;
455 }
456
457 name_quark = g_quark_try_string(name);
458 if (!name_quark) {
459 goto end;
460 }
461
462 /*
463 * No need to increment field_type's reference count since getting it
464 * from the structure already does.
465 */
466 field_type = bt_ctf_field_type_structure_get_field_type_by_name(
467 event_class->fields, name);
468 end:
469 return field_type;
470 }
471
472 struct bt_ctf_field_type *bt_ctf_event_class_get_context_type(
473 struct bt_ctf_event_class *event_class)
474 {
475 struct bt_ctf_field_type *context_type = NULL;
476
477 if (!event_class || !event_class->context) {
478 goto end;
479 }
480
481 bt_ctf_field_type_get(event_class->context);
482 context_type = event_class->context;
483 end:
484 return context_type;
485 }
486
487 int bt_ctf_event_class_set_context_type(
488 struct bt_ctf_event_class *event_class,
489 struct bt_ctf_field_type *context)
490 {
491 int ret = 0;
492
493 if (!event_class || !context || event_class->frozen) {
494 ret = -1;
495 goto end;
496 }
497
498 if (bt_ctf_field_type_get_type_id(context) != CTF_TYPE_STRUCT) {
499 ret = -1;
500 goto end;
501 }
502
503 bt_ctf_field_type_get(context);
504 bt_ctf_field_type_put(event_class->context);
505 event_class->context = context;
506 end:
507 return ret;
508
509 }
510
511 void bt_ctf_event_class_get(struct bt_ctf_event_class *event_class)
512 {
513 if (!event_class) {
514 return;
515 }
516
517 bt_ctf_ref_get(&event_class->ref_count);
518 }
519
520 void bt_ctf_event_class_put(struct bt_ctf_event_class *event_class)
521 {
522 if (!event_class) {
523 return;
524 }
525
526 bt_ctf_ref_put(&event_class->ref_count, bt_ctf_event_class_destroy);
527 }
528
529 BT_HIDDEN
530 int bt_ctf_event_class_set_stream_id(struct bt_ctf_event_class *event_class,
531 uint32_t stream_id)
532 {
533 int ret = 0;
534 struct bt_object *obj;
535
536 obj = bt_object_integer_create_init(stream_id);
537
538 if (!obj) {
539 ret = -1;
540 goto end;
541 }
542
543 ret = bt_ctf_attributes_set_field_value(event_class->attributes,
544 "stream_id", obj);
545
546 end:
547 BT_OBJECT_PUT(obj);
548
549 return ret;
550 }
551
552 struct bt_ctf_event *bt_ctf_event_create(struct bt_ctf_event_class *event_class)
553 {
554 struct bt_ctf_event *event = NULL;
555
556 if (!event_class) {
557 goto end;
558 }
559
560 /*
561 * The event class does not keep ownership of the stream class to
562 * which it as been added. Therefore, it can't assume it has been
563 * set. However, we disallow the creation of an event if its
564 * associated stream class has been reclaimed.
565 */
566 if (!event_class->stream_class) {
567 goto end;
568 }
569 assert(event_class->stream_class->event_header_type);
570 event = g_new0(struct bt_ctf_event, 1);
571 if (!event) {
572 goto end;
573 }
574
575 bt_ctf_ref_init(&event->ref_count);
576 bt_ctf_event_class_get(event_class);
577 bt_ctf_event_class_freeze(event_class);
578 event->event_class = event_class;
579
580 event->event_header = bt_ctf_field_create(
581 event_class->stream_class->event_header_type);
582 if (!event->event_header) {
583 goto error_destroy;
584 }
585 if (event_class->context) {
586 event->context_payload = bt_ctf_field_create(
587 event_class->context);
588 if (!event->context_payload) {
589 goto error_destroy;
590 }
591 }
592 event->fields_payload = bt_ctf_field_create(event_class->fields);
593 if (!event->fields_payload) {
594 goto error_destroy;
595 }
596
597 /*
598 * Freeze the stream class since the event header must not be changed
599 * anymore.
600 */
601 bt_ctf_stream_class_freeze(event_class->stream_class);
602 end:
603 return event;
604 error_destroy:
605 if (event) {
606 bt_ctf_event_destroy(&event->ref_count);
607 }
608
609 return NULL;
610 }
611
612 struct bt_ctf_event_class *bt_ctf_event_get_class(struct bt_ctf_event *event)
613 {
614 struct bt_ctf_event_class *event_class = NULL;
615
616 if (!event) {
617 goto end;
618 }
619
620 event_class = event->event_class;
621 bt_ctf_event_class_get(event_class);
622 end:
623 return event_class;
624 }
625
626 struct bt_ctf_stream *bt_ctf_event_get_stream(struct bt_ctf_event *event)
627 {
628 struct bt_ctf_stream *stream = NULL;
629
630 if (!event) {
631 goto end;
632 }
633
634 stream = event->stream;
635 if (stream) {
636 bt_ctf_stream_get(stream);
637 }
638 end:
639 return stream;
640 }
641
642 struct bt_ctf_clock *bt_ctf_event_get_clock(struct bt_ctf_event *event)
643 {
644 struct bt_ctf_clock *clock = NULL;
645 struct bt_ctf_event_class *event_class;
646 struct bt_ctf_stream_class *stream_class;
647
648 if (!event) {
649 goto end;
650 }
651
652 event_class = bt_ctf_event_get_class(event);
653 if (!event_class) {
654 goto end;
655 }
656
657 stream_class = bt_ctf_event_class_get_stream_class(event_class);
658 if (!stream_class) {
659 goto error_put_event_class;
660 }
661
662 clock = bt_ctf_stream_class_get_clock(stream_class);
663 if (!clock) {
664 goto error_put_stream_class;
665 }
666
667 error_put_stream_class:
668 bt_ctf_stream_class_put(stream_class);
669 error_put_event_class:
670 bt_ctf_event_class_put(event_class);
671 end:
672 return clock;
673 }
674
675 int bt_ctf_event_set_payload(struct bt_ctf_event *event,
676 const char *name,
677 struct bt_ctf_field *payload)
678 {
679 int ret = 0;
680
681 if (!event || !payload) {
682 ret = -1;
683 goto end;
684 }
685
686 if (name) {
687 ret = bt_ctf_field_structure_set_field(event->fields_payload,
688 name, payload);
689 } else {
690 struct bt_ctf_field_type *payload_type;
691
692 payload_type = bt_ctf_field_get_type(payload);
693 if (payload_type == event->event_class->fields) {
694 bt_ctf_field_put(event->fields_payload);
695 bt_ctf_field_get(payload);
696 event->fields_payload = payload;
697 } else {
698 ret = -1;
699 }
700
701 bt_ctf_field_type_put(payload_type);
702 }
703 end:
704 return ret;
705 }
706
707 struct bt_ctf_field *bt_ctf_event_get_payload_field(struct bt_ctf_event *event)
708 {
709 struct bt_ctf_field *payload = NULL;
710
711 if (!event || !event->fields_payload) {
712 goto end;
713 }
714
715 payload = event->fields_payload;
716 bt_ctf_field_get(payload);
717 end:
718 return payload;
719 }
720
721 int bt_ctf_event_set_payload_field(struct bt_ctf_event *event,
722 struct bt_ctf_field *payload)
723 {
724 int ret = 0;
725 struct bt_ctf_field_type *payload_type = NULL;
726
727 if (!event || !payload) {
728 ret = -1;
729 goto end;
730 }
731
732 payload_type = bt_ctf_field_get_type(payload);
733 if (!payload_type) {
734 ret = -1;
735 goto end;
736 }
737
738 if (bt_ctf_field_type_get_type_id(payload_type) != CTF_TYPE_STRUCT) {
739 ret = -1;
740 goto end;
741 }
742
743 bt_ctf_field_get(payload);
744 if (event->fields_payload) {
745 bt_ctf_field_put(event->fields_payload);
746 }
747 event->fields_payload = payload;
748
749 end:
750 if (payload_type) {
751 bt_ctf_field_type_put(payload_type);
752 }
753 return ret;
754 }
755
756 struct bt_ctf_field *bt_ctf_event_get_payload(struct bt_ctf_event *event,
757 const char *name)
758 {
759 struct bt_ctf_field *field = NULL;
760
761 if (!event) {
762 goto end;
763 }
764
765 if (name) {
766 field = bt_ctf_field_structure_get_field(event->fields_payload,
767 name);
768 } else {
769 field = event->fields_payload;
770 bt_ctf_field_get(field);
771 }
772 end:
773 return field;
774 }
775
776 struct bt_ctf_field *bt_ctf_event_get_payload_by_index(
777 struct bt_ctf_event *event, int index)
778 {
779 struct bt_ctf_field *field = NULL;
780
781 if (!event || index < 0) {
782 goto end;
783 }
784
785 field = bt_ctf_field_structure_get_field_by_index(event->fields_payload,
786 index);
787 end:
788 return field;
789 }
790
791 struct bt_ctf_field *bt_ctf_event_get_event_header(
792 struct bt_ctf_event *event)
793 {
794 struct bt_ctf_field *header = NULL;
795
796 if (!event || !event->event_header) {
797 goto end;
798 }
799
800 header = event->event_header;
801 bt_ctf_field_get(header);
802 end:
803 return header;
804 }
805
806 int bt_ctf_event_set_event_header(struct bt_ctf_event *event,
807 struct bt_ctf_field *header)
808 {
809 int ret = 0;
810 struct bt_ctf_field_type *field_type = NULL;
811
812 if (!event || !header) {
813 ret = -1;
814 goto end;
815 }
816
817 /* Could be NULL since an event class doesn't own a stream class */
818 if (!event->event_class->stream_class) {
819 ret = -1;
820 goto end;
821 }
822
823 /*
824 * Ensure the provided header's type matches the one registered to the
825 * stream class.
826 */
827 field_type = bt_ctf_field_get_type(header);
828 if (field_type != event->event_class->stream_class->event_header_type) {
829 ret = -1;
830 goto end;
831 }
832
833 bt_ctf_field_get(header);
834 bt_ctf_field_put(event->event_header);
835 event->event_header = header;
836 end:
837 if (field_type) {
838 bt_ctf_field_type_put(field_type);
839 }
840 return ret;
841 }
842
843 struct bt_ctf_field *bt_ctf_event_get_event_context(
844 struct bt_ctf_event *event)
845 {
846 struct bt_ctf_field *context = NULL;
847
848 if (!event || !event->context_payload) {
849 goto end;
850 }
851
852 context = event->context_payload;
853 bt_ctf_field_get(context);
854 end:
855 return context;
856 }
857
858 int bt_ctf_event_set_event_context(struct bt_ctf_event *event,
859 struct bt_ctf_field *context)
860 {
861 int ret = 0;
862 struct bt_ctf_field_type *field_type = NULL;
863
864 if (!event || !context) {
865 ret = -1;
866 goto end;
867 }
868
869 field_type = bt_ctf_field_get_type(context);
870 if (field_type != event->event_class->context) {
871 ret = -1;
872 goto end;
873 }
874
875 bt_ctf_field_get(context);
876 bt_ctf_field_put(event->context_payload);
877 event->context_payload = context;
878 end:
879 if (field_type) {
880 bt_ctf_field_type_put(field_type);
881 }
882 return ret;
883 }
884
885 void bt_ctf_event_get(struct bt_ctf_event *event)
886 {
887 if (!event) {
888 return;
889 }
890
891 bt_ctf_ref_get(&event->ref_count);
892 }
893
894 void bt_ctf_event_put(struct bt_ctf_event *event)
895 {
896 if (!event) {
897 return;
898 }
899
900 bt_ctf_ref_put(&event->ref_count, bt_ctf_event_destroy);
901 }
902
903 static
904 void bt_ctf_event_class_destroy(struct bt_ctf_ref *ref)
905 {
906 struct bt_ctf_event_class *event_class;
907
908 if (!ref) {
909 return;
910 }
911
912 /*
913 * Don't call put() on the stream class. See comment in
914 * bt_ctf_event_class_set_stream_class for explanation.
915 */
916 event_class = container_of(ref, struct bt_ctf_event_class, ref_count);
917 if (event_class->attributes) {
918 bt_ctf_attributes_destroy(event_class->attributes);
919 }
920 if (event_class->context) {
921 bt_ctf_field_type_put(event_class->context);
922 }
923 if (event_class->fields) {
924 bt_ctf_field_type_put(event_class->fields);
925 }
926 g_free(event_class);
927 }
928
929 static
930 void bt_ctf_event_destroy(struct bt_ctf_ref *ref)
931 {
932 struct bt_ctf_event *event;
933
934 if (!ref) {
935 return;
936 }
937
938 event = container_of(ref, struct bt_ctf_event,
939 ref_count);
940 if (event->event_class) {
941 bt_ctf_event_class_put(event->event_class);
942 }
943 if (event->event_header) {
944 bt_ctf_field_put(event->event_header);
945 }
946 if (event->context_payload) {
947 bt_ctf_field_put(event->context_payload);
948 }
949 if (event->fields_payload) {
950 bt_ctf_field_put(event->fields_payload);
951 }
952 g_free(event);
953 }
954
955 static
956 int set_integer_field_value(struct bt_ctf_field* field, uint64_t value)
957 {
958 int ret = 0;
959 struct bt_ctf_field_type *field_type = NULL;
960
961 if (!field) {
962 ret = -1;
963 goto end;
964 }
965
966 if (!bt_ctf_field_validate(field)) {
967 /* Payload already set, skip! (not an error) */
968 goto end;
969 }
970
971 field_type = bt_ctf_field_get_type(field);
972 assert(field_type);
973
974 if (bt_ctf_field_type_get_type_id(field_type) != CTF_TYPE_INTEGER) {
975 /* Not an integer and the value is unset, error. */
976 ret = -1;
977 goto end;
978 }
979
980 if (bt_ctf_field_type_integer_get_signed(field_type)) {
981 ret = bt_ctf_field_signed_integer_set_value(field, (int64_t) value);
982 if (ret) {
983 /* Value is out of range, error. */
984 goto end;
985 }
986 } else {
987 ret = bt_ctf_field_unsigned_integer_set_value(field, value);
988 if (ret) {
989 /* Value is out of range, error. */
990 goto end;
991 }
992 }
993 end:
994 bt_ctf_field_type_put(field_type);
995 return ret;
996 }
997
998 BT_HIDDEN
999 void bt_ctf_event_class_freeze(struct bt_ctf_event_class *event_class)
1000 {
1001 assert(event_class);
1002 event_class->frozen = 1;
1003 bt_ctf_field_type_freeze(event_class->context);
1004 bt_ctf_field_type_freeze(event_class->fields);
1005 bt_ctf_attributes_freeze(event_class->attributes);
1006 }
1007
1008 BT_HIDDEN
1009 int bt_ctf_event_class_set_stream_class(struct bt_ctf_event_class *event_class,
1010 struct bt_ctf_stream_class *stream_class)
1011 {
1012 int ret = 0;
1013
1014 if (!event_class) {
1015 ret = -1;
1016 goto end;
1017 }
1018
1019 /* Allow a NULL stream_class to unset the current stream_class */
1020 if (stream_class && event_class->stream_class) {
1021 ret = -1;
1022 goto end;
1023 }
1024
1025 event_class->stream_class = stream_class;
1026 /*
1027 * We don't get() the stream_class since doing so would introduce
1028 * a circular ownership between event classes and stream classes.
1029 *
1030 * A stream class will always unset itself from its events before
1031 * being destroyed. This ensures that a user won't get a pointer
1032 * to a stale stream class instance from an event class.
1033 */
1034 end:
1035 return ret;
1036 }
1037
1038 BT_HIDDEN
1039 int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class,
1040 struct metadata_context *context)
1041 {
1042 int i;
1043 int count;
1044 int ret = 0;
1045 struct bt_object *attr_value = NULL;
1046
1047 assert(event_class);
1048 assert(context);
1049
1050 context->current_indentation_level = 1;
1051 g_string_assign(context->field_name, "");
1052 g_string_append(context->string, "event {\n");
1053 count = bt_ctf_event_class_get_attribute_count(event_class);
1054
1055 if (count < 0) {
1056 ret = -1;
1057 goto end;
1058 }
1059
1060 for (i = 0; i < count; ++i) {
1061 const char *attr_name = NULL;
1062
1063 attr_name = bt_ctf_event_class_get_attribute_name(
1064 event_class, i);
1065 attr_value = bt_ctf_event_class_get_attribute_value(
1066 event_class, i);
1067
1068 if (!attr_name || !attr_value) {
1069 ret = -1;
1070 goto end;
1071 }
1072
1073 switch (bt_object_get_type(attr_value)) {
1074 case BT_OBJECT_TYPE_INTEGER:
1075 {
1076 int64_t value;
1077
1078 ret = bt_object_integer_get(attr_value, &value);
1079
1080 if (ret) {
1081 goto end;
1082 }
1083
1084 g_string_append_printf(context->string,
1085 "\t%s = %" PRId64 ";\n", attr_name, value);
1086 break;
1087 }
1088
1089 case BT_OBJECT_TYPE_STRING:
1090 {
1091 const char *value;
1092
1093 ret = bt_object_string_get(attr_value, &value);
1094
1095 if (ret) {
1096 goto end;
1097 }
1098
1099 g_string_append_printf(context->string,
1100 "\t%s = \"%s\";\n", attr_name, value);
1101 break;
1102 }
1103
1104 default:
1105 /* should never happen */
1106 assert(false);
1107 break;
1108 }
1109
1110 BT_OBJECT_PUT(attr_value);
1111 }
1112
1113 if (event_class->context) {
1114 g_string_append(context->string, "\tcontext := ");
1115 ret = bt_ctf_field_type_serialize(event_class->context,
1116 context);
1117 if (ret) {
1118 goto end;
1119 }
1120 g_string_append(context->string, ";\n");
1121 }
1122
1123 if (event_class->fields) {
1124 g_string_append(context->string, "\tfields := ");
1125 ret = bt_ctf_field_type_serialize(event_class->fields, context);
1126 if (ret) {
1127 goto end;
1128 }
1129 g_string_append(context->string, ";\n");
1130 }
1131
1132 g_string_append(context->string, "};\n\n");
1133 end:
1134 context->current_indentation_level = 0;
1135 BT_OBJECT_PUT(attr_value);
1136 return ret;
1137 }
1138
1139 void bt_ctf_event_class_set_native_byte_order(
1140 struct bt_ctf_event_class *event_class,
1141 int byte_order)
1142 {
1143 if (!event_class) {
1144 return;
1145 }
1146
1147 bt_ctf_field_type_set_native_byte_order(event_class->context,
1148 byte_order);
1149 bt_ctf_field_type_set_native_byte_order(event_class->fields,
1150 byte_order);
1151 }
1152
1153 BT_HIDDEN
1154 int bt_ctf_event_validate(struct bt_ctf_event *event)
1155 {
1156 /* Make sure each field's payload has been set */
1157 int ret;
1158
1159 assert(event);
1160 ret = bt_ctf_field_validate(event->event_header);
1161 if (ret) {
1162 goto end;
1163 }
1164
1165 ret = bt_ctf_field_validate(event->fields_payload);
1166 if (ret) {
1167 goto end;
1168 }
1169
1170 if (event->event_class->context) {
1171 ret = bt_ctf_field_validate(event->context_payload);
1172 }
1173 end:
1174 return ret;
1175 }
1176
1177 BT_HIDDEN
1178 int bt_ctf_event_serialize(struct bt_ctf_event *event,
1179 struct ctf_stream_pos *pos)
1180 {
1181 int ret = 0;
1182
1183 assert(event);
1184 assert(pos);
1185 if (event->context_payload) {
1186 ret = bt_ctf_field_serialize(event->context_payload, pos);
1187 if (ret) {
1188 goto end;
1189 }
1190 }
1191
1192 if (event->fields_payload) {
1193 ret = bt_ctf_field_serialize(event->fields_payload, pos);
1194 if (ret) {
1195 goto end;
1196 }
1197 }
1198 end:
1199 return ret;
1200 }
1201
1202 BT_HIDDEN
1203 int bt_ctf_event_populate_event_header(struct bt_ctf_event *event)
1204 {
1205 int ret = 0;
1206 struct bt_ctf_field *id_field = NULL, *timestamp_field = NULL;
1207
1208 if (!event) {
1209 ret = -1;
1210 goto end;
1211 }
1212
1213 id_field = bt_ctf_field_structure_get_field(event->event_header, "id");
1214 if (id_field) {
1215 ret = set_integer_field_value(id_field,
1216 (uint64_t) bt_ctf_event_class_get_id(
1217 event->event_class));
1218 if (ret) {
1219 goto end;
1220 }
1221 }
1222
1223 timestamp_field = bt_ctf_field_structure_get_field(event->event_header,
1224 "timestamp");
1225 if (timestamp_field) {
1226 struct bt_ctf_field_type *timestamp_field_type =
1227 bt_ctf_field_get_type(timestamp_field);
1228 struct bt_ctf_clock *mapped_clock;
1229
1230 assert(timestamp_field_type);
1231 mapped_clock = bt_ctf_field_type_integer_get_mapped_clock(
1232 timestamp_field_type);
1233 bt_ctf_field_type_put(timestamp_field_type);
1234 if (mapped_clock) {
1235 uint64_t timestamp = bt_ctf_clock_get_time(
1236 mapped_clock);
1237
1238 bt_ctf_clock_put(mapped_clock);
1239 if (timestamp == (uint64_t) -1ULL) {
1240 goto end;
1241 }
1242
1243 ret = set_integer_field_value(timestamp_field,
1244 timestamp);
1245 if (ret) {
1246 goto end;
1247 }
1248 }
1249 }
1250 end:
1251 if (id_field) {
1252 bt_ctf_field_put(id_field);
1253 }
1254 if (timestamp_field) {
1255 bt_ctf_field_put(timestamp_field);
1256 }
1257 return ret;
1258 }
1259
1260 BT_HIDDEN
1261 int bt_ctf_event_set_stream(struct bt_ctf_event *event,
1262 struct bt_ctf_stream *stream)
1263 {
1264 int ret = 0;
1265
1266 if (!event) {
1267 ret = -1;
1268 goto end;
1269 }
1270
1271 if (event->stream && stream) {
1272 /* Already attached to a stream */
1273 ret = -1;
1274 goto end;
1275 }
1276
1277 event->stream = stream;
1278 end:
1279 return ret;
1280 }
1281
1282 struct bt_ctf_event *bt_ctf_event_copy(struct bt_ctf_event *event)
1283 {
1284 struct bt_ctf_event *copy = NULL;
1285
1286 if (!event) {
1287 goto error;
1288 }
1289
1290 copy = g_new0(struct bt_ctf_event, 1);
1291 if (!copy) {
1292 goto error;
1293 }
1294
1295 bt_ctf_ref_init(&copy->ref_count);
1296 copy->event_class = event->event_class;
1297 bt_ctf_event_class_get(copy->event_class);
1298 copy->stream = event->stream;
1299
1300 if (event->event_header) {
1301 copy->event_header = bt_ctf_field_copy(event->event_header);
1302
1303 if (!copy->event_header) {
1304 goto error;
1305 }
1306 }
1307
1308 if (event->context_payload) {
1309 copy->context_payload = bt_ctf_field_copy(
1310 event->context_payload);
1311
1312 if (!copy->context_payload) {
1313 goto error;
1314 }
1315 }
1316
1317 if (event->fields_payload) {
1318 copy->fields_payload = bt_ctf_field_copy(event->fields_payload);
1319
1320 if (!copy->fields_payload) {
1321 goto error;
1322 }
1323 }
1324
1325 return copy;
1326
1327 error:
1328 if (copy) {
1329 if (copy->event_class) {
1330 bt_ctf_event_class_put(copy->event_class);
1331 }
1332
1333 if (copy->event_header) {
1334 bt_ctf_field_put(copy->event_header);
1335 }
1336
1337 if (copy->context_payload) {
1338 bt_ctf_field_put(copy->context_payload);
1339 }
1340
1341 if (copy->fields_payload) {
1342 bt_ctf_field_put(copy->fields_payload);
1343 }
1344 }
1345
1346 g_free(copy);
1347 return NULL;
1348 }
This page took 0.060072 seconds and 5 git commands to generate.