Unify reference counting using a common bt_object base
[babeltrace.git] / formats / ctf / ir / stream.c
1 /*
2 * stream.c
3 *
4 * Babeltrace CTF IR - Stream
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-ir/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-ir/stream.h>
36 #include <babeltrace/ctf-ir/stream-internal.h>
37 #include <babeltrace/ctf-ir/stream-class-internal.h>
38 #include <babeltrace/ref.h>
39 #include <babeltrace/ctf-writer/functor-internal.h>
40 #include <babeltrace/compiler.h>
41 #include <babeltrace/align.h>
42 #include <babeltrace/ctf/ctf-index.h>
43
44 static
45 void bt_ctf_stream_destroy(struct bt_object *obj);
46 static
47 int set_structure_field_integer(struct bt_ctf_field *, char *, uint64_t);
48
49 static
50 int set_packet_header_magic(struct bt_ctf_stream *stream)
51 {
52 int ret = 0;
53 struct bt_ctf_field_type *magic_field_type = NULL;
54 struct bt_ctf_field *magic_field = bt_ctf_field_structure_get_field(
55 stream->packet_header, "magic");
56
57 if (!magic_field) {
58 /* No magic field found. Not an error, skip. */
59 goto end;
60 }
61
62 if (!bt_ctf_field_validate(magic_field)) {
63 /* Value already set. Not an error, skip. */
64 goto end;
65 }
66
67 magic_field_type = bt_ctf_field_get_type(magic_field);
68 assert(magic_field_type);
69
70 if (bt_ctf_field_type_get_type_id(magic_field_type) !=
71 CTF_TYPE_INTEGER) {
72 /* Magic field is not an integer. Not an error, skip. */
73 goto end;
74 }
75
76 if (bt_ctf_field_type_integer_get_size(magic_field_type) != 32) {
77 /*
78 * Magic field is not of the expected size.
79 * Not an error, skip.
80 */
81 goto end;
82 }
83
84 ret = bt_ctf_field_type_integer_get_signed(magic_field_type);
85 assert(ret >= 0);
86 if (ret) {
87 ret = bt_ctf_field_signed_integer_set_value(magic_field,
88 (int64_t) 0xC1FC1FC1);
89 } else {
90 ret = bt_ctf_field_unsigned_integer_set_value(magic_field,
91 (uint64_t) 0xC1FC1FC1);
92 }
93 end:
94 bt_put(magic_field);
95 bt_put(magic_field_type);
96 return ret;
97 }
98
99 static
100 int set_packet_header_uuid(struct bt_ctf_stream *stream)
101 {
102 int i, ret = 0;
103 struct bt_ctf_field_type *uuid_field_type = NULL;
104 struct bt_ctf_field_type *element_field_type = NULL;
105 struct bt_ctf_field *uuid_field = bt_ctf_field_structure_get_field(
106 stream->packet_header, "uuid");
107
108 if (!uuid_field) {
109 /* No uuid field found. Not an error, skip. */
110 goto end;
111 }
112
113 if (!bt_ctf_field_validate(uuid_field)) {
114 /* Value already set. Not an error, skip. */
115 goto end;
116 }
117
118 uuid_field_type = bt_ctf_field_get_type(uuid_field);
119 assert(uuid_field_type);
120 if (bt_ctf_field_type_get_type_id(uuid_field_type) !=
121 CTF_TYPE_ARRAY) {
122 /* UUID field is not an array. Not an error, skip. */
123 goto end;
124 }
125
126 if (bt_ctf_field_type_array_get_length(uuid_field_type) != 16) {
127 /*
128 * UUID field is not of the expected size.
129 * Not an error, skip.
130 */
131 goto end;
132 }
133
134 element_field_type = bt_ctf_field_type_array_get_element_type(
135 uuid_field_type);
136 assert(element_field_type);
137 if (bt_ctf_field_type_get_type_id(element_field_type) !=
138 CTF_TYPE_INTEGER) {
139 /* UUID array elements are not integers. Not an error, skip */
140 goto end;
141 }
142
143 for (i = 0; i < 16; i++) {
144 struct bt_ctf_field *uuid_element =
145 bt_ctf_field_array_get_field(uuid_field, i);
146
147 ret = bt_ctf_field_type_integer_get_signed(element_field_type);
148 assert(ret >= 0);
149
150 if (ret) {
151 ret = bt_ctf_field_signed_integer_set_value(
152 uuid_element, (int64_t) stream->trace->uuid[i]);
153 } else {
154 ret = bt_ctf_field_unsigned_integer_set_value(
155 uuid_element,
156 (uint64_t) stream->trace->uuid[i]);
157 }
158 bt_put(uuid_element);
159 if (ret) {
160 goto end;
161 }
162 }
163
164 end:
165 bt_put(uuid_field);
166 bt_put(uuid_field_type);
167 bt_put(element_field_type);
168 return ret;
169 }
170 static
171 int set_packet_header_stream_id(struct bt_ctf_stream *stream)
172 {
173 int ret = 0;
174 uint32_t stream_id;
175 struct bt_ctf_field_type *stream_id_field_type = NULL;
176 struct bt_ctf_field *stream_id_field = bt_ctf_field_structure_get_field(
177 stream->packet_header, "stream_id");
178
179 if (!stream_id_field) {
180 /* No stream_id field found. Not an error, skip. */
181 goto end;
182 }
183
184 if (!bt_ctf_field_validate(stream_id_field)) {
185 /* Value already set. Not an error, skip. */
186 goto end;
187 }
188
189 stream_id_field_type = bt_ctf_field_get_type(stream_id_field);
190 assert(stream_id_field_type);
191 if (bt_ctf_field_type_get_type_id(stream_id_field_type) !=
192 CTF_TYPE_INTEGER) {
193 /* stream_id field is not an integer. Not an error, skip. */
194 goto end;
195 }
196
197 stream_id = stream->stream_class->id;
198 ret = bt_ctf_field_type_integer_get_signed(stream_id_field_type);
199 assert(ret >= 0);
200 if (ret) {
201 ret = bt_ctf_field_signed_integer_set_value(stream_id_field,
202 (int64_t) stream_id);
203 } else {
204 ret = bt_ctf_field_unsigned_integer_set_value(stream_id_field,
205 (uint64_t) stream_id);
206 }
207 end:
208 bt_put(stream_id_field);
209 bt_put(stream_id_field_type);
210 return ret;
211 }
212
213 static
214 int set_packet_header(struct bt_ctf_stream *stream)
215 {
216 int ret;
217
218 ret = set_packet_header_magic(stream);
219 if (ret) {
220 goto end;
221 }
222
223 ret = set_packet_header_uuid(stream);
224 if (ret) {
225 goto end;
226 }
227
228 ret = set_packet_header_stream_id(stream);
229 if (ret) {
230 goto end;
231 }
232 end:
233 return ret;
234 }
235
236 static
237 void put_event(struct bt_ctf_event *event)
238 {
239 bt_ctf_event_set_stream(event, NULL);
240 bt_put(event);
241 }
242
243 BT_HIDDEN
244 struct bt_ctf_stream *bt_ctf_stream_create(
245 struct bt_ctf_stream_class *stream_class,
246 struct bt_ctf_trace *trace)
247 {
248 int ret;
249 struct bt_ctf_stream *stream = NULL;
250
251 if (!stream_class || !trace) {
252 goto end;
253 }
254
255 stream = g_new0(struct bt_ctf_stream, 1);
256 if (!stream) {
257 goto end;
258 }
259
260 /* A stream has no ownership of its trace (weak ptr) */
261 stream->trace = trace;
262 bt_object_init(stream, bt_ctf_stream_destroy);
263 stream->packet_context = bt_ctf_field_create(
264 stream_class->packet_context_type);
265 if (!stream->packet_context) {
266 goto error;
267 }
268
269 /*
270 * A stream class may not have a stream event context defined
271 * in which case this stream will never have a stream_event_context
272 * member since, after a stream's creation, the parent stream class
273 * is "frozen" (immutable).
274 */
275 if (stream_class->event_context_type) {
276 stream->event_context = bt_ctf_field_create(
277 stream_class->event_context_type);
278 if (!stream->packet_context) {
279 goto error;
280 }
281 }
282
283 /* Initialize events_discarded */
284 ret = set_structure_field_integer(stream->packet_context,
285 "events_discarded", 0);
286 if (ret) {
287 goto error;
288 }
289
290 stream->pos.fd = -1;
291 stream->id = stream_class->next_stream_id++;
292 stream->stream_class = stream_class;
293 bt_get(stream_class);
294 stream->events = g_ptr_array_new_with_free_func(
295 (GDestroyNotify) put_event);
296 if (!stream->events) {
297 goto error;
298 }
299 if (stream_class->event_context_type) {
300 stream->event_contexts = g_ptr_array_new_with_free_func(
301 (GDestroyNotify) bt_ctf_field_put);
302 if (!stream->event_contexts) {
303 goto error;
304 }
305 }
306
307 /* A trace is not allowed to have a NULL packet header */
308 assert(trace->packet_header_type);
309 stream->packet_header = bt_ctf_field_create(trace->packet_header_type);
310 if (!stream->packet_header) {
311 goto error;
312 }
313 /*
314 * Attempt to populate the default trace packet header fields
315 * (magic, uuid and stream_id). This will _not_ fail shall the
316 * fields not be found or be of an incompatible type; they will
317 * simply not be populated automatically. The user will have to
318 * make sure to set the trace packet header fields himself before
319 * flushing.
320 */
321 ret = set_packet_header(stream);
322 if (ret) {
323 goto error;
324 }
325 end:
326 return stream;
327 error:
328 BT_PUT(stream);
329 return stream;
330 }
331
332 BT_HIDDEN
333 int bt_ctf_stream_set_fd(struct bt_ctf_stream *stream, int fd)
334 {
335 int ret = 0;
336
337 if (stream->pos.fd != -1) {
338 ret = -1;
339 goto end;
340 }
341
342 ctf_init_pos(&stream->pos, NULL, fd, O_RDWR);
343 stream->pos.fd = fd;
344 end:
345 return ret;
346 }
347
348 struct bt_ctf_stream_class *bt_ctf_stream_get_class(
349 struct bt_ctf_stream *stream)
350 {
351 struct bt_ctf_stream_class *stream_class = NULL;
352
353 if (!stream) {
354 goto end;
355 }
356
357 stream_class = stream->stream_class;
358 bt_get(stream_class);
359 end:
360 return stream_class;
361 }
362
363 int bt_ctf_stream_get_discarded_events_count(
364 struct bt_ctf_stream *stream, uint64_t *count)
365 {
366 int64_t ret = 0;
367 int field_signed;
368 struct bt_ctf_field *events_discarded_field = NULL;
369 struct bt_ctf_field_type *events_discarded_field_type = NULL;
370
371 if (!stream || !count || !stream->packet_context) {
372 ret = -1;
373 goto end;
374 }
375
376 events_discarded_field = bt_ctf_field_structure_get_field(
377 stream->packet_context, "events_discarded");
378 if (!events_discarded_field) {
379 ret = -1;
380 goto end;
381 }
382
383 events_discarded_field_type = bt_ctf_field_get_type(
384 events_discarded_field);
385 if (!events_discarded_field_type) {
386 ret = -1;
387 goto end;
388 }
389
390 field_signed = bt_ctf_field_type_integer_get_signed(
391 events_discarded_field_type);
392 if (field_signed < 0) {
393 ret = field_signed;
394 goto end;
395 }
396
397 if (field_signed) {
398 int64_t signed_count;
399
400 ret = bt_ctf_field_signed_integer_get_value(
401 events_discarded_field, &signed_count);
402 if (ret) {
403 goto end;
404 }
405 if (signed_count < 0) {
406 /* Invalid value */
407 ret = -1;
408 goto end;
409 }
410 *count = (uint64_t) signed_count;
411 } else {
412 ret = bt_ctf_field_unsigned_integer_get_value(
413 events_discarded_field, count);
414 if (ret) {
415 goto end;
416 }
417 }
418 end:
419 bt_put(events_discarded_field);
420 bt_put(events_discarded_field_type);
421 return ret;
422 }
423
424 void bt_ctf_stream_append_discarded_events(struct bt_ctf_stream *stream,
425 uint64_t event_count)
426 {
427 int ret;
428 int field_signed;
429 uint64_t previous_count;
430 uint64_t new_count;
431 struct bt_ctf_field *events_discarded_field = NULL;
432 struct bt_ctf_field_type *events_discarded_field_type = NULL;
433
434 if (!stream || !stream->packet_context) {
435 goto end;
436 }
437
438 ret = bt_ctf_stream_get_discarded_events_count(stream,
439 &previous_count);
440 if (ret) {
441 goto end;
442 }
443
444 events_discarded_field = bt_ctf_field_structure_get_field(
445 stream->packet_context, "events_discarded");
446 if (!events_discarded_field) {
447 goto end;
448 }
449
450 events_discarded_field_type = bt_ctf_field_get_type(
451 events_discarded_field);
452 if (!events_discarded_field_type) {
453 goto end;
454 }
455
456 field_signed = bt_ctf_field_type_integer_get_signed(
457 events_discarded_field_type);
458 if (field_signed < 0) {
459 goto end;
460 }
461
462 new_count = previous_count + event_count;
463 if (field_signed) {
464 ret = bt_ctf_field_signed_integer_set_value(
465 events_discarded_field, (int64_t) new_count);
466 if (ret) {
467 goto end;
468 }
469 } else {
470 ret = bt_ctf_field_unsigned_integer_set_value(
471 events_discarded_field, new_count);
472 if (ret) {
473 goto end;
474 }
475 }
476
477 end:
478 bt_put(events_discarded_field);
479 bt_put(events_discarded_field_type);
480 }
481
482 int bt_ctf_stream_append_event(struct bt_ctf_stream *stream,
483 struct bt_ctf_event *event)
484 {
485 int ret = 0;
486 struct bt_ctf_field *event_context_copy = NULL;
487
488 if (!stream || !event) {
489 ret = -1;
490 goto end;
491 }
492
493 ret = bt_ctf_event_set_stream(event, stream);
494 if (ret) {
495 /* Event was already associated to a stream */
496 ret = -1;
497 goto end;
498 }
499
500 ret = bt_ctf_event_populate_event_header(event);
501 if (ret) {
502 goto end;
503 }
504
505 /* Make sure the event's payload is set */
506 ret = bt_ctf_event_validate(event);
507 if (ret) {
508 goto end;
509 }
510
511 /* Sample the current stream event context by copying it */
512 if (stream->event_context) {
513 /* Make sure the event context's payload is set */
514 ret = bt_ctf_field_validate(stream->event_context);
515 if (ret) {
516 goto end;
517 }
518
519 event_context_copy = bt_ctf_field_copy(stream->event_context);
520 if (!event_context_copy) {
521 ret = -1;
522 goto end;
523 }
524 }
525
526 bt_get(event);
527 /* Save the new event along with its associated stream event context */
528 g_ptr_array_add(stream->events, event);
529 if (event_context_copy) {
530 g_ptr_array_add(stream->event_contexts, event_context_copy);
531 }
532 end:
533 if (ret) {
534 (void) bt_ctf_event_set_stream(event, NULL);
535 }
536 return ret;
537 }
538
539 struct bt_ctf_field *bt_ctf_stream_get_packet_context(
540 struct bt_ctf_stream *stream)
541 {
542 struct bt_ctf_field *packet_context = NULL;
543
544 if (!stream) {
545 goto end;
546 }
547
548 packet_context = stream->packet_context;
549 if (packet_context) {
550 bt_get(packet_context);
551 }
552 end:
553 return packet_context;
554 }
555
556 int bt_ctf_stream_set_packet_context(struct bt_ctf_stream *stream,
557 struct bt_ctf_field *field)
558 {
559 int ret = 0;
560 struct bt_ctf_field_type *field_type;
561
562 if (!stream || !field) {
563 ret = -1;
564 goto end;
565 }
566
567 field_type = bt_ctf_field_get_type(field);
568 if (field_type != stream->stream_class->packet_context_type) {
569 ret = -1;
570 goto end;
571 }
572
573 bt_put(field_type);
574 bt_get(field);
575 bt_put(stream->packet_context);
576 stream->packet_context = field;
577 end:
578 return ret;
579 }
580
581 struct bt_ctf_field *bt_ctf_stream_get_event_context(
582 struct bt_ctf_stream *stream)
583 {
584 struct bt_ctf_field *event_context = NULL;
585
586 if (!stream) {
587 goto end;
588 }
589
590 event_context = stream->event_context;
591 if (event_context) {
592 bt_get(event_context);
593 }
594 end:
595 return event_context;
596 }
597
598 int bt_ctf_stream_set_event_context(struct bt_ctf_stream *stream,
599 struct bt_ctf_field *field)
600 {
601 int ret = 0;
602 struct bt_ctf_field_type *field_type = NULL;
603
604 if (!stream || !field) {
605 ret = -1;
606 goto end;
607 }
608
609 field_type = bt_ctf_field_get_type(field);
610 if (field_type != stream->stream_class->event_context_type) {
611 ret = -1;
612 goto end;
613 }
614
615 bt_get(field);
616 bt_put(stream->event_context);
617 stream->event_context = field;
618 end:
619 bt_put(field_type);
620 return ret;
621 }
622
623 struct bt_ctf_field *bt_ctf_stream_get_packet_header(
624 struct bt_ctf_stream *stream)
625 {
626 struct bt_ctf_field *packet_header = NULL;
627
628 if (!stream) {
629 goto end;
630 }
631
632 packet_header = stream->packet_header;
633 if (packet_header) {
634 bt_get(packet_header);
635 }
636 end:
637 return packet_header;
638 }
639
640 int bt_ctf_stream_set_packet_header(struct bt_ctf_stream *stream,
641 struct bt_ctf_field *field)
642 {
643 int ret = 0;
644 struct bt_ctf_field_type *field_type = NULL;
645
646 if (!stream || !field) {
647 ret = -1;
648 goto end;
649 }
650
651 field_type = bt_ctf_field_get_type(field);
652 if (field_type != stream->trace->packet_header_type) {
653 ret = -1;
654 goto end;
655 }
656
657 bt_get(field);
658 bt_put(stream->packet_header);
659 stream->packet_header = field;
660 end:
661 bt_put(field_type);
662 return ret;
663 }
664
665 static
666 int get_event_header_timestamp(struct bt_ctf_field *event_header, uint64_t *timestamp)
667 {
668 int ret = 0;
669 struct bt_ctf_field *timestamp_field = NULL;
670 struct bt_ctf_field_type *timestamp_field_type = NULL;
671
672 timestamp_field = bt_ctf_field_structure_get_field(event_header,
673 "timestamp");
674 if (!timestamp_field) {
675 ret = -1;
676 goto end;
677 }
678
679 timestamp_field_type = bt_ctf_field_get_type(timestamp_field);
680 assert(timestamp_field_type);
681 if (bt_ctf_field_type_get_type_id(timestamp_field_type) !=
682 CTF_TYPE_INTEGER) {
683 ret = -1;
684 goto end;
685 }
686
687 if (bt_ctf_field_type_integer_get_signed(timestamp_field_type)) {
688 int64_t val;
689
690 ret = bt_ctf_field_signed_integer_get_value(timestamp_field,
691 &val);
692 if (ret) {
693 goto end;
694 }
695 *timestamp = (uint64_t) val;
696 } else {
697 ret = bt_ctf_field_unsigned_integer_get_value(timestamp_field,
698 timestamp);
699 if (ret) {
700 goto end;
701 }
702 }
703 end:
704 bt_put(timestamp_field);
705 bt_put(timestamp_field_type);
706 return ret;
707 }
708
709 int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
710 {
711 int ret = 0;
712 size_t i;
713 uint64_t timestamp_begin, timestamp_end, events_discarded;
714 struct bt_ctf_field *integer = NULL;
715 struct ctf_stream_pos packet_context_pos;
716
717 if (!stream || stream->pos.fd < 0) {
718 /*
719 * Stream does not have an associated fd. It is,
720 * therefore, not a stream being used to write events.
721 */
722 ret = -1;
723 goto end;
724 }
725
726 if (!stream->events->len) {
727 goto end;
728 }
729
730 ret = bt_ctf_field_validate(stream->packet_header);
731 if (ret) {
732 goto end;
733 }
734
735 /* mmap the next packet */
736 ctf_packet_seek(&stream->pos.parent, 0, SEEK_CUR);
737
738 ret = bt_ctf_field_serialize(stream->packet_header, &stream->pos);
739 if (ret) {
740 goto end;
741 }
742
743 /* Set the default context attributes if present and unset. */
744 if (!get_event_header_timestamp(
745 ((struct bt_ctf_event *) g_ptr_array_index(
746 stream->events, 0))->event_header, &timestamp_begin)) {
747 ret = set_structure_field_integer(stream->packet_context,
748 "timestamp_begin", timestamp_begin);
749 if (ret) {
750 goto end;
751 }
752 }
753
754 if (!get_event_header_timestamp(
755 ((struct bt_ctf_event *) g_ptr_array_index(
756 stream->events, stream->events->len - 1))->event_header,
757 &timestamp_end)) {
758
759 ret = set_structure_field_integer(stream->packet_context,
760 "timestamp_end", timestamp_end);
761 if (ret) {
762 goto end;
763 }
764 }
765 ret = set_structure_field_integer(stream->packet_context,
766 "content_size", UINT64_MAX);
767 if (ret) {
768 goto end;
769 }
770
771 ret = set_structure_field_integer(stream->packet_context,
772 "packet_size", UINT64_MAX);
773 if (ret) {
774 goto end;
775 }
776
777 /* Write packet context */
778 memcpy(&packet_context_pos, &stream->pos,
779 sizeof(struct ctf_stream_pos));
780 ret = bt_ctf_field_serialize(stream->packet_context,
781 &stream->pos);
782 if (ret) {
783 goto end;
784 }
785
786 ret = bt_ctf_stream_get_discarded_events_count(stream,
787 &events_discarded);
788 if (ret) {
789 goto end;
790 }
791
792 /* Unset the packet context's fields. */
793 ret = bt_ctf_field_reset(stream->packet_context);
794 if (ret) {
795 goto end;
796 }
797
798 /* Set the previous number of discarded events. */
799 ret = set_structure_field_integer(stream->packet_context,
800 "events_discarded", events_discarded);
801 if (ret) {
802 goto end;
803 }
804
805 for (i = 0; i < stream->events->len; i++) {
806 struct bt_ctf_event *event = g_ptr_array_index(
807 stream->events, i);
808
809 ret = bt_ctf_field_reset(event->event_header);
810 if (ret) {
811 goto end;
812 }
813
814 /* Write event header */
815 ret = bt_ctf_field_serialize(event->event_header,
816 &stream->pos);
817 if (ret) {
818 goto end;
819 }
820
821 /* Write stream event context */
822 if (stream->event_contexts) {
823 ret = bt_ctf_field_serialize(
824 g_ptr_array_index(stream->event_contexts, i),
825 &stream->pos);
826 if (ret) {
827 goto end;
828 }
829 }
830
831 /* Write event content */
832 ret = bt_ctf_event_serialize(event, &stream->pos);
833 if (ret) {
834 goto end;
835 }
836 }
837
838 /*
839 * Update the packet total size and content size and overwrite the
840 * packet context.
841 * Copy base_mma as the packet may have been remapped (e.g. when a
842 * packet is resized).
843 */
844 packet_context_pos.base_mma = stream->pos.base_mma;
845 ret = set_structure_field_integer(stream->packet_context,
846 "content_size", stream->pos.offset);
847 if (ret) {
848 goto end;
849 }
850
851 ret = set_structure_field_integer(stream->packet_context,
852 "packet_size", stream->pos.packet_size);
853 if (ret) {
854 goto end;
855 }
856
857 ret = bt_ctf_field_serialize(stream->packet_context,
858 &packet_context_pos);
859 if (ret) {
860 goto end;
861 }
862
863 g_ptr_array_set_size(stream->events, 0);
864 if (stream->event_contexts) {
865 g_ptr_array_set_size(stream->event_contexts, 0);
866 }
867 stream->flushed_packet_count++;
868 end:
869 bt_put(integer);
870 return ret;
871 }
872
873 void bt_ctf_stream_get(struct bt_ctf_stream *stream)
874 {
875 bt_get(stream);
876 }
877
878 void bt_ctf_stream_put(struct bt_ctf_stream *stream)
879 {
880 bt_put(stream);
881 }
882
883 static
884 void bt_ctf_stream_destroy(struct bt_object *obj)
885 {
886 struct bt_ctf_stream *stream;
887
888 stream = container_of(obj, struct bt_ctf_stream, base);
889 ctf_fini_pos(&stream->pos);
890 if (stream->pos.fd >= 0 && close(stream->pos.fd)) {
891 perror("close");
892 }
893
894 bt_put(stream->stream_class);
895 if (stream->events) {
896 g_ptr_array_free(stream->events, TRUE);
897 }
898 if (stream->event_contexts) {
899 g_ptr_array_free(stream->event_contexts, TRUE);
900 }
901 bt_put(stream->packet_header);
902 bt_put(stream->packet_context);
903 bt_put(stream->event_context);
904 g_free(stream);
905 }
906
907 static
908 int set_structure_field_integer(struct bt_ctf_field *structure, char *name,
909 uint64_t value)
910 {
911 int ret = 0;
912 struct bt_ctf_field_type *field_type = NULL;
913 struct bt_ctf_field *integer =
914 bt_ctf_field_structure_get_field(structure, name);
915
916 if (!structure || !name) {
917 ret = -1;
918 goto end;
919 }
920
921 if (!integer) {
922 /* Field not found, not an error. */
923 goto end;
924 }
925
926 /* Make sure the payload has not already been set. */
927 if (!bt_ctf_field_validate(integer)) {
928 /* Payload already set, not an error */
929 goto end;
930 }
931
932 field_type = bt_ctf_field_get_type(integer);
933 /* Something is serioulsly wrong */
934 assert(field_type);
935 if (bt_ctf_field_type_get_type_id(field_type) != CTF_TYPE_INTEGER) {
936 /*
937 * The user most likely meant for us to populate this field
938 * automatically. However, we can only do this if the field
939 * is an integer. Return an error.
940 */
941 ret = -1;
942 goto end;
943 }
944
945 if (bt_ctf_field_type_integer_get_signed(field_type)) {
946 ret = bt_ctf_field_signed_integer_set_value(integer,
947 (int64_t) value);
948 } else {
949 ret = bt_ctf_field_unsigned_integer_set_value(integer, value);
950 }
951 end:
952 bt_put(integer);
953 bt_put(field_type);
954 return ret;
955 }
This page took 0.048165 seconds and 4 git commands to generate.