ir: add bt_ctf_event_copy() (event deep copy)
[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
708 struct bt_ctf_field *bt_ctf_event_get_payload(struct bt_ctf_event *event,
709 const char *name)
710 {
711 struct bt_ctf_field *field = NULL;
712
713 if (!event) {
714 goto end;
715 }
716
717 if (name) {
718 field = bt_ctf_field_structure_get_field(event->fields_payload,
719 name);
720 } else {
721 field = event->fields_payload;
722 bt_ctf_field_get(field);
723 }
724 end:
725 return field;
726 }
727
728 struct bt_ctf_field *bt_ctf_event_get_payload_by_index(
729 struct bt_ctf_event *event, int index)
730 {
731 struct bt_ctf_field *field = NULL;
732
733 if (!event || index < 0) {
734 goto end;
735 }
736
737 field = bt_ctf_field_structure_get_field_by_index(event->fields_payload,
738 index);
739 end:
740 return field;
741 }
742
743 struct bt_ctf_field *bt_ctf_event_get_event_header(
744 struct bt_ctf_event *event)
745 {
746 struct bt_ctf_field *header = NULL;
747
748 if (!event || !event->event_header) {
749 goto end;
750 }
751
752 header = event->event_header;
753 bt_ctf_field_get(header);
754 end:
755 return header;
756 }
757
758 int bt_ctf_event_set_event_header(struct bt_ctf_event *event,
759 struct bt_ctf_field *header)
760 {
761 int ret = 0;
762 struct bt_ctf_field_type *field_type = NULL;
763
764 if (!event || !header) {
765 ret = -1;
766 goto end;
767 }
768
769 /* Could be NULL since an event class doesn't own a stream class */
770 if (!event->event_class->stream_class) {
771 ret = -1;
772 goto end;
773 }
774
775 /*
776 * Ensure the provided header's type matches the one registered to the
777 * stream class.
778 */
779 field_type = bt_ctf_field_get_type(header);
780 if (field_type != event->event_class->stream_class->event_header_type) {
781 ret = -1;
782 goto end;
783 }
784
785 bt_ctf_field_get(header);
786 bt_ctf_field_put(event->event_header);
787 event->event_header = header;
788 end:
789 if (field_type) {
790 bt_ctf_field_type_put(field_type);
791 }
792 return ret;
793 }
794
795 struct bt_ctf_field *bt_ctf_event_get_event_context(
796 struct bt_ctf_event *event)
797 {
798 struct bt_ctf_field *context = NULL;
799
800 if (!event || !event->context_payload) {
801 goto end;
802 }
803
804 context = event->context_payload;
805 bt_ctf_field_get(context);
806 end:
807 return context;
808 }
809
810 int bt_ctf_event_set_event_context(struct bt_ctf_event *event,
811 struct bt_ctf_field *context)
812 {
813 int ret = 0;
814 struct bt_ctf_field_type *field_type = NULL;
815
816 if (!event || !context) {
817 ret = -1;
818 goto end;
819 }
820
821 field_type = bt_ctf_field_get_type(context);
822 if (field_type != event->event_class->context) {
823 ret = -1;
824 goto end;
825 }
826
827 bt_ctf_field_get(context);
828 bt_ctf_field_put(event->context_payload);
829 event->context_payload = context;
830 end:
831 if (field_type) {
832 bt_ctf_field_type_put(field_type);
833 }
834 return ret;
835 }
836
837 void bt_ctf_event_get(struct bt_ctf_event *event)
838 {
839 if (!event) {
840 return;
841 }
842
843 bt_ctf_ref_get(&event->ref_count);
844 }
845
846 void bt_ctf_event_put(struct bt_ctf_event *event)
847 {
848 if (!event) {
849 return;
850 }
851
852 bt_ctf_ref_put(&event->ref_count, bt_ctf_event_destroy);
853 }
854
855 static
856 void bt_ctf_event_class_destroy(struct bt_ctf_ref *ref)
857 {
858 struct bt_ctf_event_class *event_class;
859
860 if (!ref) {
861 return;
862 }
863
864 /*
865 * Don't call put() on the stream class. See comment in
866 * bt_ctf_event_class_set_stream_class for explanation.
867 */
868 event_class = container_of(ref, struct bt_ctf_event_class, ref_count);
869 if (event_class->attributes) {
870 bt_ctf_attributes_destroy(event_class->attributes);
871 }
872 if (event_class->context) {
873 bt_ctf_field_type_put(event_class->context);
874 }
875 if (event_class->fields) {
876 bt_ctf_field_type_put(event_class->fields);
877 }
878 g_free(event_class);
879 }
880
881 static
882 void bt_ctf_event_destroy(struct bt_ctf_ref *ref)
883 {
884 struct bt_ctf_event *event;
885
886 if (!ref) {
887 return;
888 }
889
890 event = container_of(ref, struct bt_ctf_event,
891 ref_count);
892 if (event->event_class) {
893 bt_ctf_event_class_put(event->event_class);
894 }
895 if (event->event_header) {
896 bt_ctf_field_put(event->event_header);
897 }
898 if (event->context_payload) {
899 bt_ctf_field_put(event->context_payload);
900 }
901 if (event->fields_payload) {
902 bt_ctf_field_put(event->fields_payload);
903 }
904 g_free(event);
905 }
906
907 static
908 int set_integer_field_value(struct bt_ctf_field* field, uint64_t value)
909 {
910 int ret = 0;
911 struct bt_ctf_field_type *field_type = NULL;
912
913 if (!field) {
914 ret = -1;
915 goto end;
916 }
917
918 if (!bt_ctf_field_validate(field)) {
919 /* Payload already set, skip! (not an error) */
920 goto end;
921 }
922
923 field_type = bt_ctf_field_get_type(field);
924 assert(field_type);
925
926 if (bt_ctf_field_type_get_type_id(field_type) != CTF_TYPE_INTEGER) {
927 /* Not an integer and the value is unset, error. */
928 ret = -1;
929 goto end;
930 }
931
932 if (bt_ctf_field_type_integer_get_signed(field_type)) {
933 ret = bt_ctf_field_signed_integer_set_value(field, (int64_t) value);
934 if (ret) {
935 /* Value is out of range, error. */
936 goto end;
937 }
938 } else {
939 ret = bt_ctf_field_unsigned_integer_set_value(field, value);
940 if (ret) {
941 /* Value is out of range, error. */
942 goto end;
943 }
944 }
945 end:
946 bt_ctf_field_type_put(field_type);
947 return ret;
948 }
949
950 BT_HIDDEN
951 void bt_ctf_event_class_freeze(struct bt_ctf_event_class *event_class)
952 {
953 assert(event_class);
954 event_class->frozen = 1;
955 bt_ctf_field_type_freeze(event_class->context);
956 bt_ctf_field_type_freeze(event_class->fields);
957 bt_ctf_attributes_freeze(event_class->attributes);
958 }
959
960 BT_HIDDEN
961 int bt_ctf_event_class_set_stream_class(struct bt_ctf_event_class *event_class,
962 struct bt_ctf_stream_class *stream_class)
963 {
964 int ret = 0;
965
966 if (!event_class) {
967 ret = -1;
968 goto end;
969 }
970
971 /* Allow a NULL stream_class to unset the current stream_class */
972 if (stream_class && event_class->stream_class) {
973 ret = -1;
974 goto end;
975 }
976
977 event_class->stream_class = stream_class;
978 /*
979 * We don't get() the stream_class since doing so would introduce
980 * a circular ownership between event classes and stream classes.
981 *
982 * A stream class will always unset itself from its events before
983 * being destroyed. This ensures that a user won't get a pointer
984 * to a stale stream class instance from an event class.
985 */
986 end:
987 return ret;
988 }
989
990 BT_HIDDEN
991 int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class,
992 struct metadata_context *context)
993 {
994 int i;
995 int count;
996 int ret = 0;
997 struct bt_object *attr_value = NULL;
998
999 assert(event_class);
1000 assert(context);
1001
1002 context->current_indentation_level = 1;
1003 g_string_assign(context->field_name, "");
1004 g_string_append(context->string, "event {\n");
1005 count = bt_ctf_event_class_get_attribute_count(event_class);
1006
1007 if (count < 0) {
1008 ret = -1;
1009 goto end;
1010 }
1011
1012 for (i = 0; i < count; ++i) {
1013 const char *attr_name = NULL;
1014
1015 attr_name = bt_ctf_event_class_get_attribute_name(
1016 event_class, i);
1017 attr_value = bt_ctf_event_class_get_attribute_value(
1018 event_class, i);
1019
1020 if (!attr_name || !attr_value) {
1021 ret = -1;
1022 goto end;
1023 }
1024
1025 switch (bt_object_get_type(attr_value)) {
1026 case BT_OBJECT_TYPE_INTEGER:
1027 {
1028 int64_t value;
1029
1030 ret = bt_object_integer_get(attr_value, &value);
1031
1032 if (ret) {
1033 goto end;
1034 }
1035
1036 g_string_append_printf(context->string,
1037 "\t%s = %" PRId64 ";\n", attr_name, value);
1038 break;
1039 }
1040
1041 case BT_OBJECT_TYPE_STRING:
1042 {
1043 const char *value;
1044
1045 ret = bt_object_string_get(attr_value, &value);
1046
1047 if (ret) {
1048 goto end;
1049 }
1050
1051 g_string_append_printf(context->string,
1052 "\t%s = \"%s\";\n", attr_name, value);
1053 break;
1054 }
1055
1056 default:
1057 /* should never happen */
1058 assert(false);
1059 break;
1060 }
1061
1062 BT_OBJECT_PUT(attr_value);
1063 }
1064
1065 if (event_class->context) {
1066 g_string_append(context->string, "\tcontext := ");
1067 ret = bt_ctf_field_type_serialize(event_class->context,
1068 context);
1069 if (ret) {
1070 goto end;
1071 }
1072 g_string_append(context->string, ";\n");
1073 }
1074
1075 if (event_class->fields) {
1076 g_string_append(context->string, "\tfields := ");
1077 ret = bt_ctf_field_type_serialize(event_class->fields, context);
1078 if (ret) {
1079 goto end;
1080 }
1081 g_string_append(context->string, ";\n");
1082 }
1083
1084 g_string_append(context->string, "};\n\n");
1085 end:
1086 context->current_indentation_level = 0;
1087 BT_OBJECT_PUT(attr_value);
1088 return ret;
1089 }
1090
1091 void bt_ctf_event_class_set_native_byte_order(
1092 struct bt_ctf_event_class *event_class,
1093 int byte_order)
1094 {
1095 if (!event_class) {
1096 return;
1097 }
1098
1099 bt_ctf_field_type_set_native_byte_order(event_class->context,
1100 byte_order);
1101 bt_ctf_field_type_set_native_byte_order(event_class->fields,
1102 byte_order);
1103 }
1104
1105 BT_HIDDEN
1106 int bt_ctf_event_validate(struct bt_ctf_event *event)
1107 {
1108 /* Make sure each field's payload has been set */
1109 int ret;
1110
1111 assert(event);
1112 ret = bt_ctf_field_validate(event->event_header);
1113 if (ret) {
1114 goto end;
1115 }
1116
1117 ret = bt_ctf_field_validate(event->fields_payload);
1118 if (ret) {
1119 goto end;
1120 }
1121
1122 if (event->event_class->context) {
1123 ret = bt_ctf_field_validate(event->context_payload);
1124 }
1125 end:
1126 return ret;
1127 }
1128
1129 BT_HIDDEN
1130 int bt_ctf_event_serialize(struct bt_ctf_event *event,
1131 struct ctf_stream_pos *pos)
1132 {
1133 int ret = 0;
1134
1135 assert(event);
1136 assert(pos);
1137 if (event->context_payload) {
1138 ret = bt_ctf_field_serialize(event->context_payload, pos);
1139 if (ret) {
1140 goto end;
1141 }
1142 }
1143
1144 if (event->fields_payload) {
1145 ret = bt_ctf_field_serialize(event->fields_payload, pos);
1146 if (ret) {
1147 goto end;
1148 }
1149 }
1150 end:
1151 return ret;
1152 }
1153
1154 BT_HIDDEN
1155 int bt_ctf_event_populate_event_header(struct bt_ctf_event *event)
1156 {
1157 int ret = 0;
1158 struct bt_ctf_field *id_field = NULL, *timestamp_field = NULL;
1159
1160 if (!event) {
1161 ret = -1;
1162 goto end;
1163 }
1164
1165 id_field = bt_ctf_field_structure_get_field(event->event_header, "id");
1166 if (id_field) {
1167 ret = set_integer_field_value(id_field,
1168 (uint64_t) bt_ctf_event_class_get_id(
1169 event->event_class));
1170 if (ret) {
1171 goto end;
1172 }
1173 }
1174
1175 timestamp_field = bt_ctf_field_structure_get_field(event->event_header,
1176 "timestamp");
1177 if (timestamp_field) {
1178 struct bt_ctf_field_type *timestamp_field_type =
1179 bt_ctf_field_get_type(timestamp_field);
1180 struct bt_ctf_clock *mapped_clock;
1181
1182 assert(timestamp_field_type);
1183 mapped_clock = bt_ctf_field_type_integer_get_mapped_clock(
1184 timestamp_field_type);
1185 bt_ctf_field_type_put(timestamp_field_type);
1186 if (mapped_clock) {
1187 uint64_t timestamp = bt_ctf_clock_get_time(
1188 mapped_clock);
1189
1190 bt_ctf_clock_put(mapped_clock);
1191 if (timestamp == (uint64_t) -1ULL) {
1192 goto end;
1193 }
1194
1195 ret = set_integer_field_value(timestamp_field,
1196 timestamp);
1197 if (ret) {
1198 goto end;
1199 }
1200 }
1201 }
1202 end:
1203 if (id_field) {
1204 bt_ctf_field_put(id_field);
1205 }
1206 if (timestamp_field) {
1207 bt_ctf_field_put(timestamp_field);
1208 }
1209 return ret;
1210 }
1211
1212 BT_HIDDEN
1213 int bt_ctf_event_set_stream(struct bt_ctf_event *event,
1214 struct bt_ctf_stream *stream)
1215 {
1216 int ret = 0;
1217
1218 if (!event) {
1219 ret = -1;
1220 goto end;
1221 }
1222
1223 if (event->stream && stream) {
1224 /* Already attached to a stream */
1225 ret = -1;
1226 goto end;
1227 }
1228
1229 event->stream = stream;
1230 end:
1231 return ret;
1232 }
1233
1234 struct bt_ctf_event *bt_ctf_event_copy(struct bt_ctf_event *event)
1235 {
1236 struct bt_ctf_event *copy = NULL;
1237
1238 if (!event) {
1239 goto error;
1240 }
1241
1242 copy = g_new0(struct bt_ctf_event, 1);
1243 if (!copy) {
1244 goto error;
1245 }
1246
1247 bt_ctf_ref_init(&copy->ref_count);
1248 copy->event_class = event->event_class;
1249 bt_ctf_event_class_get(copy->event_class);
1250 copy->stream = event->stream;
1251
1252 if (event->event_header) {
1253 copy->event_header = bt_ctf_field_copy(event->event_header);
1254
1255 if (!copy->event_header) {
1256 goto error;
1257 }
1258 }
1259
1260 if (event->context_payload) {
1261 copy->context_payload = bt_ctf_field_copy(
1262 event->context_payload);
1263
1264 if (!copy->context_payload) {
1265 goto error;
1266 }
1267 }
1268
1269 if (event->fields_payload) {
1270 copy->fields_payload = bt_ctf_field_copy(event->fields_payload);
1271
1272 if (!copy->fields_payload) {
1273 goto error;
1274 }
1275 }
1276
1277 return copy;
1278
1279 error:
1280 if (copy) {
1281 if (copy->event_class) {
1282 bt_ctf_event_class_put(copy->event_class);
1283 }
1284
1285 if (copy->event_header) {
1286 bt_ctf_field_put(copy->event_header);
1287 }
1288
1289 if (copy->context_payload) {
1290 bt_ctf_field_put(copy->context_payload);
1291 }
1292
1293 if (copy->fields_payload) {
1294 bt_ctf_field_put(copy->fields_payload);
1295 }
1296 }
1297
1298 g_free(copy);
1299 return NULL;
1300 }
This page took 0.05513 seconds and 5 git commands to generate.