Fix: lib: add NULL check for destroy_listeners in destroy_component_class
[babeltrace.git] / src / ctf-writer / stream.c
CommitLineData
3dca2276 1/*
0235b0db
MJ
2 * SPDX-License-Identifier: MIT
3 *
3dca2276
PP
4 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
3dca2276
PP
6 */
7
350ad6c1 8#define BT_LOG_TAG "CTF-WRITER/STREAM"
67d2ce02 9#include "logging.h"
3dca2276 10
578e048b 11#include <inttypes.h>
c4f23e30 12#include <stdbool.h>
578e048b
MJ
13#include <stdint.h>
14#include <unistd.h>
15
217cf9d3
PP
16#include <babeltrace2-ctf-writer/field-types.h>
17#include <babeltrace2-ctf-writer/object.h>
18#include <babeltrace2-ctf-writer/stream-class.h>
19#include <babeltrace2-ctf-writer/stream.h>
20#include <babeltrace2-ctf-writer/trace.h>
578e048b
MJ
21
22#include "common/align.h"
23#include "common/assert.h"
24#include "compat/compiler.h"
25#include "ctfser/ctfser.h"
26
27#include "assert-pre.h"
28#include "event-class.h"
29#include "event.h"
30#include "fields.h"
31#include "stream-class.h"
32#include "stream.h"
33#include "trace.h"
34#include "writer.h"
16ca5ff0
PP
35
36BT_HIDDEN
37void bt_ctf_stream_common_finalize(struct bt_ctf_stream_common *stream)
38{
39 BT_LOGD("Finalizing common stream object: addr=%p, name=\"%s\"",
40 stream, bt_ctf_stream_common_get_name(stream));
41
42 if (stream->name) {
43 g_string_free(stream->name, TRUE);
44 }
45}
46
47BT_HIDDEN
48int bt_ctf_stream_common_initialize(
49 struct bt_ctf_stream_common *stream,
50 struct bt_ctf_stream_class_common *stream_class, const char *name,
e1e02a22 51 uint64_t id, bt_ctf_object_release_func release_func)
16ca5ff0
PP
52{
53 int ret = 0;
54 struct bt_ctf_trace_common *trace = NULL;
55
e1e02a22 56 bt_ctf_object_init_shared_with_parent(&stream->base, release_func);
16ca5ff0
PP
57
58 if (!stream_class) {
59 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
60 goto error;
61 }
62
63 BT_LOGD("Initializing common stream object: stream-class-addr=%p, "
64 "stream-class-name=\"%s\", stream-name=\"%s\", "
65 "stream-id=%" PRIu64,
66 stream_class, bt_ctf_stream_class_common_get_name(stream_class),
67 name, id);
68 trace = bt_ctf_stream_class_common_borrow_trace(stream_class);
69 if (!trace) {
70 BT_LOGW("Invalid parameter: cannot create stream from a stream class which is not part of trace: "
71 "stream-class-addr=%p, stream-class-name=\"%s\", "
72 "stream-name=\"%s\"",
73 stream_class,
74 bt_ctf_stream_class_common_get_name(stream_class), name);
75 goto error;
76 }
77
78 if (id != -1ULL) {
79 /*
80 * Validate that the given ID is unique amongst all the
81 * existing trace's streams created from the same stream
82 * class.
83 */
84 size_t i;
85
86 for (i = 0; i < trace->streams->len; i++) {
87 struct bt_ctf_stream_common *trace_stream =
88 g_ptr_array_index(trace->streams, i);
89
90 if (trace_stream->stream_class != (void *) stream_class) {
91 continue;
92 }
93
94 if (trace_stream->id == id) {
95 BT_LOGW_STR("Invalid parameter: another stream in the same trace already has this ID.");
96 goto error;
97 }
98 }
99 }
100
101 /*
102 * Acquire reference to parent since stream will become publicly
103 * reachable; it needs its parent to remain valid.
104 */
e1e02a22 105 bt_ctf_object_set_parent(&stream->base, &trace->base);
16ca5ff0
PP
106 stream->stream_class = stream_class;
107 stream->id = (int64_t) id;
108
109 if (name) {
110 stream->name = g_string_new(name);
111 if (!stream->name) {
112 BT_LOGE_STR("Failed to allocate a GString.");
113 goto error;
114 }
115 }
116
117 BT_LOGD("Set common stream's trace parent: trace-addr=%p", trace);
118
119 /* Add this stream to the trace's streams */
120 BT_LOGD("Created common stream object: addr=%p", stream);
121 goto end;
122
123error:
124 ret = -1;
125
126end:
127 return ret;
128}
3dca2276
PP
129
130static
e1e02a22 131void bt_ctf_stream_destroy(struct bt_ctf_object *obj);
3dca2276
PP
132
133static
02bb4fcc 134int try_set_structure_field_integer(struct bt_ctf_field *, const char *, uint64_t);
3dca2276
PP
135
136static
137int set_integer_field_value(struct bt_ctf_field* field, uint64_t value)
138{
139 int ret = 0;
140 struct bt_ctf_field_type *field_type = NULL;
141
142 if (!field) {
143 BT_LOGW_STR("Invalid parameter: field is NULL.");
144 ret = -1;
145 goto end;
146 }
147
148 field_type = bt_ctf_field_get_type(field);
98b15851 149 BT_ASSERT_DBG(field_type);
3dca2276
PP
150
151 if (bt_ctf_field_type_get_type_id(field_type) !=
152 BT_CTF_FIELD_TYPE_ID_INTEGER) {
153 /* Not an integer and the value is unset, error. */
154 BT_LOGW("Invalid parameter: field's type is not an integer field type: "
155 "field-addr=%p, ft-addr=%p, ft-id=%s",
156 field, field_type,
16ca5ff0 157 bt_ctf_field_type_id_string((int)
3dca2276
PP
158 bt_ctf_field_type_get_type_id(field_type)));
159 ret = -1;
160 goto end;
161 }
162
163 if (bt_ctf_field_type_integer_is_signed(field_type)) {
164 ret = bt_ctf_field_integer_signed_set_value(field, (int64_t) value);
165 if (ret) {
166 /* Value is out of range, error. */
167 BT_LOGW("Cannot set signed integer field's value: "
168 "addr=%p, value=%" PRId64,
169 field, (int64_t) value);
170 goto end;
171 }
172 } else {
173 ret = bt_ctf_field_integer_unsigned_set_value(field, value);
174 if (ret) {
175 /* Value is out of range, error. */
176 BT_LOGW("Cannot set unsigned integer field's value: "
177 "addr=%p, value=%" PRIu64,
178 field, value);
179 goto end;
180 }
181 }
182end:
e1e02a22 183 bt_ctf_object_put_ref(field_type);
3dca2276
PP
184 return ret;
185}
186
187static
188int set_packet_header_magic(struct bt_ctf_stream *stream)
189{
190 int ret = 0;
191 struct bt_ctf_field *magic_field = bt_ctf_field_structure_get_field_by_name(
192 stream->packet_header, "magic");
193 const uint32_t magic_value = 0xc1fc1fc1;
194
98b15851 195 BT_ASSERT_DBG(stream);
3dca2276
PP
196
197 if (!magic_field) {
198 /* No magic field found. Not an error, skip. */
ef267d12 199 BT_LOGT("No field named `magic` in packet header: skipping: "
3dca2276
PP
200 "stream-addr=%p, stream-name=\"%s\"",
201 stream, bt_ctf_stream_get_name(stream));
202 goto end;
203 }
204
205 ret = bt_ctf_field_integer_unsigned_set_value(magic_field,
206 (uint64_t) magic_value);
207
208 if (ret) {
209 BT_LOGW("Cannot set packet header field's `magic` integer field's value: "
210 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
211 stream, bt_ctf_stream_get_name(stream),
212 magic_field, (uint64_t) magic_value);
213 } else {
ef267d12 214 BT_LOGT("Set packet header field's `magic` field's value: "
3dca2276
PP
215 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
216 stream, bt_ctf_stream_get_name(stream),
217 magic_field, (uint64_t) magic_value);
218 }
219end:
e1e02a22 220 bt_ctf_object_put_ref(magic_field);
3dca2276
PP
221 return ret;
222}
223
224static
225int set_packet_header_uuid(struct bt_ctf_stream *stream)
226{
227 int ret = 0;
228 int64_t i;
229 struct bt_ctf_trace *trace = NULL;
230 struct bt_ctf_field *uuid_field = bt_ctf_field_structure_get_field_by_name(
231 stream->packet_header, "uuid");
232
98b15851 233 BT_ASSERT_DBG(stream);
3dca2276
PP
234
235 if (!uuid_field) {
236 /* No uuid field found. Not an error, skip. */
ef267d12 237 BT_LOGT("No field named `uuid` in packet header: skipping: "
3dca2276
PP
238 "stream-addr=%p, stream-name=\"%s\"",
239 stream, bt_ctf_stream_get_name(stream));
240 goto end;
241 }
242
3fea54f6 243 trace = (struct bt_ctf_trace *)
e1e02a22 244 bt_ctf_object_get_parent(&stream->common.base);
3fea54f6 245
3dca2276
PP
246 for (i = 0; i < 16; i++) {
247 struct bt_ctf_field *uuid_element =
248 bt_ctf_field_array_get_field(uuid_field, i);
249
250 ret = bt_ctf_field_integer_unsigned_set_value(
251 uuid_element, (uint64_t) trace->common.uuid[i]);
e1e02a22 252 bt_ctf_object_put_ref(uuid_element);
3dca2276
PP
253 if (ret) {
254 BT_LOGW("Cannot set integer field's value (for `uuid` packet header field): "
255 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, "
256 "value=%" PRIu64 ", index=%" PRId64,
257 stream, bt_ctf_stream_get_name(stream),
258 uuid_element, (uint64_t) trace->common.uuid[i], i);
259 goto end;
260 }
261 }
262
ef267d12 263 BT_LOGT("Set packet header field's `uuid` field's value: "
3dca2276
PP
264 "stream-addr=%p, stream-name=\"%s\", field-addr=%p",
265 stream, bt_ctf_stream_get_name(stream), uuid_field);
266
267end:
e1e02a22
PP
268 bt_ctf_object_put_ref(uuid_field);
269 BT_CTF_OBJECT_PUT_REF_AND_RESET(trace);
3dca2276
PP
270 return ret;
271}
272static
273int set_packet_header_stream_id(struct bt_ctf_stream *stream)
274{
275 int ret = 0;
276 uint32_t stream_id;
277 struct bt_ctf_field *stream_id_field =
278 bt_ctf_field_structure_get_field_by_name(
279 stream->packet_header, "stream_id");
280
281 if (!stream_id_field) {
282 /* No stream_id field found. Not an error, skip. */
ef267d12 283 BT_LOGT("No field named `stream_id` in packet header: skipping: "
3dca2276
PP
284 "stream-addr=%p, stream-name=\"%s\"",
285 stream, bt_ctf_stream_get_name(stream));
286 goto end;
287 }
288
289 stream_id = stream->common.stream_class->id;
290 ret = bt_ctf_field_integer_unsigned_set_value(stream_id_field,
291 (uint64_t) stream_id);
292 if (ret) {
293 BT_LOGW("Cannot set packet header field's `stream_id` integer field's value: "
294 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
295 stream, bt_ctf_stream_get_name(stream),
296 stream_id_field, (uint64_t) stream_id);
297 } else {
ef267d12 298 BT_LOGT("Set packet header field's `stream_id` field's value: "
3dca2276
PP
299 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
300 stream, bt_ctf_stream_get_name(stream),
301 stream_id_field, (uint64_t) stream_id);
302 }
303
304end:
e1e02a22 305 bt_ctf_object_put_ref(stream_id_field);
3dca2276
PP
306 return ret;
307}
308
309static
310int auto_populate_packet_header(struct bt_ctf_stream *stream)
311{
312 int ret = 0;
313
314 if (!stream->packet_header) {
315 goto end;
316 }
317
318 ret = set_packet_header_magic(stream);
319 if (ret) {
320 BT_LOGW("Cannot set packet header's magic number field: "
321 "stream-addr=%p, stream-name=\"%s\"",
322 stream, bt_ctf_stream_get_name(stream));
323 goto end;
324 }
325
326 ret = set_packet_header_uuid(stream);
327 if (ret) {
328 BT_LOGW("Cannot set packet header's UUID field: "
329 "stream-addr=%p, stream-name=\"%s\"",
330 stream, bt_ctf_stream_get_name(stream));
331 goto end;
332 }
333
334 ret = set_packet_header_stream_id(stream);
335 if (ret) {
336 BT_LOGW("Cannot set packet header's stream class ID field: "
337 "stream-addr=%p, stream-name=\"%s\"",
338 stream, bt_ctf_stream_get_name(stream));
339 goto end;
340 }
341
ef267d12 342 BT_LOGT("Automatically populated stream's packet header's known fields: "
3dca2276
PP
343 "stream-addr=%p, stream-name=\"%s\"",
344 stream, bt_ctf_stream_get_name(stream));
345
346end:
347 return ret;
348}
349
350static
013f35c6
PP
351int set_packet_context_packet_size(struct bt_ctf_stream *stream,
352 uint64_t packet_size_bits)
3dca2276
PP
353{
354 int ret = 0;
355 struct bt_ctf_field *field = bt_ctf_field_structure_get_field_by_name(
356 stream->packet_context, "packet_size");
357
013f35c6 358 ret = bt_ctf_field_integer_unsigned_set_value(field, packet_size_bits);
3dca2276
PP
359 if (ret) {
360 BT_LOGW("Cannot set packet context field's `packet_size` integer field's value: "
361 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
362 stream, bt_ctf_stream_get_name(stream),
013f35c6 363 field, packet_size_bits);
3dca2276 364 } else {
ef267d12 365 BT_LOGT("Set packet context field's `packet_size` field's value: "
3dca2276
PP
366 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
367 stream, bt_ctf_stream_get_name(stream),
013f35c6 368 field, packet_size_bits);
3dca2276
PP
369 }
370
e1e02a22 371 bt_ctf_object_put_ref(field);
3dca2276
PP
372 return ret;
373}
374
375static
013f35c6
PP
376int set_packet_context_content_size(struct bt_ctf_stream *stream,
377 uint64_t content_size_bits)
3dca2276
PP
378{
379 int ret = 0;
380 struct bt_ctf_field *field = bt_ctf_field_structure_get_field_by_name(
381 stream->packet_context, "content_size");
382
98b15851 383 BT_ASSERT_DBG(stream);
3dca2276
PP
384
385 if (!field) {
386 /* No content size field found. Not an error, skip. */
ef267d12 387 BT_LOGT("No field named `content_size` in packet context: skipping: "
3dca2276
PP
388 "stream-addr=%p, stream-name=\"%s\"",
389 stream, bt_ctf_stream_get_name(stream));
390 goto end;
391 }
392
013f35c6 393 ret = bt_ctf_field_integer_unsigned_set_value(field, content_size_bits);
3dca2276
PP
394 if (ret) {
395 BT_LOGW("Cannot set packet context field's `content_size` integer field's value: "
013f35c6 396 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
3dca2276 397 stream, bt_ctf_stream_get_name(stream),
013f35c6 398 field, content_size_bits);
3dca2276 399 } else {
ef267d12 400 BT_LOGT("Set packet context field's `content_size` field's value: "
013f35c6 401 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
3dca2276 402 stream, bt_ctf_stream_get_name(stream),
013f35c6 403 field, content_size_bits);
3dca2276
PP
404 }
405
406end:
e1e02a22 407 bt_ctf_object_put_ref(field);
3dca2276
PP
408 return ret;
409}
410
411static
412int set_packet_context_events_discarded(struct bt_ctf_stream *stream)
413{
414 int ret = 0;
415 struct bt_ctf_field *field = bt_ctf_field_structure_get_field_by_name(
416 stream->packet_context, "events_discarded");
417
98b15851 418 BT_ASSERT_DBG(stream);
3dca2276
PP
419
420 if (!field) {
421 /* No discarded events count field found. Not an error, skip. */
ef267d12 422 BT_LOGT("No field named `events_discarded` in packet context: skipping: "
3dca2276
PP
423 "stream-addr=%p, stream-name=\"%s\"",
424 stream, bt_ctf_stream_get_name(stream));
425 goto end;
426 }
427
428 /*
429 * If the field is set by the user, make sure that the value is
430 * greater than or equal to the stream's current count of
431 * discarded events. We do not allow wrapping here. If it's
432 * valid, update the stream's current count.
433 */
434 if (bt_ctf_field_is_set_recursive(field)) {
435 uint64_t user_val;
436
437 ret = bt_ctf_field_integer_unsigned_get_value(field,
438 &user_val);
439 if (ret) {
440 BT_LOGW("Cannot get packet context `events_discarded` field's unsigned value: "
441 "stream-addr=%p, stream-name=\"%s\", field-addr=%p",
442 stream, bt_ctf_stream_get_name(stream), field);
443 goto end;
444 }
445
446 if (user_val < stream->discarded_events) {
447 BT_LOGW("Invalid packet context `events_discarded` field's unsigned value: "
448 "value is lesser than the stream's current discarded events count: "
449 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, "
450 "value=%" PRIu64 ", "
451 "stream-discarded-events-count=%" PRIu64,
452 stream, bt_ctf_stream_get_name(stream), field,
453 user_val, stream->discarded_events);
454 goto end;
455 }
456
457 stream->discarded_events = user_val;
458 } else {
459 ret = bt_ctf_field_integer_unsigned_set_value(field,
460 stream->discarded_events);
461 if (ret) {
462 BT_LOGW("Cannot set packet context field's `events_discarded` integer field's value: "
463 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
464 stream, bt_ctf_stream_get_name(stream),
465 field, stream->discarded_events);
466 } else {
ef267d12 467 BT_LOGT("Set packet context field's `events_discarded` field's value: "
3dca2276
PP
468 "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
469 stream, bt_ctf_stream_get_name(stream),
470 field, stream->discarded_events);
471 }
472 }
473
474end:
e1e02a22 475 bt_ctf_object_put_ref(field);
3dca2276
PP
476 return ret;
477}
478
479static
480void update_clock_value(uint64_t *val, uint64_t new_val,
481 unsigned int new_val_size)
482{
483 const uint64_t pow2 = 1ULL << new_val_size;
484 const uint64_t mask = pow2 - 1;
485 uint64_t val_masked;
486
ef267d12 487#ifdef BT_LOG_ENABLED_TRACE
3dca2276
PP
488 uint64_t old_val = *val;
489#endif
490
491 if (new_val_size == 64) {
492 *val = new_val;
493 goto end;
494 }
495
496 val_masked = *val & mask;
497
498 if (new_val < val_masked) {
499 /* Wrapped once */
500 new_val |= pow2;
501 }
502
503 *val &= ~mask;
504 *val |= new_val;
505
506end:
ef267d12 507 BT_LOGT("Updated clock value: old-val=%" PRIu64 ", new-val=%" PRIu64,
3dca2276
PP
508 old_val, *val);
509 return;
510}
511
512static
513int visit_field_update_clock_value(struct bt_ctf_field *field, uint64_t *val)
514{
515 int ret = 0;
16ca5ff0 516 struct bt_ctf_field_common *field_common = (void *) field;
3dca2276
PP
517
518 if (!field) {
519 goto end;
520 }
521
522 switch (bt_ctf_field_get_type_id(field)) {
523 case BT_CTF_FIELD_TYPE_ID_INTEGER:
524 {
525 struct bt_ctf_clock_class *cc =
526 bt_ctf_field_type_integer_get_mapped_clock_class(
527 (void *) field_common->type);
528 int val_size;
529 uint64_t uval;
530
531 if (!cc) {
532 goto end;
533 }
534
e1e02a22 535 bt_ctf_object_put_ref(cc);
3dca2276
PP
536 val_size = bt_ctf_field_type_integer_get_size(
537 (void *) field_common->type);
98b15851 538 BT_ASSERT_DBG(val_size >= 1);
3dca2276
PP
539
540 if (bt_ctf_field_type_integer_is_signed(
541 (void *) field_common->type)) {
542 int64_t ival;
543
544 ret = bt_ctf_field_integer_signed_get_value(field, &ival);
545 uval = (uint64_t) ival;
546 } else {
547 ret = bt_ctf_field_integer_unsigned_get_value(field, &uval);
548 }
549
550 if (ret) {
551 /* Not set */
552 goto end;
553 }
554
555 update_clock_value(val, uval, val_size);
556 break;
557 }
558 case BT_CTF_FIELD_TYPE_ID_ENUM:
559 {
560 struct bt_ctf_field *int_field =
561 bt_ctf_field_enumeration_get_container(field);
562
98b15851 563 BT_ASSERT_DBG(int_field);
3dca2276 564 ret = visit_field_update_clock_value(int_field, val);
e1e02a22 565 bt_ctf_object_put_ref(int_field);
3dca2276
PP
566 break;
567 }
568 case BT_CTF_FIELD_TYPE_ID_ARRAY:
569 {
570 uint64_t i;
571 int64_t len = bt_ctf_field_type_array_get_length(
572 (void *) field_common->type);
573
98b15851 574 BT_ASSERT_DBG(len >= 0);
3dca2276
PP
575
576 for (i = 0; i < len; i++) {
577 struct bt_ctf_field *elem_field =
578 bt_ctf_field_array_get_field(field, i);
579
98b15851 580 BT_ASSERT_DBG(elem_field);
3dca2276 581 ret = visit_field_update_clock_value(elem_field, val);
e1e02a22 582 bt_ctf_object_put_ref(elem_field);
3dca2276
PP
583 if (ret) {
584 goto end;
585 }
586 }
587 break;
588 }
589 case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
590 {
591 uint64_t i;
16ca5ff0 592 int64_t len = bt_ctf_field_common_sequence_get_length(
3dca2276
PP
593 (void *) field);
594
595 if (len < 0) {
596 ret = -1;
597 goto end;
598 }
599
600 for (i = 0; i < len; i++) {
601 struct bt_ctf_field *elem_field =
602 bt_ctf_field_sequence_get_field(field, i);
603
98b15851 604 BT_ASSERT_DBG(elem_field);
3dca2276 605 ret = visit_field_update_clock_value(elem_field, val);
e1e02a22 606 bt_ctf_object_put_ref(elem_field);
3dca2276
PP
607 if (ret) {
608 goto end;
609 }
610 }
611 break;
612 }
613 case BT_CTF_FIELD_TYPE_ID_STRUCT:
614 {
615 uint64_t i;
616 int64_t len = bt_ctf_field_type_structure_get_field_count(
617 (void *) field_common->type);
618
98b15851 619 BT_ASSERT_DBG(len >= 0);
3dca2276
PP
620
621 for (i = 0; i < len; i++) {
622 struct bt_ctf_field *member_field =
623 bt_ctf_field_structure_get_field_by_index(field, i);
624
98b15851 625 BT_ASSERT_DBG(member_field);
3dca2276 626 ret = visit_field_update_clock_value(member_field, val);
e1e02a22 627 bt_ctf_object_put_ref(member_field);
3dca2276
PP
628 if (ret) {
629 goto end;
630 }
631 }
632 break;
633 }
634 case BT_CTF_FIELD_TYPE_ID_VARIANT:
635 {
636 struct bt_ctf_field *cur_field =
637 bt_ctf_field_variant_get_current_field(field);
638
639 if (!cur_field) {
640 ret = -1;
641 goto end;
642 }
643
644 ret = visit_field_update_clock_value(cur_field, val);
e1e02a22 645 bt_ctf_object_put_ref(cur_field);
3dca2276
PP
646 break;
647 }
648 default:
649 break;
650 }
651
652end:
653 return ret;
654}
655
7c7301d5 656static
3dca2276
PP
657int visit_event_update_clock_value(struct bt_ctf_event *event, uint64_t *val)
658{
659 int ret = 0;
660 struct bt_ctf_field *field;
661
662 field = bt_ctf_event_get_header(event);
663 ret = visit_field_update_clock_value(field, val);
e1e02a22 664 bt_ctf_object_put_ref(field);
3dca2276
PP
665 if (ret) {
666 BT_LOGW_STR("Cannot automatically update clock value in "
667 "event's header.");
668 goto end;
669 }
670
671 field = bt_ctf_event_get_stream_event_context(event);
672 ret = visit_field_update_clock_value(field, val);
e1e02a22 673 bt_ctf_object_put_ref(field);
3dca2276
PP
674 if (ret) {
675 BT_LOGW_STR("Cannot automatically update clock value in "
676 "event's stream event context.");
677 goto end;
678 }
679
680 field = bt_ctf_event_get_context(event);
681 ret = visit_field_update_clock_value(field, val);
e1e02a22 682 bt_ctf_object_put_ref(field);
3dca2276
PP
683 if (ret) {
684 BT_LOGW_STR("Cannot automatically update clock value in "
685 "event's context.");
686 goto end;
687 }
688
689 field = bt_ctf_event_get_payload_field(event);
690 ret = visit_field_update_clock_value(field, val);
e1e02a22 691 bt_ctf_object_put_ref(field);
3dca2276
PP
692 if (ret) {
693 BT_LOGW_STR("Cannot automatically update clock value in "
694 "event's payload.");
695 goto end;
696 }
697
698end:
699 return ret;
700}
701
702static
703int set_packet_context_timestamps(struct bt_ctf_stream *stream)
704{
705 int ret = 0;
706 uint64_t val;
707 uint64_t cur_clock_value;
708 uint64_t init_clock_value = 0;
709 struct bt_ctf_field *ts_begin_field = bt_ctf_field_structure_get_field_by_name(
710 stream->packet_context, "timestamp_begin");
711 struct bt_ctf_field *ts_end_field = bt_ctf_field_structure_get_field_by_name(
712 stream->packet_context, "timestamp_end");
16ca5ff0 713 struct bt_ctf_field_common *packet_context =
3dca2276
PP
714 (void *) stream->packet_context;
715 uint64_t i;
716 int64_t len;
717
718 if (ts_begin_field && bt_ctf_field_is_set_recursive(ts_begin_field)) {
719 /* Use provided `timestamp_begin` value as starting value */
720 ret = bt_ctf_field_integer_unsigned_get_value(ts_begin_field, &val);
98b15851 721 BT_ASSERT_DBG(ret == 0);
3dca2276
PP
722 init_clock_value = val;
723 } else if (stream->last_ts_end != -1ULL) {
724 /* Use last packet's ending timestamp as starting value */
725 init_clock_value = stream->last_ts_end;
726 }
727
728 cur_clock_value = init_clock_value;
729
730 if (stream->last_ts_end != -1ULL &&
731 cur_clock_value < stream->last_ts_end) {
732 BT_LOGW("Packet's initial timestamp is less than previous "
733 "packet's final timestamp: "
734 "stream-addr=%p, stream-name=\"%s\", "
735 "cur-packet-ts-begin=%" PRIu64 ", "
736 "prev-packet-ts-end=%" PRIu64,
737 stream, bt_ctf_stream_get_name(stream),
738 cur_clock_value, stream->last_ts_end);
739 ret = -1;
740 goto end;
741 }
742
743 /*
744 * Visit all the packet context fields, followed by all the
745 * fields of all the events, in order, updating our current
746 * clock value as we visit.
747 *
748 * While visiting the packet context fields, do not consider
749 * `timestamp_begin` and `timestamp_end` because this function's
750 * purpose is to set them anyway. Also do not consider
751 * `packet_size`, `content_size`, `events_discarded`, and
752 * `packet_seq_num` if they are not set because those are
753 * autopopulating fields.
754 */
755 len = bt_ctf_field_type_structure_get_field_count(
756 (void *) packet_context->type);
98b15851 757 BT_ASSERT_DBG(len >= 0);
3dca2276
PP
758
759 for (i = 0; i < len; i++) {
760 const char *member_name;
761 struct bt_ctf_field *member_field;
762
763 ret = bt_ctf_field_type_structure_get_field_by_index(
764 (void *) packet_context->type, &member_name, NULL, i);
98b15851 765 BT_ASSERT_DBG(ret == 0);
3dca2276
PP
766
767 if (strcmp(member_name, "timestamp_begin") == 0 ||
768 strcmp(member_name, "timestamp_end") == 0) {
769 continue;
770 }
771
772 member_field = bt_ctf_field_structure_get_field_by_index(
773 stream->packet_context, i);
98b15851 774 BT_ASSERT_DBG(member_field);
3dca2276
PP
775
776 if (strcmp(member_name, "packet_size") == 0 &&
777 !bt_ctf_field_is_set_recursive(member_field)) {
e1e02a22 778 bt_ctf_object_put_ref(member_field);
3dca2276
PP
779 continue;
780 }
781
782 if (strcmp(member_name, "content_size") == 0 &&
783 !bt_ctf_field_is_set_recursive(member_field)) {
e1e02a22 784 bt_ctf_object_put_ref(member_field);
3dca2276
PP
785 continue;
786 }
787
788 if (strcmp(member_name, "events_discarded") == 0 &&
789 !bt_ctf_field_is_set_recursive(member_field)) {
e1e02a22 790 bt_ctf_object_put_ref(member_field);
3dca2276
PP
791 continue;
792 }
793
794 if (strcmp(member_name, "packet_seq_num") == 0 &&
795 !bt_ctf_field_is_set_recursive(member_field)) {
e1e02a22 796 bt_ctf_object_put_ref(member_field);
3dca2276
PP
797 continue;
798 }
799
800 ret = visit_field_update_clock_value(member_field,
801 &cur_clock_value);
e1e02a22 802 bt_ctf_object_put_ref(member_field);
3dca2276
PP
803 if (ret) {
804 BT_LOGW("Cannot automatically update clock value "
805 "in stream's packet context: "
806 "stream-addr=%p, stream-name=\"%s\", "
807 "field-name=\"%s\"",
808 stream, bt_ctf_stream_get_name(stream),
809 member_name);
810 goto end;
811 }
812 }
813
814 for (i = 0; i < stream->events->len; i++) {
815 struct bt_ctf_event *event = g_ptr_array_index(stream->events, i);
816
98b15851 817 BT_ASSERT_DBG(event);
3dca2276
PP
818 ret = visit_event_update_clock_value(event, &cur_clock_value);
819 if (ret) {
820 BT_LOGW("Cannot automatically update clock value "
821 "in stream's packet context: "
822 "stream-addr=%p, stream-name=\"%s\", "
823 "index=%" PRIu64 ", event-addr=%p, "
824 "event-class-id=%" PRId64 ", "
825 "event-class-name=\"%s\"",
826 stream, bt_ctf_stream_get_name(stream),
827 i, event,
16ca5ff0
PP
828 bt_ctf_event_class_common_get_id(event->common.class),
829 bt_ctf_event_class_common_get_name(event->common.class));
3dca2276
PP
830 goto end;
831 }
832 }
833
834 /*
835 * Everything is visited, thus the current clock value
836 * corresponds to the ending timestamp. Validate this value
837 * against the provided value of `timestamp_end`, if any,
838 * otherwise set it.
839 */
840 if (ts_end_field && bt_ctf_field_is_set_recursive(ts_end_field)) {
841 ret = bt_ctf_field_integer_unsigned_get_value(ts_end_field, &val);
98b15851 842 BT_ASSERT_DBG(ret == 0);
3dca2276
PP
843
844 if (val < cur_clock_value) {
845 BT_LOGW("Packet's final timestamp is less than "
846 "computed packet's final timestamp: "
847 "stream-addr=%p, stream-name=\"%s\", "
848 "cur-packet-ts-end=%" PRIu64 ", "
849 "computed-packet-ts-end=%" PRIu64,
850 stream, bt_ctf_stream_get_name(stream),
851 val, cur_clock_value);
852 ret = -1;
853 goto end;
854 }
855
856 stream->last_ts_end = val;
857 }
858
859 if (ts_end_field && !bt_ctf_field_is_set_recursive(ts_end_field)) {
860 ret = set_integer_field_value(ts_end_field, cur_clock_value);
98b15851 861 BT_ASSERT_DBG(ret == 0);
3dca2276
PP
862 stream->last_ts_end = cur_clock_value;
863 }
864
865 if (!ts_end_field) {
866 stream->last_ts_end = cur_clock_value;
867 }
868
869 /* Set `timestamp_begin` field to initial clock value */
870 if (ts_begin_field && !bt_ctf_field_is_set_recursive(ts_begin_field)) {
871 ret = set_integer_field_value(ts_begin_field, init_clock_value);
98b15851 872 BT_ASSERT_DBG(ret == 0);
3dca2276
PP
873 }
874
875end:
e1e02a22
PP
876 bt_ctf_object_put_ref(ts_begin_field);
877 bt_ctf_object_put_ref(ts_end_field);
3dca2276
PP
878 return ret;
879}
880
881static
013f35c6
PP
882int auto_populate_packet_context(struct bt_ctf_stream *stream, bool set_ts,
883 uint64_t packet_size_bits, uint64_t content_size_bits)
3dca2276
PP
884{
885 int ret = 0;
886
887 if (!stream->packet_context) {
888 goto end;
889 }
890
013f35c6 891 ret = set_packet_context_packet_size(stream, packet_size_bits);
3dca2276
PP
892 if (ret) {
893 BT_LOGW("Cannot set packet context's packet size field: "
894 "stream-addr=%p, stream-name=\"%s\"",
895 stream, bt_ctf_stream_get_name(stream));
896 goto end;
897 }
898
013f35c6 899 ret = set_packet_context_content_size(stream, content_size_bits);
3dca2276
PP
900 if (ret) {
901 BT_LOGW("Cannot set packet context's content size field: "
902 "stream-addr=%p, stream-name=\"%s\"",
903 stream, bt_ctf_stream_get_name(stream));
904 goto end;
905 }
906
907 if (set_ts) {
908 ret = set_packet_context_timestamps(stream);
909 if (ret) {
910 BT_LOGW("Cannot set packet context's timestamp fields: "
911 "stream-addr=%p, stream-name=\"%s\"",
912 stream, bt_ctf_stream_get_name(stream));
913 goto end;
914 }
915 }
916
917 ret = set_packet_context_events_discarded(stream);
918 if (ret) {
919 BT_LOGW("Cannot set packet context's discarded events count field: "
920 "stream-addr=%p, stream-name=\"%s\"",
921 stream, bt_ctf_stream_get_name(stream));
922 goto end;
923 }
924
ef267d12 925 BT_LOGT("Automatically populated stream's packet context's known fields: "
3dca2276
PP
926 "stream-addr=%p, stream-name=\"%s\"",
927 stream, bt_ctf_stream_get_name(stream));
928
929end:
930 return ret;
931}
932
933static
934void release_event(struct bt_ctf_event *event)
935{
e1e02a22 936 if (bt_ctf_object_get_ref_count(&event->common.base)) {
3dca2276
PP
937 /*
938 * The event is being orphaned, but it must guarantee the
939 * existence of its event class for the duration of its
940 * lifetime.
941 */
e1e02a22
PP
942 bt_ctf_object_get_ref(event->common.class);
943 BT_CTF_OBJECT_PUT_REF_AND_RESET(event->common.base.parent);
3dca2276 944 } else {
e1e02a22 945 bt_ctf_object_try_spec_release(&event->common.base);
3dca2276
PP
946 }
947}
948
949static
950int create_stream_file(struct bt_ctf_writer *writer,
951 struct bt_ctf_stream *stream)
952{
013f35c6 953 int ret = 0;
3dca2276
PP
954 GString *filename = g_string_new(NULL);
955 int64_t stream_class_id;
956 char *file_path = NULL;
957
958 BT_LOGD("Creating stream file: writer-addr=%p, stream-addr=%p, "
959 "stream-name=\"%s\", stream-class-addr=%p, stream-class-name=\"%s\"",
960 writer, stream, bt_ctf_stream_get_name(stream),
961 stream->common.stream_class,
962 stream->common.stream_class->name->str);
963
964 if (stream->common.name && stream->common.name->len > 0) {
965 /* Use stream name's base name as prefix */
966 gchar *basename = g_path_get_basename(stream->common.name->str);
967
98b15851 968 BT_ASSERT_DBG(basename);
3dca2276
PP
969
970 if (strcmp(basename, G_DIR_SEPARATOR_S) == 0) {
971 g_string_assign(filename, "stream");
972 } else {
973 g_string_assign(filename, basename);
974 }
975
976 g_free(basename);
977 goto append_ids;
978 }
979
980 if (stream->common.stream_class->name &&
981 stream->common.stream_class->name->len > 0) {
982 /* Use stream class name's base name as prefix */
983 gchar *basename =
984 g_path_get_basename(
985 stream->common.stream_class->name->str);
986
98b15851 987 BT_ASSERT_DBG(basename);
3dca2276
PP
988
989 if (strcmp(basename, G_DIR_SEPARATOR_S) == 0) {
990 g_string_assign(filename, "stream");
991 } else {
992 g_string_assign(filename, basename);
993 }
994
995 g_free(basename);
996 goto append_ids;
997 }
998
999 /* Default to using `stream-` as prefix */
1000 g_string_assign(filename, "stream");
1001
1002append_ids:
16ca5ff0 1003 stream_class_id = bt_ctf_stream_class_common_get_id(stream->common.stream_class);
98b15851
PP
1004 BT_ASSERT_DBG(stream_class_id >= 0);
1005 BT_ASSERT_DBG(stream->common.id >= 0);
3dca2276
PP
1006 g_string_append_printf(filename, "-%" PRId64 "-%" PRId64,
1007 stream_class_id, stream->common.id);
1008
1009 file_path = g_build_filename(writer->path->str, filename->str, NULL);
5084732e 1010 if (!file_path) {
013f35c6 1011 ret = -1;
3dca2276
PP
1012 goto end;
1013 }
1014
86d8b7b8
PP
1015 ret = bt_ctfser_init(&stream->ctfser, file_path,
1016 BT_LOG_OUTPUT_LEVEL);
3dca2276 1017 g_free(file_path);
013f35c6
PP
1018 if (ret) {
1019 /* bt_ctfser_init() logs errors */
3dca2276
PP
1020 goto end;
1021 }
1022
1023 BT_LOGD("Created stream file for writing: "
1024 "stream-addr=%p, stream-name=\"%s\", "
013f35c6
PP
1025 "filename=\"%s\"", stream, bt_ctf_stream_get_name(stream),
1026 filename->str);
3dca2276
PP
1027
1028end:
1029 g_string_free(filename, TRUE);
013f35c6 1030 return ret;
3dca2276
PP
1031}
1032
1033BT_HIDDEN
1034struct bt_ctf_stream *bt_ctf_stream_create_with_id(
1035 struct bt_ctf_stream_class *stream_class,
1036 const char *name, uint64_t id)
1037{
1038 int ret;
1039 int fd;
1040 struct bt_ctf_stream *stream = NULL;
1041 struct bt_ctf_trace *trace = NULL;
1042 struct bt_ctf_writer *writer = NULL;
1043
1044 BT_LOGD("Creating CTF writer stream object: stream-class-addr=%p, "
1045 "stream-class-name=\"%s\", stream-name=\"%s\", "
1046 "stream-id=%" PRIu64,
1047 stream_class, bt_ctf_stream_class_get_name(stream_class),
1048 name, id);
1049 stream = g_new0(struct bt_ctf_stream, 1);
1050 if (!stream) {
1051 BT_LOGE_STR("Failed to allocate one stream.");
1052 goto error;
1053 }
1054
1055 if (id == -1ULL) {
1056 id = stream_class->next_stream_id;
1057 }
1058
16ca5ff0
PP
1059 ret = bt_ctf_stream_common_initialize(BT_CTF_TO_COMMON(stream),
1060 BT_CTF_TO_COMMON(stream_class), name, id, bt_ctf_stream_destroy);
3dca2276 1061 if (ret) {
16ca5ff0 1062 /* bt_ctf_stream_common_initialize() logs errors */
3dca2276
PP
1063 goto error;
1064 }
1065
16ca5ff0
PP
1066 trace = BT_CTF_FROM_COMMON(bt_ctf_stream_class_common_borrow_trace(
1067 BT_CTF_TO_COMMON(stream_class)));
3dca2276
PP
1068 if (!trace) {
1069 BT_LOGW("Invalid parameter: cannot create stream from a stream class which is not part of trace: "
1070 "stream-class-addr=%p, stream-class-name=\"%s\", "
1071 "stream-name=\"%s\"",
1072 stream_class, bt_ctf_stream_class_get_name(stream_class),
1073 name);
1074 goto error;
1075 }
1076
3fea54f6 1077 writer = (struct bt_ctf_writer *)
e1e02a22 1078 bt_ctf_object_get_parent(&trace->common.base);
3dca2276
PP
1079 stream->last_ts_end = -1ULL;
1080 BT_LOGD("CTF writer stream object belongs writer's trace: "
1081 "writer-addr=%p", writer);
98b15851 1082 BT_ASSERT_DBG(writer);
3dca2276
PP
1083
1084 if (stream_class->common.packet_context_field_type) {
1085 BT_LOGD("Creating stream's packet context field: "
1086 "ft-addr=%p",
1087 stream_class->common.packet_context_field_type);
1088 stream->packet_context = bt_ctf_field_create(
1089 (void *) stream_class->common.packet_context_field_type);
1090 if (!stream->packet_context) {
1091 BT_LOGW_STR("Cannot create stream's packet context field.");
1092 goto error;
1093 }
1094
1095 /* Initialize events_discarded */
1096 ret = try_set_structure_field_integer(
1097 stream->packet_context, "events_discarded", 0);
1098 if (ret < 0) {
1099 BT_LOGW("Cannot set `events_discarded` field in packet context: "
1100 "ret=%d, packet-context-field-addr=%p",
1101 ret, stream->packet_context);
1102 goto error;
1103 }
1104 }
1105
1106 stream->events = g_ptr_array_new_with_free_func(
1107 (GDestroyNotify) release_event);
1108 if (!stream->events) {
1109 BT_LOGE_STR("Failed to allocate a GPtrArray.");
1110 goto error;
1111 }
1112
1113 if (trace->common.packet_header_field_type) {
1114 BT_LOGD("Creating stream's packet header field: "
1115 "ft-addr=%p", trace->common.packet_header_field_type);
1116 stream->packet_header =
1117 bt_ctf_field_create(
1118 (void *) trace->common.packet_header_field_type);
1119 if (!stream->packet_header) {
1120 BT_LOGW_STR("Cannot create stream's packet header field.");
1121 goto error;
1122 }
1123 }
1124
1125 /*
1126 * Attempt to populate the default trace packet header fields
1127 * (magic, uuid and stream_id). This will _not_ fail shall the
1128 * fields not be found or be of an incompatible type; they will
1129 * simply not be populated automatically. The user will have to
1130 * make sure to set the trace packet header fields himself
1131 * before flushing.
1132 */
1133 ret = auto_populate_packet_header(stream);
1134 if (ret) {
1135 BT_LOGW_STR("Cannot automatically populate the stream's packet header.");
1136 goto error;
1137 }
1138
1139 /* Create file associated with this stream */
1140 fd = create_stream_file(writer, stream);
1141 if (fd < 0) {
1142 BT_LOGW_STR("Cannot create stream file.");
1143 goto error;
1144 }
1145
3dca2276
PP
1146 /* Freeze the writer */
1147 BT_LOGD_STR("Freezing stream's CTF writer.");
1148 bt_ctf_writer_freeze(writer);
1149
1150 /* Add this stream to the trace's streams */
1151 g_ptr_array_add(trace->common.streams, stream);
1152 stream_class->next_stream_id++;
1153 BT_LOGD("Created stream object: addr=%p", stream);
1154 goto end;
1155
1156error:
e1e02a22 1157 BT_CTF_OBJECT_PUT_REF_AND_RESET(stream);
3dca2276
PP
1158
1159end:
e1e02a22 1160 bt_ctf_object_put_ref(writer);
3dca2276
PP
1161 return stream;
1162}
1163
1164struct bt_ctf_stream *bt_ctf_stream_create(
1165 struct bt_ctf_stream_class *stream_class,
1166 const char *name, uint64_t id_param)
1167{
1168 return bt_ctf_stream_create_with_id(stream_class,
1169 name, id_param);
1170}
1171
1172int bt_ctf_stream_get_discarded_events_count(
1173 struct bt_ctf_stream *stream, uint64_t *count)
1174{
1175 int ret = 0;
1176
1177 if (!stream) {
1178 BT_LOGW_STR("Invalid parameter: stream is NULL.");
1179 ret = -1;
1180 goto end;
1181 }
1182
1183 if (!count) {
1184 BT_LOGW_STR("Invalid parameter: count is NULL.");
1185 ret = -1;
1186 goto end;
1187 }
1188
3dca2276
PP
1189 *count = (uint64_t) stream->discarded_events;
1190
1191end:
1192 return ret;
1193}
1194
1195static
1196int set_packet_context_events_discarded_field(struct bt_ctf_stream *stream,
1197 uint64_t count)
1198{
1199 int ret = 0;
1200 struct bt_ctf_field *events_discarded_field = NULL;
1201
1202 if (!stream->packet_context) {
1203 goto end;
1204 }
1205
1206 events_discarded_field = bt_ctf_field_structure_get_field_by_name(
1207 stream->packet_context, "events_discarded");
1208 if (!events_discarded_field) {
1209 goto end;
1210 }
1211
1212 ret = bt_ctf_field_integer_unsigned_set_value(
1213 events_discarded_field, count);
1214 if (ret) {
1215 BT_LOGW("Cannot set packet context's `events_discarded` field: "
1216 "field-addr=%p, value=%" PRIu64,
1217 events_discarded_field, count);
1218 goto end;
1219 }
1220
1221end:
e1e02a22 1222 bt_ctf_object_put_ref(events_discarded_field);
3dca2276
PP
1223 return ret;
1224}
1225
1226void bt_ctf_stream_append_discarded_events(struct bt_ctf_stream *stream,
1227 uint64_t event_count)
1228{
1229 int ret;
1230 uint64_t new_count;
1231 struct bt_ctf_field *events_discarded_field = NULL;
1232
1233 if (!stream) {
1234 BT_LOGW_STR("Invalid parameter: stream is NULL.");
1235 goto end;
1236 }
1237
ef267d12 1238 BT_LOGT("Appending discarded events to stream: "
3dca2276
PP
1239 "stream-addr=%p, stream-name=\"%s\", append-count=%" PRIu64,
1240 stream, bt_ctf_stream_get_name(stream), event_count);
1241
1242 if (!stream->packet_context) {
1243 BT_LOGW_STR("Invalid parameter: stream has no packet context field.");
1244 goto end;
1245 }
1246
3dca2276
PP
1247 events_discarded_field = bt_ctf_field_structure_get_field_by_name(
1248 stream->packet_context, "events_discarded");
1249 if (!events_discarded_field) {
1250 BT_LOGW_STR("No field named `events_discarded` in stream's packet context.");
1251 goto end;
1252 }
1253
1254 new_count = stream->discarded_events + event_count;
1255 if (new_count < stream->discarded_events) {
1256 BT_LOGW("New discarded events count is less than the stream's current discarded events count: "
1257 "cur-count=%" PRIu64 ", new-count=%" PRIu64,
1258 stream->discarded_events, new_count);
1259 goto end;
1260 }
1261
1262 ret = set_packet_context_events_discarded_field(stream, new_count);
1263 if (ret) {
1264 /* set_packet_context_events_discarded_field() logs errors */
1265 goto end;
1266 }
1267
1268 stream->discarded_events = new_count;
ef267d12 1269 BT_LOGT("Appended discarded events to stream: "
3dca2276
PP
1270 "stream-addr=%p, stream-name=\"%s\", append-count=%" PRIu64,
1271 stream, bt_ctf_stream_get_name(stream), event_count);
1272
1273end:
e1e02a22 1274 bt_ctf_object_put_ref(events_discarded_field);
3dca2276
PP
1275}
1276
1277static int auto_populate_event_header(struct bt_ctf_stream *stream,
1278 struct bt_ctf_event *event)
1279{
1280 int ret = 0;
1281 struct bt_ctf_field *id_field = NULL, *timestamp_field = NULL;
1282 struct bt_ctf_clock_class *mapped_clock_class = NULL;
1283 struct bt_ctf_stream_class *stream_class =
16ca5ff0
PP
1284 BT_CTF_FROM_COMMON(bt_ctf_stream_common_borrow_class(
1285 BT_CTF_TO_COMMON(stream)));
3dca2276
PP
1286 int64_t event_class_id;
1287
98b15851 1288 BT_ASSERT_DBG(event);
3dca2276
PP
1289
1290 if (!event->common.header_field) {
1291 goto end;
1292 }
1293
1294 if (event->common.frozen) {
1295 BT_LOGW_STR("Cannot populate event header field: event is frozen.");
1296 ret = -1;
1297 goto end;
1298 }
1299
ef267d12 1300 BT_LOGT("Automatically populating event's header field: "
3dca2276
PP
1301 "stream-addr=%p, stream-name=\"%s\", event-addr=%p",
1302 stream, bt_ctf_stream_get_name(stream), event);
1303
1304 id_field = bt_ctf_field_structure_get_field_by_name(
312c056a 1305 (void *) event->common.header_field->field, "id");
16ca5ff0 1306 event_class_id = bt_ctf_event_class_common_get_id(event->common.class);
98b15851 1307 BT_ASSERT_DBG(event_class_id >= 0);
3dca2276
PP
1308
1309 if (id_field && bt_ctf_field_get_type_id(id_field) == BT_CTF_FIELD_TYPE_ID_INTEGER) {
1310 ret = set_integer_field_value(id_field, event_class_id);
1311 if (ret) {
1312 BT_LOGW("Cannot set event header's `id` field's value: "
1313 "addr=%p, value=%" PRIu64, id_field,
1314 event_class_id);
1315 goto end;
1316 }
1317 }
1318
1319 /*
1320 * The conditions to automatically set the timestamp are:
1321 *
1322 * 1. The event header field "timestamp" exists and is an
1323 * integer field.
1324 * 2. This stream's class has a registered clock (set with
1325 * bt_ctf_stream_class_set_clock()).
1326 * 3. The "timestamp" field is not set.
1327 */
1328 timestamp_field = bt_ctf_field_structure_get_field_by_name(
312c056a 1329 (void *) event->common.header_field->field, "timestamp");
3dca2276
PP
1330 if (timestamp_field && stream_class->clock &&
1331 bt_ctf_field_get_type_id(id_field) == BT_CTF_FIELD_TYPE_ID_INTEGER &&
1332 !bt_ctf_field_is_set_recursive(timestamp_field)) {
1333 mapped_clock_class =
1334 bt_ctf_field_type_integer_get_mapped_clock_class(
16ca5ff0 1335 (void *) ((struct bt_ctf_field_common *) timestamp_field)->type);
3dca2276
PP
1336 if (mapped_clock_class) {
1337 uint64_t timestamp;
1338
98b15851 1339 BT_ASSERT_DBG(mapped_clock_class ==
3dca2276
PP
1340 stream_class->clock->clock_class);
1341 ret = bt_ctf_clock_get_value(
1342 stream_class->clock,
1343 &timestamp);
98b15851 1344 BT_ASSERT_DBG(ret == 0);
3dca2276
PP
1345 ret = set_integer_field_value(timestamp_field,
1346 timestamp);
1347 if (ret) {
1348 BT_LOGW("Cannot set event header's `timestamp` field's value: "
1349 "addr=%p, value=%" PRIu64,
1350 timestamp_field, timestamp);
1351 goto end;
1352 }
1353 }
1354 }
1355
ef267d12 1356 BT_LOGT("Automatically populated event's header field: "
3dca2276
PP
1357 "stream-addr=%p, stream-name=\"%s\", event-addr=%p",
1358 stream, bt_ctf_stream_get_name(stream), event);
1359
1360end:
e1e02a22
PP
1361 bt_ctf_object_put_ref(id_field);
1362 bt_ctf_object_put_ref(timestamp_field);
1363 bt_ctf_object_put_ref(mapped_clock_class);
3dca2276
PP
1364 return ret;
1365}
1366
1367int bt_ctf_stream_append_event(struct bt_ctf_stream *stream,
1368 struct bt_ctf_event *event)
1369{
1370 int ret = 0;
1371
1372 if (!stream) {
1373 BT_LOGW_STR("Invalid parameter: stream is NULL.");
1374 ret = -1;
1375 goto end;
1376 }
1377
1378 if (!event) {
1379 BT_LOGW_STR("Invalid parameter: event is NULL.");
1380 ret = -1;
1381 goto end;
1382 }
1383
ef267d12 1384 BT_LOGT("Appending event to stream: "
3dca2276
PP
1385 "stream-addr=%p, stream-name=\"%s\", event-addr=%p, "
1386 "event-class-name=\"%s\", event-class-id=%" PRId64,
1387 stream, bt_ctf_stream_get_name(stream), event,
16ca5ff0
PP
1388 bt_ctf_event_class_common_get_name(
1389 bt_ctf_event_common_borrow_class(BT_CTF_TO_COMMON(event))),
1390 bt_ctf_event_class_common_get_id(
1391 bt_ctf_event_common_borrow_class(BT_CTF_TO_COMMON(event))));
3dca2276
PP
1392
1393 /*
1394 * The event is not supposed to have a parent stream at this
1395 * point. The only other way an event can have a parent stream
1396 * is if it was assigned when setting a packet to the event,
1397 * in which case the packet's stream is not a writer stream,
1398 * and thus the user is trying to append an event which belongs
1399 * to another stream.
1400 */
1401 if (event->common.base.parent) {
1402 ret = -1;
1403 goto end;
1404 }
1405
e1e02a22 1406 bt_ctf_object_set_parent(&event->common.base, &stream->common.base);
ef267d12 1407 BT_LOGT_STR("Automatically populating the header of the event to append.");
3dca2276
PP
1408 ret = auto_populate_event_header(stream, event);
1409 if (ret) {
1410 /* auto_populate_event_header() reports errors */
1411 goto error;
1412 }
1413
1414 /* Make sure the various scopes of the event are set */
ef267d12 1415 BT_LOGT_STR("Validating event to append.");
67d2ce02 1416 BT_CTF_ASSERT_PRE(bt_ctf_event_common_validate(BT_CTF_TO_COMMON(event)) == 0,
16ca5ff0 1417 "Invalid event: event-addr=%p", event);
3dca2276
PP
1418
1419 /* Save the new event and freeze it */
ef267d12 1420 BT_LOGT_STR("Freezing the event to append.");
16ca5ff0 1421 bt_ctf_event_common_set_is_frozen(BT_CTF_TO_COMMON(event), true);
3dca2276
PP
1422 g_ptr_array_add(stream->events, event);
1423
1424 /*
1425 * Event had to hold a reference to its event class as long as it wasn't
1426 * part of the same trace hierarchy. From now on, the event and its
1427 * class share the same lifetime guarantees and the reference is no
1428 * longer needed.
1429 */
ef267d12 1430 BT_LOGT_STR("Putting the event's class.");
e1e02a22 1431 bt_ctf_object_put_ref(event->common.class);
ef267d12 1432 BT_LOGT("Appended event to stream: "
3dca2276
PP
1433 "stream-addr=%p, stream-name=\"%s\", event-addr=%p, "
1434 "event-class-name=\"%s\", event-class-id=%" PRId64,
1435 stream, bt_ctf_stream_get_name(stream), event,
16ca5ff0
PP
1436 bt_ctf_event_class_common_get_name(
1437 bt_ctf_event_common_borrow_class(BT_CTF_TO_COMMON(event))),
1438 bt_ctf_event_class_common_get_id(
1439 bt_ctf_event_common_borrow_class(BT_CTF_TO_COMMON(event))));
3dca2276
PP
1440
1441end:
1442 return ret;
1443
1444error:
1445 /*
1446 * Orphan the event; we were not successful in associating it to
1447 * a stream.
1448 */
e1e02a22 1449 bt_ctf_object_set_parent(&event->common.base, NULL);
3dca2276
PP
1450 return ret;
1451}
1452
1453struct bt_ctf_field *bt_ctf_stream_get_packet_context(struct bt_ctf_stream *stream)
1454{
1455 struct bt_ctf_field *packet_context = NULL;
1456
1457 if (!stream) {
1458 BT_LOGW_STR("Invalid parameter: stream is NULL.");
1459 goto end;
1460 }
1461
3dca2276
PP
1462 packet_context = stream->packet_context;
1463 if (packet_context) {
e1e02a22 1464 bt_ctf_object_get_ref(packet_context);
3dca2276
PP
1465 }
1466end:
1467 return packet_context;
1468}
1469
1470int bt_ctf_stream_set_packet_context(struct bt_ctf_stream *stream,
1471 struct bt_ctf_field *field)
1472{
1473 int ret = 0;
1474 struct bt_ctf_field_type *field_type;
1475
1476 if (!stream) {
1477 BT_LOGW_STR("Invalid parameter: stream is NULL.");
1478 ret = -1;
1479 goto end;
1480 }
1481
3dca2276 1482 field_type = bt_ctf_field_get_type(field);
16ca5ff0 1483 if (bt_ctf_field_type_common_compare((void *) field_type,
3dca2276
PP
1484 stream->common.stream_class->packet_context_field_type)) {
1485 BT_LOGW("Invalid parameter: packet context's field type is different from the stream's packet context field type: "
1486 "stream-addr=%p, stream-name=\"%s\", "
1487 "packet-context-field-addr=%p, "
1488 "packet-context-ft-addr=%p",
1489 stream, bt_ctf_stream_get_name(stream),
1490 field, field_type);
1491 ret = -1;
1492 goto end;
1493 }
1494
e1e02a22
PP
1495 bt_ctf_object_put_ref(field_type);
1496 bt_ctf_object_put_ref(stream->packet_context);
1497 stream->packet_context = bt_ctf_object_get_ref(field);
ef267d12 1498 BT_LOGT("Set stream's packet context field: "
3dca2276
PP
1499 "stream-addr=%p, stream-name=\"%s\", "
1500 "packet-context-field-addr=%p",
1501 stream, bt_ctf_stream_get_name(stream), field);
1502end:
1503 return ret;
1504}
1505
1506struct bt_ctf_field *bt_ctf_stream_get_packet_header(struct bt_ctf_stream *stream)
1507{
1508 struct bt_ctf_field *packet_header = NULL;
1509
1510 if (!stream) {
1511 BT_LOGW_STR("Invalid parameter: stream is NULL.");
1512 goto end;
1513 }
1514
3dca2276
PP
1515 packet_header = stream->packet_header;
1516 if (packet_header) {
e1e02a22 1517 bt_ctf_object_get_ref(packet_header);
3dca2276
PP
1518 }
1519end:
1520 return packet_header;
1521}
1522
1523int bt_ctf_stream_set_packet_header(struct bt_ctf_stream *stream,
1524 struct bt_ctf_field *field)
1525{
1526 int ret = 0;
1527 struct bt_ctf_trace *trace = NULL;
1528 struct bt_ctf_field_type *field_type = NULL;
1529
1530 if (!stream) {
1531 BT_LOGW_STR("Invalid parameter: stream is NULL.");
1532 ret = -1;
1533 goto end;
1534 }
1535
3fea54f6 1536 trace = (struct bt_ctf_trace *)
e1e02a22 1537 bt_ctf_object_get_parent(&stream->common.base);
3dca2276
PP
1538
1539 if (!field) {
1540 if (trace->common.packet_header_field_type) {
1541 BT_LOGW("Invalid parameter: setting no packet header but packet header field type is not NULL: "
1542 "stream-addr=%p, stream-name=\"%s\", "
1543 "packet-header-field-addr=%p, "
1544 "expected-ft-addr=%p",
1545 stream, bt_ctf_stream_get_name(stream),
1546 field, trace->common.packet_header_field_type);
1547 ret = -1;
1548 goto end;
1549 }
1550
1551 goto skip_validation;
1552 }
1553
1554 field_type = bt_ctf_field_get_type(field);
98b15851 1555 BT_ASSERT_DBG(field_type);
3dca2276 1556
16ca5ff0 1557 if (bt_ctf_field_type_common_compare((void *) field_type,
3dca2276
PP
1558 trace->common.packet_header_field_type)) {
1559 BT_LOGW("Invalid parameter: packet header's field type is different from the stream's packet header field type: "
1560 "stream-addr=%p, stream-name=\"%s\", "
1561 "packet-header-field-addr=%p, "
1562 "packet-header-ft-addr=%p",
1563 stream, bt_ctf_stream_get_name(stream),
1564 field, field_type);
1565 ret = -1;
1566 goto end;
1567 }
1568
1569skip_validation:
e1e02a22
PP
1570 bt_ctf_object_put_ref(stream->packet_header);
1571 stream->packet_header = bt_ctf_object_get_ref(field);
ef267d12 1572 BT_LOGT("Set stream's packet header field: "
3dca2276
PP
1573 "stream-addr=%p, stream-name=\"%s\", "
1574 "packet-header-field-addr=%p",
1575 stream, bt_ctf_stream_get_name(stream), field);
1576end:
e1e02a22
PP
1577 BT_CTF_OBJECT_PUT_REF_AND_RESET(trace);
1578 bt_ctf_object_put_ref(field_type);
3dca2276
PP
1579 return ret;
1580}
1581
1582static
1583void reset_structure_field(struct bt_ctf_field *structure, const char *name)
1584{
1585 struct bt_ctf_field *member;
1586
1587 member = bt_ctf_field_structure_get_field_by_name(structure, name);
1588 if (member) {
16ca5ff0 1589 bt_ctf_field_common_reset_recursive((void *) member);
e1e02a22 1590 bt_ctf_object_put_ref(member);
3dca2276
PP
1591 }
1592}
1593
1594int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
1595{
1596 int ret = 0;
1597 size_t i;
9f034c64 1598 uint64_t packet_context_offset_bits = 0;
3dca2276
PP
1599 struct bt_ctf_trace *trace;
1600 enum bt_ctf_byte_order native_byte_order;
1601 bool has_packet_size = false;
013f35c6
PP
1602 uint64_t packet_size_bits = 0;
1603 uint64_t content_size_bits = 0;
3dca2276
PP
1604
1605 if (!stream) {
1606 BT_LOGW_STR("Invalid parameter: stream is NULL.");
1607 ret = -1;
1608 goto end_no_stream;
1609 }
1610
3dca2276
PP
1611 if (stream->packet_context) {
1612 struct bt_ctf_field *packet_size_field;
1613
1614 packet_size_field = bt_ctf_field_structure_get_field_by_name(
1615 stream->packet_context, "packet_size");
5084732e 1616 has_packet_size = packet_size_field;
e1e02a22 1617 bt_ctf_object_put_ref(packet_size_field);
3dca2276
PP
1618 }
1619
1620 if (stream->flushed_packet_count == 1) {
1621 if (!stream->packet_context) {
1622 BT_LOGW_STR("Cannot flush a stream which has no packet context field more than once.");
1623 ret = -1;
1624 goto end;
1625 }
1626
1627 if (!has_packet_size) {
1628 BT_LOGW_STR("Cannot flush a stream which has no packet context's `packet_size` field more than once.");
1629 ret = -1;
1630 goto end;
1631 }
1632 }
1633
ef267d12 1634 BT_LOGT("Flushing stream's current packet: stream-addr=%p, "
3dca2276
PP
1635 "stream-name=\"%s\", packet-index=%u", stream,
1636 bt_ctf_stream_get_name(stream), stream->flushed_packet_count);
16ca5ff0 1637 trace = BT_CTF_FROM_COMMON(bt_ctf_stream_class_common_borrow_trace(
3dca2276 1638 stream->common.stream_class));
98b15851 1639 BT_ASSERT_DBG(trace);
3dca2276
PP
1640 native_byte_order = bt_ctf_trace_get_native_byte_order(trace);
1641
1642 ret = auto_populate_packet_header(stream);
1643 if (ret) {
1644 BT_LOGW_STR("Cannot automatically populate the stream's packet header field.");
1645 ret = -1;
1646 goto end;
1647 }
1648
013f35c6
PP
1649 /* Initialize packet/content sizes to `0`; we will overwrite later */
1650 ret = auto_populate_packet_context(stream, true, 0, 0);
3dca2276
PP
1651 if (ret) {
1652 BT_LOGW_STR("Cannot automatically populate the stream's packet context field.");
1653 ret = -1;
1654 goto end;
1655 }
1656
013f35c6
PP
1657 ret = bt_ctfser_open_packet(&stream->ctfser);
1658 if (ret) {
1659 /* bt_ctfser_open_packet() logs errors */
1660 ret = -1;
1661 goto end;
1662 }
3dca2276
PP
1663
1664 if (stream->packet_header) {
ef267d12 1665 BT_LOGT_STR("Serializing packet header field (initial).");
3dca2276 1666 ret = bt_ctf_field_serialize_recursive(stream->packet_header,
013f35c6 1667 &stream->ctfser, native_byte_order);
3dca2276
PP
1668 if (ret) {
1669 BT_LOGW("Cannot serialize stream's packet header field: "
1670 "field-addr=%p", stream->packet_header);
1671 goto end;
1672 }
1673 }
1674
1675 if (stream->packet_context) {
013f35c6
PP
1676 /* Save packet context's position to overwrite it later */
1677 packet_context_offset_bits =
1678 bt_ctfser_get_offset_in_current_packet_bits(
1679 &stream->ctfser);
1680
3dca2276 1681 /* Write packet context */
ef267d12 1682 BT_LOGT_STR("Serializing packet context field (initial).");
3dca2276 1683 ret = bt_ctf_field_serialize_recursive(stream->packet_context,
013f35c6 1684 &stream->ctfser, native_byte_order);
3dca2276
PP
1685 if (ret) {
1686 BT_LOGW("Cannot serialize stream's packet context field: "
1687 "field-addr=%p", stream->packet_context);
1688 goto end;
1689 }
1690 }
1691
ef267d12 1692 BT_LOGT("Serializing events: count=%u", stream->events->len);
3dca2276
PP
1693
1694 for (i = 0; i < stream->events->len; i++) {
1695 struct bt_ctf_event *event = g_ptr_array_index(
1696 stream->events, i);
1697 struct bt_ctf_event_class *event_class =
16ca5ff0
PP
1698 BT_CTF_FROM_COMMON(bt_ctf_event_common_borrow_class(
1699 BT_CTF_TO_COMMON(event)));
3dca2276 1700
ef267d12 1701 BT_LOGT("Serializing event: index=%zu, event-addr=%p, "
3dca2276 1702 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
013f35c6 1703 "ser-offset=%" PRIu64,
3dca2276
PP
1704 i, event, bt_ctf_event_class_get_name(event_class),
1705 bt_ctf_event_class_get_id(event_class),
013f35c6
PP
1706 bt_ctfser_get_offset_in_current_packet_bits(
1707 &stream->ctfser));
3dca2276
PP
1708
1709 /* Write event header */
1710 if (event->common.header_field) {
ef267d12 1711 BT_LOGT_STR("Serializing event's header field.");
3dca2276 1712 ret = bt_ctf_field_serialize_recursive(
312c056a 1713 (void *) event->common.header_field->field,
013f35c6 1714 &stream->ctfser, native_byte_order);
3dca2276
PP
1715 if (ret) {
1716 BT_LOGW("Cannot serialize event's header field: "
1717 "field-addr=%p",
312c056a 1718 event->common.header_field->field);
3dca2276
PP
1719 goto end;
1720 }
1721 }
1722
1723 /* Write stream event context */
1724 if (event->common.stream_event_context_field) {
ef267d12 1725 BT_LOGT_STR("Serializing event's stream event context field.");
3dca2276
PP
1726 ret = bt_ctf_field_serialize_recursive(
1727 (void *) event->common.stream_event_context_field,
013f35c6 1728 &stream->ctfser, native_byte_order);
3dca2276
PP
1729 if (ret) {
1730 BT_LOGW("Cannot serialize event's stream event context field: "
1731 "field-addr=%p",
1732 event->common.stream_event_context_field);
1733 goto end;
1734 }
1735 }
1736
1737 /* Write event content */
013f35c6
PP
1738 ret = bt_ctf_event_serialize(event, &stream->ctfser,
1739 native_byte_order);
3dca2276
PP
1740 if (ret) {
1741 /* bt_ctf_event_serialize() logs errors */
1742 goto end;
1743 }
1744 }
1745
013f35c6
PP
1746 content_size_bits = bt_ctfser_get_offset_in_current_packet_bits(
1747 &stream->ctfser);
1748
1749 if (!has_packet_size && content_size_bits % 8 != 0) {
3dca2276
PP
1750 BT_LOGW("Stream's packet context field type has no `packet_size` field, "
1751 "but current content size is not a multiple of 8 bits: "
013f35c6 1752 "content-size=%" PRIu64 ", "
3dca2276 1753 "packet-size=%" PRIu64,
013f35c6
PP
1754 content_size_bits,
1755 packet_size_bits);
3dca2276
PP
1756 ret = -1;
1757 goto end;
1758 }
1759
013f35c6
PP
1760 /* Set packet size; make it a multiple of 8 */
1761 packet_size_bits = (content_size_bits + 7) & ~UINT64_C(7);
3dca2276
PP
1762
1763 if (stream->packet_context) {
1764 /*
013f35c6
PP
1765 * The whole packet is serialized at this point. Make
1766 * sure that, if `packet_size` is missing, the current
1767 * content size is equal to the current packet size.
3dca2276 1768 */
013f35c6
PP
1769 struct bt_ctf_field *field =
1770 bt_ctf_field_structure_get_field_by_name(
1771 stream->packet_context, "content_size");
3dca2276 1772
e1e02a22 1773 bt_ctf_object_put_ref(field);
3dca2276 1774 if (!field) {
013f35c6 1775 if (content_size_bits != packet_size_bits) {
3dca2276
PP
1776 BT_LOGW("Stream's packet context's `content_size` field is missing, "
1777 "but current packet's content size is not equal to its packet size: "
013f35c6 1778 "content-size=%" PRIu64 ", "
3dca2276 1779 "packet-size=%" PRIu64,
013f35c6
PP
1780 bt_ctfser_get_offset_in_current_packet_bits(&stream->ctfser),
1781 packet_size_bits);
3dca2276
PP
1782 ret = -1;
1783 goto end;
1784 }
1785 }
1786
1787 /*
1788 * Overwrite the packet context now that the stream
1789 * position's packet and content sizes have the correct
1790 * values.
3dca2276 1791 */
013f35c6
PP
1792 bt_ctfser_set_offset_in_current_packet_bits(&stream->ctfser,
1793 packet_context_offset_bits);
1794 ret = auto_populate_packet_context(stream, false,
1795 packet_size_bits, content_size_bits);
3dca2276
PP
1796 if (ret) {
1797 BT_LOGW_STR("Cannot automatically populate the stream's packet context field.");
1798 ret = -1;
1799 goto end;
1800 }
1801
ef267d12 1802 BT_LOGT("Rewriting (serializing) packet context field.");
3dca2276 1803 ret = bt_ctf_field_serialize_recursive(stream->packet_context,
013f35c6 1804 &stream->ctfser, native_byte_order);
3dca2276
PP
1805 if (ret) {
1806 BT_LOGW("Cannot serialize stream's packet context field: "
1807 "field-addr=%p", stream->packet_context);
1808 goto end;
1809 }
1810 }
1811
1812 g_ptr_array_set_size(stream->events, 0);
1813 stream->flushed_packet_count++;
013f35c6 1814 bt_ctfser_close_current_packet(&stream->ctfser, packet_size_bits / 8);
3dca2276
PP
1815
1816end:
1817 /* Reset automatically-set fields. */
1818 if (stream->packet_context) {
1819 reset_structure_field(stream->packet_context, "timestamp_begin");
1820 reset_structure_field(stream->packet_context, "timestamp_end");
1821 reset_structure_field(stream->packet_context, "packet_size");
1822 reset_structure_field(stream->packet_context, "content_size");
1823 reset_structure_field(stream->packet_context, "events_discarded");
1824 }
1825
013f35c6 1826 if (ret == 0) {
ef267d12 1827 BT_LOGT("Flushed stream's current packet: "
013f35c6
PP
1828 "content-size=%" PRIu64 ", packet-size=%" PRIu64,
1829 content_size_bits, packet_size_bits);
3dca2276
PP
1830 }
1831
1832end_no_stream:
1833 return ret;
1834}
1835
1836static
e1e02a22 1837void bt_ctf_stream_destroy(struct bt_ctf_object *obj)
3dca2276
PP
1838{
1839 struct bt_ctf_stream *stream = (void *) obj;
1840
1841 BT_LOGD("Destroying CTF writer stream object: addr=%p, name=\"%s\"",
1842 stream, bt_ctf_stream_get_name(stream));
1843
16ca5ff0 1844 bt_ctf_stream_common_finalize(BT_CTF_TO_COMMON(stream));
013f35c6 1845 bt_ctfser_fini(&stream->ctfser);
3dca2276
PP
1846
1847 if (stream->events) {
1848 BT_LOGD_STR("Putting events.");
1849 g_ptr_array_free(stream->events, TRUE);
1850 }
1851
1852 BT_LOGD_STR("Putting packet header field.");
e1e02a22 1853 bt_ctf_object_put_ref(stream->packet_header);
3dca2276 1854 BT_LOGD_STR("Putting packet context field.");
e1e02a22 1855 bt_ctf_object_put_ref(stream->packet_context);
3dca2276
PP
1856 g_free(stream);
1857}
1858
1859static
02bb4fcc 1860int _set_structure_field_integer(struct bt_ctf_field *structure, const char *name,
00409097 1861 uint64_t value, bt_ctf_bool force)
3dca2276
PP
1862{
1863 int ret = 0;
1864 struct bt_ctf_field_type *field_type = NULL;
1865 struct bt_ctf_field *integer;
1866
98b15851
PP
1867 BT_ASSERT_DBG(structure);
1868 BT_ASSERT_DBG(name);
3dca2276
PP
1869
1870 integer = bt_ctf_field_structure_get_field_by_name(structure, name);
1871 if (!integer) {
1872 /* Field not found, not an error. */
ef267d12 1873 BT_LOGT("Field not found: struct-field-addr=%p, "
3dca2276
PP
1874 "name=\"%s\", force=%d", structure, name, force);
1875 goto end;
1876 }
1877
1878 /* Make sure the payload has not already been set. */
1879 if (!force && bt_ctf_field_is_set_recursive(integer)) {
1880 /* Payload already set, not an error */
ef267d12 1881 BT_LOGT("Field's payload is already set: struct-field-addr=%p, "
3dca2276
PP
1882 "name=\"%s\", force=%d", structure, name, force);
1883 goto end;
1884 }
1885
1886 field_type = bt_ctf_field_get_type(integer);
98b15851 1887 BT_ASSERT_DBG(field_type);
3dca2276
PP
1888 if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_INTEGER) {
1889 /*
1890 * The user most likely meant for us to populate this field
1891 * automatically. However, we can only do this if the field
1892 * is an integer. Return an error.
1893 */
1894 BT_LOGW("Invalid parameter: field's type is not an integer field type: "
1895 "field-addr=%p, ft-addr=%p, ft-id=%s",
1896 integer, field_type,
16ca5ff0 1897 bt_ctf_field_type_id_string((int)
3dca2276
PP
1898 bt_ctf_field_type_get_type_id(field_type)));
1899 ret = -1;
1900 goto end;
1901 }
1902
1903 if (bt_ctf_field_type_integer_is_signed(field_type)) {
1904 ret = bt_ctf_field_integer_signed_set_value(integer,
1905 (int64_t) value);
1906 } else {
1907 ret = bt_ctf_field_integer_unsigned_set_value(integer, value);
1908 }
1909 ret = !ret ? 1 : ret;
1910end:
e1e02a22
PP
1911 bt_ctf_object_put_ref(integer);
1912 bt_ctf_object_put_ref(field_type);
3dca2276
PP
1913 return ret;
1914}
1915
1916/*
1917 * Returns the following codes:
1918 * 1 if the field was found and set,
1919 * 0 if nothing was done (field not found, or was already set),
1920 * <0 if an error was encoutered
1921 */
1922static
02bb4fcc 1923int try_set_structure_field_integer(struct bt_ctf_field *structure, const char *name,
3dca2276
PP
1924 uint64_t value)
1925{
00409097 1926 return _set_structure_field_integer(structure, name, value, BT_CTF_FALSE);
3dca2276
PP
1927}
1928
1929struct bt_ctf_stream_class *bt_ctf_stream_get_class(
1930 struct bt_ctf_stream *stream)
1931{
e1e02a22 1932 return bt_ctf_object_get_ref(bt_ctf_stream_common_borrow_class(BT_CTF_TO_COMMON(stream)));
3dca2276
PP
1933}
1934
1935const char *bt_ctf_stream_get_name(struct bt_ctf_stream *stream)
1936{
16ca5ff0 1937 return bt_ctf_stream_common_get_name(BT_CTF_TO_COMMON(stream));
3dca2276
PP
1938}
1939
1940int64_t bt_ctf_stream_get_id(struct bt_ctf_stream *stream)
1941{
16ca5ff0 1942 return bt_ctf_stream_common_get_id(BT_CTF_TO_COMMON(stream));
3dca2276 1943}
This page took 0.184417 seconds and 4 git commands to generate.