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