lib: rename transforming bt_X_borrow_Y() -> bt_X_as_Y()
[babeltrace.git] / lib / ctf-writer / trace.c
CommitLineData
3dca2276
PP
1/*
2 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24#define BT_LOG_TAG "CTF-WRITER-TRACE"
25#include <babeltrace/lib-logging-internal.h>
26
16ca5ff0
PP
27#include <babeltrace/assert-internal.h>
28#include <babeltrace/compiler-internal.h>
29#include <babeltrace/ctf-writer/attributes-internal.h>
30#include <babeltrace/ctf-writer/clock-class-internal.h>
3dca2276 31#include <babeltrace/ctf-writer/clock-internal.h>
16ca5ff0
PP
32#include <babeltrace/ctf-writer/event-class-internal.h>
33#include <babeltrace/ctf-writer/event.h>
34#include <babeltrace/ctf-writer/event-internal.h>
35#include <babeltrace/ctf-writer/field-types-internal.h>
36#include <babeltrace/ctf-writer/field-wrapper-internal.h>
37#include <babeltrace/ctf-writer/functor-internal.h>
3dca2276 38#include <babeltrace/ctf-writer/stream-class-internal.h>
16ca5ff0
PP
39#include <babeltrace/ctf-writer/stream-internal.h>
40#include <babeltrace/ctf-writer/trace-internal.h>
41#include <babeltrace/ctf-writer/utils-internal.h>
42#include <babeltrace/ctf-writer/utils.h>
43#include <babeltrace/ctf-writer/validation-internal.h>
44#include <babeltrace/ctf-writer/visitor-internal.h>
3dca2276 45#include <babeltrace/ctf-writer/writer-internal.h>
16ca5ff0 46#include <babeltrace/endian-internal.h>
65300d60 47#include <babeltrace/object.h>
16ca5ff0
PP
48#include <babeltrace/types.h>
49#include <babeltrace/values-internal.h>
50#include <babeltrace/values.h>
51#include <inttypes.h>
52#include <stdint.h>
53#include <stdlib.h>
54#include <string.h>
55
56#define DEFAULT_IDENTIFIER_SIZE 128
57#define DEFAULT_METADATA_STRING_SIZE 4096
58
59BT_HIDDEN
60int bt_ctf_trace_common_initialize(struct bt_ctf_trace_common *trace,
61 bt_object_release_func release_func)
62{
63 int ret = 0;
64
65 BT_LOGD_STR("Initializing common trace object.");
66 trace->native_byte_order = BT_CTF_BYTE_ORDER_UNSPECIFIED;
67 bt_object_init_shared_with_parent(&trace->base, release_func);
68 trace->clock_classes = g_ptr_array_new_with_free_func(
65300d60 69 (GDestroyNotify) bt_object_put_ref);
16ca5ff0
PP
70 if (!trace->clock_classes) {
71 BT_LOGE_STR("Failed to allocate one GPtrArray.");
72 goto error;
73 }
74
75 trace->streams = g_ptr_array_new_with_free_func(
76 (GDestroyNotify) bt_object_try_spec_release);
77 if (!trace->streams) {
78 BT_LOGE_STR("Failed to allocate one GPtrArray.");
79 goto error;
80 }
81
82 trace->stream_classes = g_ptr_array_new_with_free_func(
83 (GDestroyNotify) bt_object_try_spec_release);
84 if (!trace->stream_classes) {
85 BT_LOGE_STR("Failed to allocate one GPtrArray.");
86 goto error;
87 }
88
89 /* Create the environment array object */
90 trace->environment = bt_ctf_attributes_create();
91 if (!trace->environment) {
92 BT_LOGE_STR("Cannot create empty attributes object.");
93 goto error;
94 }
95
96 BT_LOGD("Initialized common trace object: addr=%p", trace);
97 goto end;
98
99error:
100 ret = -1;
101
102end:
103 return ret;
104}
105
106BT_HIDDEN
107void bt_ctf_trace_common_finalize(struct bt_ctf_trace_common *trace)
108{
109 BT_LOGD("Finalizing common trace object: addr=%p, name=\"%s\"",
110 trace, bt_ctf_trace_common_get_name(trace));
111
112 if (trace->environment) {
113 BT_LOGD_STR("Destroying environment attributes.");
114 bt_ctf_attributes_destroy(trace->environment);
115 }
116
117 if (trace->name) {
118 g_string_free(trace->name, TRUE);
119 }
120
121 if (trace->clock_classes) {
122 BT_LOGD_STR("Putting clock classes.");
123 g_ptr_array_free(trace->clock_classes, TRUE);
124 }
125
126 if (trace->streams) {
127 BT_LOGD_STR("Destroying streams.");
128 g_ptr_array_free(trace->streams, TRUE);
129 }
130
131 if (trace->stream_classes) {
132 BT_LOGD_STR("Destroying stream classes.");
133 g_ptr_array_free(trace->stream_classes, TRUE);
134 }
135
136 BT_LOGD_STR("Putting packet header field type.");
65300d60 137 bt_object_put_ref(trace->packet_header_field_type);
16ca5ff0
PP
138}
139
140BT_HIDDEN
141int bt_ctf_trace_common_set_name(struct bt_ctf_trace_common *trace, const char *name)
142{
143 int ret = 0;
144
145 if (!trace) {
146 BT_LOGW_STR("Invalid parameter: trace is NULL.");
147 ret = -1;
148 goto end;
149 }
150
151 if (!name) {
152 BT_LOGW_STR("Invalid parameter: name is NULL.");
153 ret = -1;
154 goto end;
155 }
156
157 if (trace->frozen) {
158 BT_LOGW("Invalid parameter: trace is frozen: "
159 "addr=%p, name=\"%s\"",
160 trace, bt_ctf_trace_common_get_name(trace));
161 ret = -1;
162 goto end;
163 }
164
165 trace->name = trace->name ? g_string_assign(trace->name, name) :
166 g_string_new(name);
167 if (!trace->name) {
168 BT_LOGE_STR("Failed to allocate one GString.");
169 ret = -1;
170 goto end;
171 }
172
173 BT_LOGV("Set trace's name: addr=%p, name=\"%s\"", trace, name);
174
175end:
176 return ret;
177}
178
179BT_HIDDEN
180int bt_ctf_trace_common_set_uuid(struct bt_ctf_trace_common *trace,
181 const unsigned char *uuid)
182{
183 int ret = 0;
184
185 if (!trace) {
186 BT_LOGW_STR("Invalid parameter: trace is NULL.");
187 ret = -1;
188 goto end;
189 }
190
191 if (!uuid) {
192 BT_LOGW_STR("Invalid parameter: UUID is NULL.");
193 ret = -1;
194 goto end;
195 }
196
197 if (trace->frozen) {
198 BT_LOGW("Invalid parameter: trace is frozen: "
199 "addr=%p, name=\"%s\"",
200 trace, bt_ctf_trace_common_get_name(trace));
201 ret = -1;
202 goto end;
203 }
204
205 memcpy(trace->uuid, uuid, BABELTRACE_UUID_LEN);
206 trace->uuid_set = BT_TRUE;
207 BT_LOGV("Set trace's UUID: addr=%p, name=\"%s\", "
208 "uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\"",
209 trace, bt_ctf_trace_common_get_name(trace),
210 (unsigned int) uuid[0],
211 (unsigned int) uuid[1],
212 (unsigned int) uuid[2],
213 (unsigned int) uuid[3],
214 (unsigned int) uuid[4],
215 (unsigned int) uuid[5],
216 (unsigned int) uuid[6],
217 (unsigned int) uuid[7],
218 (unsigned int) uuid[8],
219 (unsigned int) uuid[9],
220 (unsigned int) uuid[10],
221 (unsigned int) uuid[11],
222 (unsigned int) uuid[12],
223 (unsigned int) uuid[13],
224 (unsigned int) uuid[14],
225 (unsigned int) uuid[15]);
226
227end:
228 return ret;
229}
230
231BT_HIDDEN
232int bt_ctf_trace_common_set_environment_field(struct bt_ctf_trace_common *trace,
da91b29a 233 const char *name, struct bt_private_value *value)
16ca5ff0
PP
234{
235 int ret = 0;
236
237 if (!trace) {
238 BT_LOGW_STR("Invalid parameter: trace is NULL.");
239 ret = -1;
240 goto end;
241 }
242
243 if (!name) {
244 BT_LOGW_STR("Invalid parameter: name is NULL.");
245 ret = -1;
246 goto end;
247 }
248
249 if (!value) {
250 BT_LOGW_STR("Invalid parameter: value is NULL.");
251 ret = -1;
252 goto end;
253 }
254
255 if (!bt_ctf_identifier_is_valid(name)) {
256 BT_LOGW("Invalid parameter: environment field's name is not a valid CTF identifier: "
257 "trace-addr=%p, trace-name=\"%s\", "
258 "env-name=\"%s\"",
259 trace, bt_ctf_trace_common_get_name(trace), name);
260 ret = -1;
261 goto end;
262 }
263
707b7d35
PP
264 if (!bt_value_is_integer(bt_private_value_as_value(value)) &&
265 !bt_value_is_string(bt_private_value_as_value(value))) {
16ca5ff0
PP
266 BT_LOGW("Invalid parameter: environment field's value is not an integer or string value: "
267 "trace-addr=%p, trace-name=\"%s\", "
268 "env-name=\"%s\", env-value-type=%s",
269 trace, bt_ctf_trace_common_get_name(trace), name,
da91b29a
PP
270 bt_common_value_type_string(
271 bt_value_get_type(
707b7d35 272 bt_private_value_as_value(value))));
16ca5ff0
PP
273 ret = -1;
274 goto end;
275 }
276
277 if (trace->frozen) {
278 /*
279 * New environment fields may be added to a frozen trace,
280 * but existing fields may not be changed.
281 *
282 * The object passed is frozen like all other attributes.
283 */
da91b29a 284 struct bt_private_value *attribute =
16ca5ff0
PP
285 bt_ctf_attributes_borrow_field_value_by_name(
286 trace->environment, name);
287
288 if (attribute) {
289 BT_LOGW("Invalid parameter: trace is frozen and environment field already exists with this name: "
290 "trace-addr=%p, trace-name=\"%s\", "
291 "env-name=\"%s\"",
292 trace, bt_ctf_trace_common_get_name(trace), name);
293 ret = -1;
294 goto end;
295 }
296
707b7d35 297 bt_value_freeze(bt_private_value_as_value(value));
16ca5ff0
PP
298 }
299
300 ret = bt_ctf_attributes_set_field_value(trace->environment, name,
301 value);
302 if (ret) {
303 BT_LOGE("Cannot set environment field's value: "
304 "trace-addr=%p, trace-name=\"%s\", "
305 "env-name=\"%s\"",
306 trace, bt_ctf_trace_common_get_name(trace), name);
307 } else {
308 BT_LOGV("Set environment field's value: "
309 "trace-addr=%p, trace-name=\"%s\", "
310 "env-name=\"%s\", value-addr=%p",
311 trace, bt_ctf_trace_common_get_name(trace), name, value);
312 }
313
314end:
315 return ret;
316}
317
318BT_HIDDEN
319int bt_ctf_trace_common_set_environment_field_string(struct bt_ctf_trace_common *trace,
320 const char *name, const char *value)
321{
322 int ret = 0;
da91b29a 323 struct bt_private_value *env_value_string_obj = NULL;
16ca5ff0
PP
324
325 if (!value) {
326 BT_LOGW_STR("Invalid parameter: value is NULL.");
327 ret = -1;
328 goto end;
329 }
330
da91b29a 331 env_value_string_obj = bt_private_value_string_create_init(value);
16ca5ff0
PP
332 if (!env_value_string_obj) {
333 BT_LOGE_STR("Cannot create string value object.");
334 ret = -1;
335 goto end;
336 }
337
338 /* bt_ctf_trace_common_set_environment_field() logs errors */
339 ret = bt_ctf_trace_common_set_environment_field(trace, name,
340 env_value_string_obj);
341
342end:
65300d60 343 bt_object_put_ref(env_value_string_obj);
16ca5ff0
PP
344 return ret;
345}
346
347BT_HIDDEN
348int bt_ctf_trace_common_set_environment_field_integer(
349 struct bt_ctf_trace_common *trace, const char *name, int64_t value)
350{
351 int ret = 0;
da91b29a 352 struct bt_private_value *env_value_integer_obj = NULL;
16ca5ff0 353
da91b29a 354 env_value_integer_obj = bt_private_value_integer_create_init(value);
16ca5ff0
PP
355 if (!env_value_integer_obj) {
356 BT_LOGE_STR("Cannot create integer value object.");
357 ret = -1;
358 goto end;
359 }
360
361 /* bt_ctf_trace_common_set_environment_field() logs errors */
362 ret = bt_ctf_trace_common_set_environment_field(trace, name,
363 env_value_integer_obj);
364
365end:
65300d60 366 bt_object_put_ref(env_value_integer_obj);
16ca5ff0
PP
367 return ret;
368}
369
370BT_HIDDEN
371int bt_ctf_trace_common_add_clock_class(struct bt_ctf_trace_common *trace,
372 struct bt_ctf_clock_class *clock_class)
373{
374 int ret = 0;
375
376 if (!trace) {
377 BT_LOGW_STR("Invalid parameter: trace is NULL.");
378 ret = -1;
379 goto end;
380 }
381
382 if (!bt_ctf_clock_class_is_valid(clock_class)) {
383 BT_LOGW("Invalid parameter: clock class is invalid: "
384 "trace-addr=%p, trace-name=\"%s\", "
385 "clock-class-addr=%p, clock-class-name=\"%s\"",
386 trace, bt_ctf_trace_common_get_name(trace),
387 clock_class, bt_ctf_clock_class_get_name(clock_class));
388 ret = -1;
389 goto end;
390 }
391
392 /* Check for duplicate clock classes */
393 if (bt_ctf_trace_common_has_clock_class(trace, clock_class)) {
394 BT_LOGW("Invalid parameter: clock class already exists in trace: "
395 "trace-addr=%p, trace-name=\"%s\", "
396 "clock-class-addr=%p, clock-class-name=\"%s\"",
397 trace, bt_ctf_trace_common_get_name(trace),
398 clock_class, bt_ctf_clock_class_get_name(clock_class));
399 ret = -1;
400 goto end;
401 }
402
65300d60 403 bt_object_get_ref(clock_class);
16ca5ff0
PP
404 g_ptr_array_add(trace->clock_classes, clock_class);
405
406 if (trace->frozen) {
407 BT_LOGV_STR("Freezing added clock class because trace is frozen.");
408 bt_ctf_clock_class_freeze(clock_class);
409 }
410
411 BT_LOGV("Added clock class to trace: "
412 "trace-addr=%p, trace-name=\"%s\", "
413 "clock-class-addr=%p, clock-class-name=\"%s\"",
414 trace, bt_ctf_trace_common_get_name(trace),
415 clock_class, bt_ctf_clock_class_get_name(clock_class));
416
417end:
418 return ret;
419}
420
421static
422bool packet_header_field_type_is_valid(struct bt_ctf_trace_common *trace,
423 struct bt_ctf_field_type_common *packet_header_type)
424{
425 int ret;
426 bool is_valid = true;
427 struct bt_ctf_field_type_common *field_type = NULL;
428
429 if (!packet_header_type) {
430 /*
431 * No packet header field type: trace must have only
432 * one stream. At this point the stream class being
433 * added is not part of the trace yet, so we validate
434 * that the trace contains no stream classes yet.
435 */
436 if (trace->stream_classes->len >= 1) {
437 BT_LOGW_STR("Invalid packet header field type: "
438 "packet header field type does not exist but there's more than one stream class in the trace.");
439 goto invalid;
440 }
441
442 /* No packet header field type: valid at this point */
443 goto end;
444 }
445
446 /* Packet header field type, if it exists, must be a structure */
447 if (packet_header_type->id != BT_CTF_FIELD_TYPE_ID_STRUCT) {
448 BT_LOGW("Invalid packet header field type: must be a structure field type if it exists: "
449 "ft-addr=%p, ft-id=%s",
450 packet_header_type,
451 bt_ctf_field_type_id_string(packet_header_type->id));
452 goto invalid;
453 }
454
455 /*
456 * If there's a `magic` field, it must be a 32-bit unsigned
457 * integer field type. Also it must be the first field of the
458 * packet header field type.
459 */
460 field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
461 packet_header_type, "magic");
462 if (field_type) {
463 const char *field_name;
464
465 if (field_type->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
466 BT_LOGW("Invalid packet header field type: `magic` field must be an integer field type: "
467 "magic-ft-addr=%p, magic-ft-id=%s",
468 field_type,
469 bt_ctf_field_type_id_string(field_type->id));
470 goto invalid;
471 }
472
473 if (bt_ctf_field_type_common_integer_is_signed(field_type)) {
474 BT_LOGW("Invalid packet header field type: `magic` field must be an unsigned integer field type: "
475 "magic-ft-addr=%p", field_type);
476 goto invalid;
477 }
478
479 if (bt_ctf_field_type_common_integer_get_size(field_type) != 32) {
480 BT_LOGW("Invalid packet header field type: `magic` field must be a 32-bit unsigned integer field type: "
481 "magic-ft-addr=%p, magic-ft-size=%u",
482 field_type,
483 bt_ctf_field_type_common_integer_get_size(field_type));
484 goto invalid;
485 }
486
487 ret = bt_ctf_field_type_common_structure_borrow_field_by_index(
488 packet_header_type, &field_name, NULL, 0);
489 BT_ASSERT(ret == 0);
490
491 if (strcmp(field_name, "magic") != 0) {
492 BT_LOGW("Invalid packet header field type: `magic` field must be the first field: "
493 "magic-ft-addr=%p, first-field-name=\"%s\"",
494 field_type, field_name);
495 goto invalid;
496 }
497 }
498
499 /*
500 * If there's a `uuid` field, it must be an array field type of
501 * length 16 with an 8-bit unsigned integer element field type.
502 */
503 field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
504 packet_header_type, "uuid");
505 if (field_type) {
506 struct bt_ctf_field_type_common *elem_ft;
507
508 if (field_type->id != BT_CTF_FIELD_TYPE_ID_ARRAY) {
509 BT_LOGW("Invalid packet header field type: `uuid` field must be an array field type: "
510 "uuid-ft-addr=%p, uuid-ft-id=%s",
511 field_type,
512 bt_ctf_field_type_id_string(field_type->id));
513 goto invalid;
514 }
515
516 if (bt_ctf_field_type_common_array_get_length(field_type) != 16) {
517 BT_LOGW("Invalid packet header field type: `uuid` array field type's length must be 16: "
518 "uuid-ft-addr=%p, uuid-ft-length=%" PRId64,
519 field_type,
520 bt_ctf_field_type_common_array_get_length(field_type));
521 goto invalid;
522 }
523
524 elem_ft = bt_ctf_field_type_common_array_borrow_element_field_type(field_type);
525 BT_ASSERT(elem_ft);
526
527 if (elem_ft->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
528 BT_LOGW("Invalid packet header field type: `uuid` field's element field type must be an integer field type: "
529 "elem-ft-addr=%p, elem-ft-id=%s",
530 elem_ft,
531 bt_ctf_field_type_id_string(elem_ft->id));
532 goto invalid;
533 }
534
535 if (bt_ctf_field_type_common_integer_is_signed(elem_ft)) {
536 BT_LOGW("Invalid packet header field type: `uuid` field's element field type must be an unsigned integer field type: "
537 "elem-ft-addr=%p", elem_ft);
538 goto invalid;
539 }
540
541 if (bt_ctf_field_type_common_integer_get_size(elem_ft) != 8) {
542 BT_LOGW("Invalid packet header field type: `uuid` field's element field type must be an 8-bit unsigned integer field type: "
543 "elem-ft-addr=%p, elem-ft-size=%u",
544 elem_ft,
545 bt_ctf_field_type_common_integer_get_size(elem_ft));
546 goto invalid;
547 }
548 }
549
550 /*
551 * The `stream_id` field must exist if there's more than one
552 * stream classes in the trace.
553 */
554 field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
555 packet_header_type, "stream_id");
556
557 if (!field_type && trace->stream_classes->len >= 1) {
558 BT_LOGW_STR("Invalid packet header field type: "
559 "`stream_id` field does not exist but there's more than one stream class in the trace.");
560 goto invalid;
561 }
562
563 /*
564 * If there's a `stream_id` field, it must be an unsigned
565 * integer field type.
566 */
567 if (field_type) {
568 if (field_type->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
569 BT_LOGW("Invalid packet header field type: `stream_id` field must be an integer field type: "
570 "stream-id-ft-addr=%p, stream-id-ft-id=%s",
571 field_type,
572 bt_ctf_field_type_id_string(field_type->id));
573 goto invalid;
574 }
575
576 if (bt_ctf_field_type_common_integer_is_signed(field_type)) {
577 BT_LOGW("Invalid packet header field type: `stream_id` field must be an unsigned integer field type: "
578 "stream-id-ft-addr=%p", field_type);
579 goto invalid;
580 }
581 }
582
583 /*
584 * If there's a `packet_seq_num` field, it must be an unsigned
585 * integer field type.
586 */
587 field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
588 packet_header_type, "packet_seq_num");
589 if (field_type) {
590 if (field_type->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
591 BT_LOGW("Invalid packet header field type: `packet_seq_num` field must be an integer field type: "
592 "stream-id-ft-addr=%p, packet-seq-num-ft-id=%s",
593 field_type,
594 bt_ctf_field_type_id_string(field_type->id));
595 goto invalid;
596 }
597
598 if (bt_ctf_field_type_common_integer_is_signed(field_type)) {
599 BT_LOGW("Invalid packet header field type: `packet_seq_num` field must be an unsigned integer field type: "
600 "packet-seq-num-ft-addr=%p", field_type);
601 goto invalid;
602 }
603 }
604
605 goto end;
606
607invalid:
608 is_valid = false;
609
610end:
611 return is_valid;
612}
613
614static
615bool packet_context_field_type_is_valid(struct bt_ctf_trace_common *trace,
616 struct bt_ctf_stream_class_common *stream_class,
617 struct bt_ctf_field_type_common *packet_context_type,
618 bool check_ts_begin_end_mapped)
619{
620 bool is_valid = true;
621 struct bt_ctf_field_type_common *field_type = NULL;
622
623 if (!packet_context_type) {
624 /* No packet context field type: valid at this point */
625 goto end;
626 }
627
628 /* Packet context field type, if it exists, must be a structure */
629 if (packet_context_type->id != BT_CTF_FIELD_TYPE_ID_STRUCT) {
630 BT_LOGW("Invalid packet context field type: must be a structure field type if it exists: "
631 "ft-addr=%p, ft-id=%s",
632 packet_context_type,
633 bt_ctf_field_type_id_string(packet_context_type->id));
634 goto invalid;
635 }
636
637 /*
638 * If there's a `packet_size` field, it must be an unsigned
639 * integer field type.
640 */
641 field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
642 packet_context_type, "packet_size");
643 if (field_type) {
644 if (field_type->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
645 BT_LOGW("Invalid packet context field type: `packet_size` field must be an integer field type: "
646 "packet-size-ft-addr=%p, packet-size-ft-id=%s",
647 field_type,
648 bt_ctf_field_type_id_string(field_type->id));
649 goto invalid;
650 }
651
652 if (bt_ctf_field_type_common_integer_is_signed(field_type)) {
653 BT_LOGW("Invalid packet context field type: `packet_size` field must be an unsigned integer field type: "
654 "packet-size-ft-addr=%p", field_type);
655 goto invalid;
656 }
657 }
658
659 /*
660 * If there's a `content_size` field, it must be an unsigned
661 * integer field type.
662 */
663 field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
664 packet_context_type, "content_size");
665 if (field_type) {
666 if (field_type->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
667 BT_LOGW("Invalid packet context field type: `content_size` field must be an integer field type: "
668 "content-size-ft-addr=%p, content-size-ft-id=%s",
669 field_type,
670 bt_ctf_field_type_id_string(field_type->id));
671 goto invalid;
672 }
673
674 if (bt_ctf_field_type_common_integer_is_signed(field_type)) {
675 BT_LOGW("Invalid packet context field type: `content_size` field must be an unsigned integer field type: "
676 "content-size-ft-addr=%p", field_type);
677 goto invalid;
678 }
679 }
680
681 /*
682 * If there's a `events_discarded` field, it must be an unsigned
683 * integer field type.
684 */
685 field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
686 packet_context_type, "events_discarded");
687 if (field_type) {
688 if (field_type->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
689 BT_LOGW("Invalid packet context field type: `events_discarded` field must be an integer field type: "
690 "events-discarded-ft-addr=%p, events-discarded-ft-id=%s",
691 field_type,
692 bt_ctf_field_type_id_string(field_type->id));
693 goto invalid;
694 }
695
696 if (bt_ctf_field_type_common_integer_is_signed(field_type)) {
697 BT_LOGW("Invalid packet context field type: `events_discarded` field must be an unsigned integer field type: "
698 "events-discarded-ft-addr=%p", field_type);
699 goto invalid;
700 }
701 }
702
703 /*
704 * If there's a `timestamp_begin` field, it must be an unsigned
705 * integer field type. Also, if the trace is not a CTF writer's
706 * trace, then we cannot automatically set the mapped clock
707 * class of this field, so it must have a mapped clock class.
708 */
709 field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
710 packet_context_type, "timestamp_begin");
711 if (field_type) {
712 if (field_type->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
713 BT_LOGW("Invalid packet context field type: `timestamp_begin` field must be an integer field type: "
714 "timestamp-begin-ft-addr=%p, timestamp-begin-ft-id=%s",
715 field_type,
716 bt_ctf_field_type_id_string(field_type->id));
717 goto invalid;
718 }
719
720 if (bt_ctf_field_type_common_integer_is_signed(field_type)) {
721 BT_LOGW("Invalid packet context field type: `timestamp_begin` field must be an unsigned integer field type: "
722 "timestamp-begin-ft-addr=%p", field_type);
723 goto invalid;
724 }
725
726 if (check_ts_begin_end_mapped) {
727 struct bt_ctf_clock_class *clock_class =
728 bt_ctf_field_type_common_integer_borrow_mapped_clock_class(
729 field_type);
730
731 if (!clock_class) {
732 BT_LOGW("Invalid packet context field type: `timestamp_begin` field must be mapped to a clock class: "
733 "timestamp-begin-ft-addr=%p", field_type);
734 goto invalid;
735 }
736 }
737 }
3dca2276 738
16ca5ff0
PP
739 /*
740 * If there's a `timestamp_end` field, it must be an unsigned
741 * integer field type. Also, if the trace is not a CTF writer's
742 * trace, then we cannot automatically set the mapped clock
743 * class of this field, so it must have a mapped clock class.
744 */
745 field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
746 packet_context_type, "timestamp_end");
747 if (field_type) {
748 if (field_type->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
749 BT_LOGW("Invalid packet context field type: `timestamp_end` field must be an integer field type: "
750 "timestamp-end-ft-addr=%p, timestamp-end-ft-id=%s",
751 field_type,
752 bt_ctf_field_type_id_string(field_type->id));
753 goto invalid;
754 }
755
756 if (bt_ctf_field_type_common_integer_is_signed(field_type)) {
757 BT_LOGW("Invalid packet context field type: `timestamp_end` field must be an unsigned integer field type: "
758 "timestamp-end-ft-addr=%p", field_type);
759 goto invalid;
760 }
761
762 if (check_ts_begin_end_mapped) {
763 struct bt_ctf_clock_class *clock_class =
764 bt_ctf_field_type_common_integer_borrow_mapped_clock_class(
765 field_type);
766
767 if (!clock_class) {
768 BT_LOGW("Invalid packet context field type: `timestamp_end` field must be mapped to a clock class: "
769 "timestamp-end-ft-addr=%p", field_type);
770 goto invalid;
771 }
772 }
773 }
774
775 goto end;
776
777invalid:
778 is_valid = false;
779
780end:
781 return is_valid;
782}
783
784static
785bool event_header_field_type_is_valid(struct bt_ctf_trace_common *trace,
786 struct bt_ctf_stream_class_common *stream_class,
787 struct bt_ctf_field_type_common *event_header_type)
788{
789 bool is_valid = true;
790 struct bt_ctf_field_type_common *field_type = NULL;
791
792 /*
793 * We do not validate that the `timestamp` field exists here
794 * because CTF does not require this exact name to be mapped to
795 * a clock class.
796 */
797
798 if (!event_header_type) {
799 /*
800 * No event header field type: stream class must have
801 * only one event class.
802 */
803 if (bt_ctf_stream_class_common_get_event_class_count(stream_class) > 1) {
804 BT_LOGW_STR("Invalid event header field type: "
805 "event header field type does not exist but there's more than one event class in the stream class.");
806 goto invalid;
807 }
808
809 /* No event header field type: valid at this point */
810 goto end;
811 }
812
813 /* Event header field type, if it exists, must be a structure */
814 if (event_header_type->id != BT_CTF_FIELD_TYPE_ID_STRUCT) {
815 BT_LOGW("Invalid event header field type: must be a structure field type if it exists: "
816 "ft-addr=%p, ft-id=%s",
817 event_header_type,
818 bt_ctf_field_type_id_string(event_header_type->id));
819 goto invalid;
820 }
821
822 /*
823 * If there's an `id` field, it must be an unsigned integer
824 * field type or an enumeration field type with an unsigned
825 * integer container field type.
826 */
827 field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
828 event_header_type, "id");
829 if (field_type) {
830 struct bt_ctf_field_type_common *int_ft;
831
832 if (field_type->id == BT_CTF_FIELD_TYPE_ID_INTEGER) {
833 int_ft = field_type;
834 } else if (field_type->id == BT_CTF_FIELD_TYPE_ID_ENUM) {
835 int_ft = bt_ctf_field_type_common_enumeration_borrow_container_field_type(
836 field_type);
837 } else {
838 BT_LOGW("Invalid event header field type: `id` field must be an integer or enumeration field type: "
839 "id-ft-addr=%p, id-ft-id=%s",
840 field_type,
841 bt_ctf_field_type_id_string(field_type->id));
842 goto invalid;
843 }
844
845 BT_ASSERT(int_ft);
846 if (bt_ctf_field_type_common_integer_is_signed(int_ft)) {
847 BT_LOGW("Invalid event header field type: `id` field must be an unsigned integer or enumeration field type: "
848 "id-ft-addr=%p", int_ft);
849 goto invalid;
850 }
851 }
852
853 goto end;
854
855invalid:
856 is_valid = false;
857
858end:
859 return is_valid;
860}
861
862static
863int check_packet_header_type_has_no_clock_class(struct bt_ctf_trace_common *trace)
864{
865 int ret = 0;
866
867 if (trace->packet_header_field_type) {
868 struct bt_ctf_clock_class *clock_class = NULL;
869
870 ret = bt_ctf_field_type_common_validate_single_clock_class(
871 trace->packet_header_field_type,
872 &clock_class);
65300d60 873 bt_object_put_ref(clock_class);
16ca5ff0
PP
874 if (ret || clock_class) {
875 BT_LOGW("Trace's packet header field type cannot "
876 "contain a field type which is mapped to "
877 "a clock class: "
878 "trace-addr=%p, trace-name=\"%s\", "
879 "clock-class-name=\"%s\"",
880 trace, bt_ctf_trace_common_get_name(trace),
881 clock_class ?
882 bt_ctf_clock_class_get_name(clock_class) :
883 NULL);
884 ret = -1;
885 }
886 }
887
888 return ret;
889}
890
891BT_HIDDEN
892int bt_ctf_trace_common_add_stream_class(struct bt_ctf_trace_common *trace,
893 struct bt_ctf_stream_class_common *stream_class,
894 bt_ctf_validation_flag_copy_field_type_func copy_field_type_func,
895 struct bt_ctf_clock_class *init_expected_clock_class,
896 int (*map_clock_classes_func)(struct bt_ctf_stream_class_common *stream_class,
897 struct bt_ctf_field_type_common *packet_context_field_type,
898 struct bt_ctf_field_type_common *event_header_field_type),
899 bool check_ts_begin_end_mapped)
900{
901 int ret;
902 int64_t i;
903 int64_t stream_id;
904 struct bt_ctf_validation_output trace_sc_validation_output = { 0 };
905 struct bt_ctf_validation_output *ec_validation_outputs = NULL;
906 const enum bt_ctf_validation_flag trace_sc_validation_flags =
907 BT_CTF_VALIDATION_FLAG_TRACE |
908 BT_CTF_VALIDATION_FLAG_STREAM;
909 const enum bt_ctf_validation_flag ec_validation_flags =
910 BT_CTF_VALIDATION_FLAG_EVENT;
911 struct bt_ctf_field_type_common *packet_header_type = NULL;
912 struct bt_ctf_field_type_common *packet_context_type = NULL;
913 struct bt_ctf_field_type_common *event_header_type = NULL;
914 struct bt_ctf_field_type_common *stream_event_ctx_type = NULL;
915 int64_t event_class_count;
916 struct bt_ctf_trace_common *current_parent_trace = NULL;
917 struct bt_ctf_clock_class *expected_clock_class =
65300d60 918 bt_object_get_ref(init_expected_clock_class);
16ca5ff0
PP
919
920 BT_ASSERT(copy_field_type_func);
921
922 if (!trace) {
923 BT_LOGW_STR("Invalid parameter: trace is NULL.");
924 ret = -1;
925 goto end;
926 }
927
928 if (!stream_class) {
929 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
930 ret = -1;
931 goto end;
932 }
933
934 BT_LOGD("Adding stream class to trace: "
935 "trace-addr=%p, trace-name=\"%s\", "
936 "stream-class-addr=%p, stream-class-name=\"%s\", "
937 "stream-class-id=%" PRId64,
938 trace, bt_ctf_trace_common_get_name(trace),
939 stream_class, bt_ctf_stream_class_common_get_name(stream_class),
940 bt_ctf_stream_class_common_get_id(stream_class));
941
942 current_parent_trace = bt_ctf_stream_class_common_borrow_trace(stream_class);
943 if (current_parent_trace) {
944 /* Stream class is already associated to a trace, abort. */
945 BT_LOGW("Invalid parameter: stream class is already part of a trace: "
946 "stream-class-trace-addr=%p, "
947 "stream-class-trace-name=\"%s\"",
948 current_parent_trace,
949 bt_ctf_trace_common_get_name(current_parent_trace));
950 ret = -1;
951 goto end;
952 }
953
954 event_class_count =
955 bt_ctf_stream_class_common_get_event_class_count(stream_class);
956 BT_ASSERT(event_class_count >= 0);
957
958 if (!stream_class->frozen) {
959 /*
960 * Stream class is not frozen yet. Validate that the
961 * stream class contains at most a single clock class
962 * because the previous
963 * bt_ctf_stream_class_common_add_event_class() calls did
964 * not make this validation since the stream class's
965 * direct field types (packet context, event header,
966 * event context) could change afterwards. This stream
967 * class is about to be frozen and those field types
968 * won't be changed if this function succeeds.
969 *
970 * At this point we're also sure that the stream class's
971 * clock, if any, has the same class as the stream
972 * class's expected clock class, if any. This is why, if
973 * bt_ctf_stream_class_common_validate_single_clock_class()
974 * succeeds below, the call to
975 * bt_ctf_stream_class_map_clock_class() at the end of this
976 * function is safe because it maps to the same, single
977 * clock class.
978 */
979 ret = bt_ctf_stream_class_common_validate_single_clock_class(
980 stream_class, &expected_clock_class);
981 if (ret) {
982 BT_LOGW("Invalid parameter: stream class or one of its "
983 "event classes contains a field type which is "
984 "not recursively mapped to the expected "
985 "clock class: "
986 "stream-class-addr=%p, "
987 "stream-class-id=%" PRId64 ", "
988 "stream-class-name=\"%s\", "
989 "expected-clock-class-addr=%p, "
990 "expected-clock-class-name=\"%s\"",
991 stream_class, bt_ctf_stream_class_common_get_id(stream_class),
992 bt_ctf_stream_class_common_get_name(stream_class),
993 expected_clock_class,
994 expected_clock_class ?
995 bt_ctf_clock_class_get_name(expected_clock_class) :
996 NULL);
997 goto end;
998 }
999 }
1000
1001 ret = check_packet_header_type_has_no_clock_class(trace);
1002 if (ret) {
1003 /* check_packet_header_type_has_no_clock_class() logs errors */
1004 goto end;
1005 }
1006
1007 /*
1008 * We're about to freeze both the trace and the stream class.
1009 * Also, each event class contained in this stream class are
1010 * already frozen.
1011 *
1012 * This trace, this stream class, and all its event classes
1013 * should be valid at this point.
1014 *
1015 * Validate trace and stream class first, then each event
1016 * class of this stream class can be validated individually.
1017 */
1018 packet_header_type =
1019 bt_ctf_trace_common_borrow_packet_header_field_type(trace);
1020 packet_context_type =
1021 bt_ctf_stream_class_common_borrow_packet_context_field_type(stream_class);
1022 event_header_type =
1023 bt_ctf_stream_class_common_borrow_event_header_field_type(stream_class);
1024 stream_event_ctx_type =
1025 bt_ctf_stream_class_common_borrow_event_context_field_type(stream_class);
1026
1027 BT_LOGD("Validating trace and stream class field types.");
1028 ret = bt_ctf_validate_class_types(trace->environment,
1029 packet_header_type, packet_context_type, event_header_type,
1030 stream_event_ctx_type, NULL, NULL, trace->valid,
1031 stream_class->valid, 1, &trace_sc_validation_output,
1032 trace_sc_validation_flags, copy_field_type_func);
1033
1034 if (ret) {
1035 /*
1036 * This means something went wrong during the validation
1037 * process, not that the objects are invalid.
1038 */
1039 BT_LOGE("Failed to validate trace and stream class field types: "
1040 "ret=%d", ret);
1041 goto end;
1042 }
1043
1044 if ((trace_sc_validation_output.valid_flags &
1045 trace_sc_validation_flags) !=
1046 trace_sc_validation_flags) {
1047 /* Invalid trace/stream class */
1048 BT_LOGW("Invalid trace or stream class field types: "
1049 "valid-flags=0x%x",
1050 trace_sc_validation_output.valid_flags);
1051 ret = -1;
1052 goto end;
1053 }
1054
1055 if (event_class_count > 0) {
1056 ec_validation_outputs = g_new0(struct bt_ctf_validation_output,
1057 event_class_count);
1058 if (!ec_validation_outputs) {
1059 BT_LOGE_STR("Failed to allocate one validation output structure.");
1060 ret = -1;
1061 goto end;
1062 }
1063 }
1064
1065 /* Validate each event class individually */
1066 for (i = 0; i < event_class_count; i++) {
1067 struct bt_ctf_event_class_common *event_class =
1068 bt_ctf_stream_class_common_borrow_event_class_by_index(
1069 stream_class, i);
1070 struct bt_ctf_field_type_common *event_context_type = NULL;
1071 struct bt_ctf_field_type_common *event_payload_type = NULL;
1072
1073 event_context_type =
1074 bt_ctf_event_class_common_borrow_context_field_type(
1075 event_class);
1076 event_payload_type =
1077 bt_ctf_event_class_common_borrow_payload_field_type(
1078 event_class);
1079
1080 /*
1081 * It is important to use the field types returned by
1082 * the previous trace and stream class validation here
1083 * because copies could have been made.
1084 */
1085 BT_LOGD("Validating event class's field types: "
1086 "addr=%p, name=\"%s\", id=%" PRId64,
1087 event_class, bt_ctf_event_class_common_get_name(event_class),
1088 bt_ctf_event_class_common_get_id(event_class));
1089 ret = bt_ctf_validate_class_types(trace->environment,
1090 trace_sc_validation_output.packet_header_type,
1091 trace_sc_validation_output.packet_context_type,
1092 trace_sc_validation_output.event_header_type,
1093 trace_sc_validation_output.stream_event_ctx_type,
1094 event_context_type, event_payload_type,
1095 1, 1, event_class->valid, &ec_validation_outputs[i],
1096 ec_validation_flags, copy_field_type_func);
1097
1098 if (ret) {
1099 BT_LOGE("Failed to validate event class field types: "
1100 "ret=%d", ret);
1101 goto end;
1102 }
1103
1104 if ((ec_validation_outputs[i].valid_flags &
1105 ec_validation_flags) != ec_validation_flags) {
1106 /* Invalid event class */
1107 BT_LOGW("Invalid event class field types: "
1108 "valid-flags=0x%x",
1109 ec_validation_outputs[i].valid_flags);
1110 ret = -1;
1111 goto end;
1112 }
1113 }
1114
1115 stream_id = bt_ctf_stream_class_common_get_id(stream_class);
1116 if (stream_id < 0) {
1117 stream_id = trace->next_stream_id++;
1118 if (stream_id < 0) {
1119 BT_LOGE_STR("No more stream class IDs available.");
1120 ret = -1;
1121 goto end;
1122 }
1123
1124 /* Try to assign a new stream id */
1125 for (i = 0; i < trace->stream_classes->len; i++) {
1126 if (stream_id == bt_ctf_stream_class_common_get_id(
1127 trace->stream_classes->pdata[i])) {
1128 /* Duplicate stream id found */
1129 BT_LOGW("Duplicate stream class ID: "
1130 "id=%" PRId64, (int64_t) stream_id);
1131 ret = -1;
1132 goto end;
1133 }
1134 }
1135
1136 if (bt_ctf_stream_class_common_set_id_no_check(stream_class,
1137 stream_id)) {
1138 /* TODO Should retry with a different stream id */
1139 BT_LOGE("Cannot set stream class's ID: "
1140 "id=%" PRId64, (int64_t) stream_id);
1141 ret = -1;
1142 goto end;
1143 }
1144 }
1145
1146 /*
1147 * At this point all the field types in the validation output
1148 * are valid. Validate the semantics of some scopes according to
1149 * the CTF specification.
1150 */
1151 if (!packet_header_field_type_is_valid(trace,
1152 trace_sc_validation_output.packet_header_type)) {
1153 BT_LOGW_STR("Invalid trace's packet header field type.");
1154 ret = -1;
1155 goto end;
1156 }
1157
1158 if (!packet_context_field_type_is_valid(trace,
1159 stream_class,
1160 trace_sc_validation_output.packet_context_type,
1161 check_ts_begin_end_mapped)) {
1162 BT_LOGW_STR("Invalid stream class's packet context field type.");
1163 ret = -1;
1164 goto end;
1165 }
1166
1167 if (!event_header_field_type_is_valid(trace,
1168 stream_class,
1169 trace_sc_validation_output.event_header_type)) {
1170 BT_LOGW_STR("Invalid steam class's event header field type.");
1171 ret = -1;
1172 goto end;
1173 }
1174
1175 /*
1176 * Now is the time to automatically map specific field types of
1177 * the stream class's packet context and event header field
1178 * types to the stream class's clock's class if they are not
1179 * mapped to a clock class yet. We do it here because we know
1180 * that after this point, everything is frozen so it won't be
1181 * possible for the user to modify the stream class's clock, or
1182 * to map those field types to other clock classes.
1183 */
1184 if (map_clock_classes_func) {
1185 if (map_clock_classes_func(stream_class,
1186 trace_sc_validation_output.packet_context_type,
1187 trace_sc_validation_output.event_header_type)) {
1188 /* map_clock_classes_func() logs errors */
1189 ret = -1;
1190 goto end;
1191 }
1192 }
1193
1194 bt_object_set_parent(&stream_class->base, &trace->base);
1195 g_ptr_array_add(trace->stream_classes, stream_class);
1196
1197 /*
1198 * At this point we know that the function will be successful.
1199 * Therefore we can replace the trace and stream class field
1200 * types with what's in their validation output structure and
1201 * mark them as valid. We can also replace the field types of
1202 * all the event classes of the stream class and mark them as
1203 * valid.
1204 */
1205 bt_ctf_validation_replace_types(trace, stream_class, NULL,
1206 &trace_sc_validation_output, trace_sc_validation_flags);
1207 trace->valid = 1;
1208 stream_class->valid = 1;
1209
1210 /*
1211 * Put what was not moved in bt_ctf_validation_replace_types().
1212 */
1213 bt_ctf_validation_output_put_types(&trace_sc_validation_output);
1214
1215 for (i = 0; i < event_class_count; i++) {
1216 struct bt_ctf_event_class_common *event_class =
1217 bt_ctf_stream_class_common_borrow_event_class_by_index(
1218 stream_class, i);
1219
1220 bt_ctf_validation_replace_types(NULL, NULL, event_class,
1221 &ec_validation_outputs[i], ec_validation_flags);
1222 event_class->valid = 1;
1223
1224 /*
1225 * Put what was not moved in
1226 * bt_ctf_validation_replace_types().
1227 */
1228 bt_ctf_validation_output_put_types(&ec_validation_outputs[i]);
1229 }
1230
1231 /*
1232 * Freeze the trace and the stream class.
1233 */
1234 bt_ctf_stream_class_common_freeze(stream_class);
1235 bt_ctf_trace_common_freeze(trace);
1236
1237 /*
1238 * It is safe to set the stream class's unique clock class
1239 * now because the stream class is frozen.
1240 */
1241 if (expected_clock_class) {
65300d60 1242 BT_OBJECT_MOVE_REF(stream_class->clock_class, expected_clock_class);
16ca5ff0
PP
1243 }
1244
1245 BT_LOGD("Added stream class to trace: "
1246 "trace-addr=%p, trace-name=\"%s\", "
1247 "stream-class-addr=%p, stream-class-name=\"%s\", "
1248 "stream-class-id=%" PRId64,
1249 trace, bt_ctf_trace_common_get_name(trace),
1250 stream_class, bt_ctf_stream_class_common_get_name(stream_class),
1251 bt_ctf_stream_class_common_get_id(stream_class));
1252
1253end:
1254 if (ret) {
1255 bt_object_set_parent(&stream_class->base, NULL);
1256
1257 if (ec_validation_outputs) {
1258 for (i = 0; i < event_class_count; i++) {
1259 bt_ctf_validation_output_put_types(
1260 &ec_validation_outputs[i]);
1261 }
1262 }
1263 }
1264
1265 g_free(ec_validation_outputs);
1266 bt_ctf_validation_output_put_types(&trace_sc_validation_output);
65300d60 1267 bt_object_put_ref(expected_clock_class);
16ca5ff0
PP
1268 return ret;
1269}
1270
1271BT_HIDDEN
1272bt_bool bt_ctf_trace_common_has_clock_class(struct bt_ctf_trace_common *trace,
1273 struct bt_ctf_clock_class *clock_class)
1274{
1275 struct bt_ctf_search_query query = { .value = clock_class, .found = 0 };
1276
1277 BT_ASSERT(trace);
1278 BT_ASSERT(clock_class);
1279
1280 g_ptr_array_foreach(trace->clock_classes, value_exists, &query);
1281 return query.found;
1282}
1283
1284BT_HIDDEN
1285int bt_ctf_trace_common_set_native_byte_order(struct bt_ctf_trace_common *trace,
1286 enum bt_ctf_byte_order byte_order, bool allow_unspecified)
1287{
1288 int ret = 0;
1289
1290 if (!trace) {
1291 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1292 ret = -1;
1293 goto end;
1294 }
1295
1296 if (trace->frozen) {
1297 BT_LOGW("Invalid parameter: trace is frozen: "
1298 "addr=%p, name=\"%s\"",
1299 trace, bt_ctf_trace_common_get_name(trace));
1300 ret = -1;
1301 goto end;
1302 }
1303
1304 if (byte_order == BT_CTF_BYTE_ORDER_UNSPECIFIED && !allow_unspecified) {
1305 BT_LOGW("Invalid parameter: BT_CTF_BYTE_ORDER_UNSPECIFIED byte order is not allowed: "
1306 "addr=%p, name=\"%s\"",
1307 trace, bt_ctf_trace_common_get_name(trace));
1308 ret = -1;
1309 goto end;
1310 }
1311
1312 if (byte_order != BT_CTF_BYTE_ORDER_LITTLE_ENDIAN &&
1313 byte_order != BT_CTF_BYTE_ORDER_BIG_ENDIAN &&
1314 byte_order != BT_CTF_BYTE_ORDER_NETWORK) {
1315 BT_LOGW("Invalid parameter: invalid byte order: "
1316 "addr=%p, name=\"%s\", bo=%s",
1317 trace, bt_ctf_trace_common_get_name(trace),
1318 bt_ctf_byte_order_string(byte_order));
1319 ret = -1;
1320 goto end;
1321 }
1322
1323 trace->native_byte_order = byte_order;
1324 BT_LOGV("Set trace's native byte order: "
1325 "addr=%p, name=\"%s\", bo=%s",
1326 trace, bt_ctf_trace_common_get_name(trace),
1327 bt_ctf_byte_order_string(byte_order));
1328
1329end:
1330 return ret;
1331}
1332
1333BT_HIDDEN
1334int bt_ctf_trace_common_set_packet_header_field_type(struct bt_ctf_trace_common *trace,
1335 struct bt_ctf_field_type_common *packet_header_type)
1336{
1337 int ret = 0;
1338
1339 if (!trace) {
1340 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1341 ret = -1;
1342 goto end;
1343 }
1344
1345 if (trace->frozen) {
1346 BT_LOGW("Invalid parameter: trace is frozen: "
1347 "addr=%p, name=\"%s\"",
1348 trace, bt_ctf_trace_common_get_name(trace));
1349 ret = -1;
1350 goto end;
1351 }
1352
1353 /* packet_header_type must be a structure. */
1354 if (packet_header_type &&
1355 packet_header_type->id != BT_CTF_FIELD_TYPE_ID_STRUCT) {
1356 BT_LOGW("Invalid parameter: packet header field type must be a structure field type if it exists: "
1357 "addr=%p, name=\"%s\", ft-addr=%p, ft-id=%s",
1358 trace, bt_ctf_trace_common_get_name(trace),
1359 packet_header_type,
1360 bt_ctf_field_type_id_string(packet_header_type->id));
1361 ret = -1;
1362 goto end;
1363 }
1364
65300d60
PP
1365 bt_object_put_ref(trace->packet_header_field_type);
1366 trace->packet_header_field_type = bt_object_get_ref(packet_header_type);
16ca5ff0
PP
1367 BT_LOGV("Set trace's packet header field type: "
1368 "addr=%p, name=\"%s\", packet-context-ft-addr=%p",
1369 trace, bt_ctf_trace_common_get_name(trace), packet_header_type);
1370end:
1371 return ret;
1372}
1373
1374static
1375int64_t get_stream_class_count(void *element)
1376{
1377 return bt_ctf_trace_get_stream_class_count(
1378 (struct bt_ctf_trace *) element);
1379}
1380
1381static
1382void *get_stream_class(void *element, int i)
1383{
1384 return bt_ctf_trace_get_stream_class_by_index(
1385 (struct bt_ctf_trace *) element, i);
1386}
1387
1388static
1389int visit_stream_class(void *object, bt_ctf_visitor visitor,void *data)
1390{
1391 return bt_ctf_stream_class_visit(object, visitor, data);
1392}
1393
1394int bt_ctf_trace_visit(struct bt_ctf_trace *trace,
1395 bt_ctf_visitor visitor, void *data)
1396{
1397 int ret;
1398 struct bt_ctf_visitor_object obj = {
1399 .object = trace,
1400 .type = BT_CTF_VISITOR_OBJECT_TYPE_TRACE
1401 };
1402
1403 if (!trace) {
1404 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1405 ret = -1;
1406 goto end;
1407 }
1408
1409 if (!visitor) {
1410 BT_LOGW_STR("Invalid parameter: visitor is NULL.");
1411 ret = -1;
1412 goto end;
1413 }
1414
1415 BT_LOGV("Visiting trace: addr=%p, name=\"%s\"",
1416 trace, bt_ctf_trace_get_name(trace));
44c440bc 1417 ret = bt_ctf_visitor_helper(&obj, get_stream_class_count,
16ca5ff0
PP
1418 get_stream_class, visit_stream_class, visitor, data);
1419end:
1420 return ret;
1421}
3dca2276
PP
1422
1423static
1424void bt_ctf_trace_destroy(struct bt_object *obj)
1425{
1426 struct bt_ctf_trace *trace = (void *) obj;
1427
1428 BT_LOGD("Destroying CTF writer trace object: addr=%p, name=\"%s\"",
1429 trace, bt_ctf_trace_get_name(trace));
16ca5ff0 1430 bt_ctf_trace_common_finalize(BT_CTF_TO_COMMON(trace));
3dca2276
PP
1431 g_free(trace);
1432}
1433
1434BT_HIDDEN
1435struct bt_ctf_trace *bt_ctf_trace_create(void)
1436{
1437 struct bt_ctf_trace *trace = NULL;
1438 int ret;
1439
1440 BT_LOGD_STR("Creating CTF writer trace object.");
1441 trace = g_new0(struct bt_ctf_trace, 1);
1442 if (!trace) {
1443 BT_LOGE_STR("Failed to allocate one CTF writer trace.");
1444 goto error;
1445 }
1446
16ca5ff0 1447 ret = bt_ctf_trace_common_initialize(BT_CTF_TO_COMMON(trace),
3dca2276
PP
1448 bt_ctf_trace_destroy);
1449 if (ret) {
16ca5ff0 1450 /* bt_ctf_trace_common_initialize() logs errors */
3dca2276
PP
1451 goto error;
1452 }
1453
1454 BT_LOGD("Created CTF writer trace object: addr=%p", trace);
1455 return trace;
1456
1457error:
65300d60 1458 BT_OBJECT_PUT_REF_AND_RESET(trace);
3dca2276
PP
1459 return trace;
1460}
1461
1462const unsigned char *bt_ctf_trace_get_uuid(struct bt_ctf_trace *trace)
1463{
16ca5ff0 1464 return bt_ctf_trace_common_get_uuid(BT_CTF_TO_COMMON(trace));
3dca2276
PP
1465}
1466
1467int bt_ctf_trace_set_uuid(struct bt_ctf_trace *trace,
1468 const unsigned char *uuid)
1469{
16ca5ff0 1470 return bt_ctf_trace_common_set_uuid(BT_CTF_TO_COMMON(trace), uuid);
3dca2276
PP
1471}
1472
3dca2276
PP
1473int bt_ctf_trace_set_environment_field_string(struct bt_ctf_trace *trace,
1474 const char *name, const char *value)
1475{
16ca5ff0 1476 return bt_ctf_trace_common_set_environment_field_string(BT_CTF_TO_COMMON(trace),
3dca2276
PP
1477 name, value);
1478}
1479
1480int bt_ctf_trace_set_environment_field_integer(
1481 struct bt_ctf_trace *trace, const char *name, int64_t value)
1482{
16ca5ff0
PP
1483 return bt_ctf_trace_common_set_environment_field_integer(
1484 BT_CTF_TO_COMMON(trace), name, value);
3dca2276
PP
1485}
1486
1487int64_t bt_ctf_trace_get_environment_field_count(struct bt_ctf_trace *trace)
1488{
16ca5ff0 1489 return bt_ctf_trace_common_get_environment_field_count(BT_CTF_TO_COMMON(trace));
3dca2276
PP
1490}
1491
1492const char *
1493bt_ctf_trace_get_environment_field_name_by_index(struct bt_ctf_trace *trace,
1494 uint64_t index)
1495{
16ca5ff0
PP
1496 return bt_ctf_trace_common_get_environment_field_name_by_index(
1497 BT_CTF_TO_COMMON(trace), index);
3dca2276
PP
1498}
1499
1500struct bt_value *bt_ctf_trace_get_environment_field_value_by_index(
1501 struct bt_ctf_trace *trace, uint64_t index)
1502{
65300d60 1503 return bt_object_get_ref(bt_ctf_trace_common_borrow_environment_field_value_by_index(
16ca5ff0 1504 BT_CTF_TO_COMMON(trace), index));
3dca2276
PP
1505}
1506
1507struct bt_value *bt_ctf_trace_get_environment_field_value_by_name(
1508 struct bt_ctf_trace *trace, const char *name)
1509{
65300d60 1510 return bt_object_get_ref(bt_ctf_trace_common_borrow_environment_field_value_by_name(
16ca5ff0 1511 BT_CTF_TO_COMMON(trace), name));
3dca2276
PP
1512}
1513
16ca5ff0 1514BT_HIDDEN
3dca2276
PP
1515int bt_ctf_trace_add_clock_class(struct bt_ctf_trace *trace,
1516 struct bt_ctf_clock_class *clock_class)
1517{
16ca5ff0 1518 return bt_ctf_trace_common_add_clock_class(BT_CTF_TO_COMMON(trace),
3dca2276
PP
1519 (void *) clock_class);
1520}
1521
16ca5ff0 1522BT_HIDDEN
3dca2276
PP
1523int64_t bt_ctf_trace_get_clock_class_count(struct bt_ctf_trace *trace)
1524{
16ca5ff0 1525 return bt_ctf_trace_common_get_clock_class_count(BT_CTF_TO_COMMON(trace));
3dca2276
PP
1526}
1527
16ca5ff0 1528BT_HIDDEN
3dca2276
PP
1529struct bt_ctf_clock_class *bt_ctf_trace_get_clock_class_by_index(
1530 struct bt_ctf_trace *trace, uint64_t index)
1531{
65300d60 1532 return bt_object_get_ref(bt_ctf_trace_common_borrow_clock_class_by_index(
16ca5ff0 1533 BT_CTF_TO_COMMON(trace), index));
3dca2276
PP
1534}
1535
1536static
16ca5ff0
PP
1537int map_clock_classes_func(struct bt_ctf_stream_class_common *stream_class,
1538 struct bt_ctf_field_type_common *packet_context_type,
1539 struct bt_ctf_field_type_common *event_header_type)
3dca2276
PP
1540{
1541 int ret = bt_ctf_stream_class_map_clock_class(
16ca5ff0
PP
1542 BT_CTF_FROM_COMMON(stream_class),
1543 BT_CTF_FROM_COMMON(packet_context_type),
1544 BT_CTF_FROM_COMMON(event_header_type));
3dca2276
PP
1545
1546 if (ret) {
1547 BT_LOGW_STR("Cannot automatically map selected stream class's field types to stream class's clock's class.");
1548 }
1549
1550 return ret;
1551}
1552
1553int bt_ctf_trace_add_stream_class(struct bt_ctf_trace *trace,
1554 struct bt_ctf_stream_class *stream_class)
1555{
1556 int ret = 0;
16ca5ff0 1557 struct bt_ctf_clock_class *expected_clock_class = NULL;
3dca2276
PP
1558
1559 if (!trace) {
1560 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1561 ret = -1;
1562 goto end;
1563 }
1564
1565 if (!stream_class) {
1566 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
1567 ret = -1;
1568 goto end;
1569 }
1570
1571 if (stream_class->clock) {
1572 struct bt_ctf_clock_class *stream_clock_class =
1573 stream_class->clock->clock_class;
1574
1575 /*
1576 * Make sure this clock was also added to the
1577 * trace (potentially through its CTF writer
1578 * owner).
1579 */
1580 size_t i;
1581
1582 for (i = 0; i < trace->common.clock_classes->len; i++) {
1583 if (trace->common.clock_classes->pdata[i] ==
1584 stream_clock_class) {
1585 /* Found! */
1586 break;
1587 }
1588 }
1589
1590 if (i == trace->common.clock_classes->len) {
1591 /* Not found */
1592 BT_LOGW("Stream class's clock's class is not part of the trace: "
1593 "clock-class-addr=%p, clock-class-name=\"%s\"",
1594 stream_clock_class,
16ca5ff0 1595 bt_ctf_clock_class_get_name(stream_clock_class));
3dca2276
PP
1596 ret = -1;
1597 goto end;
1598 }
1599
1600 if (stream_class->common.clock_class &&
1601 stream_class->common.clock_class !=
16ca5ff0 1602 stream_class->clock->clock_class) {
3dca2276
PP
1603 /*
1604 * Stream class already has an expected clock
1605 * class, but it does not match its clock's
1606 * class.
1607 */
1608 BT_LOGW("Invalid parameter: stream class's clock's "
1609 "class does not match stream class's "
1610 "expected clock class: "
1611 "stream-class-addr=%p, "
1612 "stream-class-id=%" PRId64 ", "
1613 "stream-class-name=\"%s\", "
1614 "expected-clock-class-addr=%p, "
1615 "expected-clock-class-name=\"%s\"",
1616 stream_class,
1617 bt_ctf_stream_class_get_id(stream_class),
1618 bt_ctf_stream_class_get_name(stream_class),
1619 stream_class->common.clock_class,
16ca5ff0 1620 bt_ctf_clock_class_get_name(stream_class->common.clock_class));
3dca2276
PP
1621 } else if (!stream_class->common.clock_class) {
1622 /*
1623 * Set expected clock class to stream class's
1624 * clock's class.
1625 */
16ca5ff0 1626 expected_clock_class = stream_class->clock->clock_class;
3dca2276
PP
1627 }
1628 }
1629
1630
16ca5ff0
PP
1631 ret = bt_ctf_trace_common_add_stream_class(BT_CTF_TO_COMMON(trace),
1632 BT_CTF_TO_COMMON(stream_class),
1633 (bt_ctf_validation_flag_copy_field_type_func) bt_ctf_field_type_copy,
3dca2276
PP
1634 expected_clock_class, map_clock_classes_func,
1635 false);
1636
1637end:
1638 return ret;
1639}
1640
1641int64_t bt_ctf_trace_get_stream_count(struct bt_ctf_trace *trace)
1642{
16ca5ff0 1643 return bt_ctf_trace_common_get_stream_count(BT_CTF_TO_COMMON(trace));
3dca2276
PP
1644}
1645
1646struct bt_ctf_stream *bt_ctf_trace_get_stream_by_index(
1647 struct bt_ctf_trace *trace, uint64_t index)
1648{
65300d60 1649 return bt_object_get_ref(bt_ctf_trace_common_borrow_stream_by_index(
16ca5ff0 1650 BT_CTF_TO_COMMON(trace), index));
3dca2276
PP
1651}
1652
1653int64_t bt_ctf_trace_get_stream_class_count(struct bt_ctf_trace *trace)
1654{
16ca5ff0 1655 return bt_ctf_trace_common_get_stream_class_count(BT_CTF_TO_COMMON(trace));
3dca2276
PP
1656}
1657
1658struct bt_ctf_stream_class *bt_ctf_trace_get_stream_class_by_index(
1659 struct bt_ctf_trace *trace, uint64_t index)
1660{
65300d60 1661 return bt_object_get_ref(bt_ctf_trace_common_borrow_stream_class_by_index(
16ca5ff0 1662 BT_CTF_TO_COMMON(trace), index));
3dca2276
PP
1663}
1664
1665struct bt_ctf_stream_class *bt_ctf_trace_get_stream_class_by_id(
1666 struct bt_ctf_trace *trace, uint64_t id)
1667{
65300d60 1668 return bt_object_get_ref(bt_ctf_trace_common_borrow_stream_class_by_id(
16ca5ff0 1669 BT_CTF_TO_COMMON(trace), id));
3dca2276
PP
1670}
1671
16ca5ff0 1672BT_HIDDEN
3dca2276
PP
1673struct bt_ctf_clock_class *bt_ctf_trace_get_clock_class_by_name(
1674 struct bt_ctf_trace *trace, const char *name)
1675{
65300d60 1676 return bt_object_get_ref(
16ca5ff0 1677 bt_ctf_trace_common_borrow_clock_class_by_name(BT_CTF_TO_COMMON(trace),
3dca2276
PP
1678 name));
1679}
1680
1681static
1682int append_trace_metadata(struct bt_ctf_trace *trace,
1683 struct metadata_context *context)
1684{
1685 unsigned char *uuid = trace->common.uuid;
1686 int ret = 0;
1687
16ca5ff0
PP
1688 if (trace->common.native_byte_order == BT_CTF_BYTE_ORDER_NATIVE ||
1689 trace->common.native_byte_order == BT_CTF_BYTE_ORDER_UNSPECIFIED) {
3dca2276
PP
1690 BT_LOGW("Invalid parameter: trace's byte order cannot be BT_CTF_BYTE_ORDER_NATIVE or BT_CTF_BYTE_ORDER_UNSPECIFIED at this point; "
1691 "set it with bt_ctf_trace_set_native_byte_order(): "
1692 "addr=%p, name=\"%s\"",
1693 trace, bt_ctf_trace_get_name(trace));
1694 ret = -1;
1695 goto end;
1696 }
1697
1698 g_string_append(context->string, "trace {\n");
1699 g_string_append(context->string, "\tmajor = 1;\n");
1700 g_string_append(context->string, "\tminor = 8;\n");
16ca5ff0
PP
1701 BT_ASSERT(trace->common.native_byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN ||
1702 trace->common.native_byte_order == BT_CTF_BYTE_ORDER_BIG_ENDIAN ||
1703 trace->common.native_byte_order == BT_CTF_BYTE_ORDER_NETWORK);
3dca2276
PP
1704
1705 if (trace->common.uuid_set) {
1706 g_string_append_printf(context->string,
1707 "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
1708 uuid[0], uuid[1], uuid[2], uuid[3],
1709 uuid[4], uuid[5], uuid[6], uuid[7],
1710 uuid[8], uuid[9], uuid[10], uuid[11],
1711 uuid[12], uuid[13], uuid[14], uuid[15]);
1712 }
1713
1714 g_string_append_printf(context->string, "\tbyte_order = %s;\n",
16ca5ff0 1715 bt_ctf_get_byte_order_string(trace->common.native_byte_order));
3dca2276
PP
1716
1717 if (trace->common.packet_header_field_type) {
1718 g_string_append(context->string, "\tpacket.header := ");
1719 context->current_indentation_level++;
1720 g_string_assign(context->field_name, "");
1721 BT_LOGD_STR("Serializing trace's packet header field type's metadata.");
1722 ret = bt_ctf_field_type_serialize_recursive(
1723 (void *) trace->common.packet_header_field_type,
1724 context);
1725 if (ret) {
1726 goto end;
1727 }
1728 context->current_indentation_level--;
1729 }
1730
1731 g_string_append(context->string, ";\n};\n\n");
1732end:
1733 return ret;
1734}
1735
1736static
1737void append_env_metadata(struct bt_ctf_trace *trace,
1738 struct metadata_context *context)
1739{
1740 int64_t i;
1741 int64_t env_size;
1742
16ca5ff0 1743 env_size = bt_ctf_attributes_get_count(trace->common.environment);
3dca2276
PP
1744 if (env_size <= 0) {
1745 return;
1746 }
1747
1748 g_string_append(context->string, "env {\n");
1749
1750 for (i = 0; i < env_size; i++) {
da91b29a 1751 struct bt_private_value *env_field_value_obj = NULL;
3dca2276
PP
1752 const char *entry_name;
1753
16ca5ff0 1754 entry_name = bt_ctf_attributes_get_field_name(
3dca2276 1755 trace->common.environment, i);
16ca5ff0 1756 env_field_value_obj = bt_ctf_attributes_borrow_field_value(
3dca2276
PP
1757 trace->common.environment, i);
1758
1759 BT_ASSERT(entry_name);
1760 BT_ASSERT(env_field_value_obj);
1761
da91b29a 1762 switch (bt_value_get_type(
707b7d35 1763 bt_private_value_as_value(env_field_value_obj))) {
3dca2276
PP
1764 case BT_VALUE_TYPE_INTEGER:
1765 {
3dca2276
PP
1766 int64_t int_value;
1767
601b0d3c 1768 int_value = bt_value_integer_get(
707b7d35 1769 bt_private_value_as_value(
601b0d3c 1770 env_field_value_obj));
3dca2276
PP
1771 g_string_append_printf(context->string,
1772 "\t%s = %" PRId64 ";\n", entry_name,
1773 int_value);
1774 break;
1775 }
1776 case BT_VALUE_TYPE_STRING:
1777 {
3dca2276
PP
1778 const char *str_value;
1779 char *escaped_str = NULL;
1780
601b0d3c 1781 str_value = bt_value_string_get(
707b7d35 1782 bt_private_value_as_value(
601b0d3c 1783 env_field_value_obj));
3dca2276
PP
1784 escaped_str = g_strescape(str_value, NULL);
1785 if (!escaped_str) {
1786 BT_LOGE("Cannot escape string: string=\"%s\"",
1787 str_value);
094ff7c0 1788 continue;
3dca2276
PP
1789 }
1790
1791 g_string_append_printf(context->string,
1792 "\t%s = \"%s\";\n", entry_name, escaped_str);
1793 free(escaped_str);
1794 break;
1795 }
1796 default:
094ff7c0 1797 continue;
3dca2276 1798 }
3dca2276
PP
1799 }
1800
1801 g_string_append(context->string, "};\n\n");
1802}
1803
1804char *bt_ctf_trace_get_metadata_string(struct bt_ctf_trace *trace)
1805{
1806 char *metadata = NULL;
1807 struct metadata_context *context = NULL;
1808 int err = 0;
1809 size_t i;
1810
1811 if (!trace) {
1812 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1813 goto end;
1814 }
1815
1816 context = g_new0(struct metadata_context, 1);
1817 if (!context) {
1818 BT_LOGE_STR("Failed to allocate one metadata context.");
1819 goto end;
1820 }
1821
1822 context->field_name = g_string_sized_new(DEFAULT_IDENTIFIER_SIZE);
1823 context->string = g_string_sized_new(DEFAULT_METADATA_STRING_SIZE);
1824 g_string_append(context->string, "/* CTF 1.8 */\n\n");
1825 if (append_trace_metadata(trace, context)) {
1826 /* append_trace_metadata() logs errors */
1827 goto error;
1828 }
1829 append_env_metadata(trace, context);
1830 g_ptr_array_foreach(trace->common.clock_classes,
1831 (GFunc) bt_ctf_clock_class_serialize, context);
1832
1833 for (i = 0; i < trace->common.stream_classes->len; i++) {
16ca5ff0 1834 /* bt_ctf_stream_class_serialize() logs details */
3dca2276
PP
1835 err = bt_ctf_stream_class_serialize(
1836 trace->common.stream_classes->pdata[i], context);
1837 if (err) {
16ca5ff0 1838 /* bt_ctf_stream_class_serialize() logs errors */
3dca2276
PP
1839 goto error;
1840 }
1841 }
1842
1843 metadata = context->string->str;
1844
1845error:
1846 g_string_free(context->string, err ? TRUE : FALSE);
1847 g_string_free(context->field_name, TRUE);
1848 g_free(context);
1849
1850end:
1851 return metadata;
1852}
1853
1854enum bt_ctf_byte_order bt_ctf_trace_get_native_byte_order(
1855 struct bt_ctf_trace *trace)
1856{
16ca5ff0 1857 return (int) bt_ctf_trace_common_get_native_byte_order(BT_CTF_TO_COMMON(trace));
3dca2276
PP
1858}
1859
1860int bt_ctf_trace_set_native_byte_order(struct bt_ctf_trace *trace,
1861 enum bt_ctf_byte_order byte_order)
1862{
16ca5ff0 1863 return bt_ctf_trace_common_set_native_byte_order(BT_CTF_TO_COMMON(trace),
3dca2276
PP
1864 (int) byte_order, false);
1865}
1866
1867struct bt_ctf_field_type *bt_ctf_trace_get_packet_header_field_type(
1868 struct bt_ctf_trace *trace)
1869{
65300d60 1870 return bt_object_get_ref(bt_ctf_trace_common_borrow_packet_header_field_type(
16ca5ff0 1871 BT_CTF_TO_COMMON(trace)));
3dca2276
PP
1872}
1873
1874int bt_ctf_trace_set_packet_header_field_type(struct bt_ctf_trace *trace,
1875 struct bt_ctf_field_type *packet_header_type)
1876{
16ca5ff0 1877 return bt_ctf_trace_common_set_packet_header_field_type(BT_CTF_TO_COMMON(trace),
3dca2276
PP
1878 (void *) packet_header_type);
1879}
1880
1881const char *bt_ctf_trace_get_name(struct bt_ctf_trace *trace)
1882{
16ca5ff0 1883 return bt_ctf_trace_common_get_name(BT_CTF_TO_COMMON(trace));
3dca2276 1884}
This page took 0.100007 seconds and 4 git commands to generate.