ir: add BT_CTF_BYTE_ORDER_NONE and make it the default trace's native BO
[babeltrace.git] / lib / ctf-ir / trace.c
CommitLineData
bc37ae52
JG
1/*
2 * trace.c
3 *
4 * Babeltrace CTF IR - Trace
5 *
6 * Copyright 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 *
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
e011d2c1
PP
29#define BT_LOG_TAG "TRACE"
30#include <babeltrace/lib-logging-internal.h>
31
bc37ae52 32#include <babeltrace/ctf-ir/trace-internal.h>
ac0c6bdd 33#include <babeltrace/ctf-ir/clock-class-internal.h>
bc37ae52
JG
34#include <babeltrace/ctf-ir/stream-internal.h>
35#include <babeltrace/ctf-ir/stream-class-internal.h>
09840de5 36#include <babeltrace/ctf-ir/event-internal.h>
272df73e
PP
37#include <babeltrace/ctf-ir/event-class.h>
38#include <babeltrace/ctf-ir/event-class-internal.h>
bc37ae52 39#include <babeltrace/ctf-writer/functor-internal.h>
ac0c6bdd 40#include <babeltrace/ctf-writer/clock-internal.h>
2e33ac5a 41#include <babeltrace/ctf-ir/field-types-internal.h>
44e0a4f5 42#include <babeltrace/ctf-ir/attributes-internal.h>
09840de5 43#include <babeltrace/ctf-ir/validation-internal.h>
8bf65fbd 44#include <babeltrace/ctf-ir/visitor-internal.h>
654c1444 45#include <babeltrace/ctf-ir/utils.h>
3d9990ac 46#include <babeltrace/compiler-internal.h>
dac5c838 47#include <babeltrace/values.h>
95c09b3a 48#include <babeltrace/values-internal.h>
83509119 49#include <babeltrace/ref.h>
c55a9f58 50#include <babeltrace/types.h>
3d9990ac 51#include <babeltrace/endian-internal.h>
dc3fffef 52#include <inttypes.h>
544d0515 53#include <stdint.h>
4a32fda0 54#include <string.h>
0fbb9a9f 55#include <stdlib.h>
bc37ae52
JG
56
57#define DEFAULT_IDENTIFIER_SIZE 128
58#define DEFAULT_METADATA_STRING_SIZE 4096
59
50ad4244
JG
60struct listener_wrapper {
61 bt_ctf_listener_cb listener;
2204c381
JG
62 void *data;
63};
64
3602afb0
PP
65struct bt_ctf_trace_is_static_listener_elem {
66 bt_ctf_trace_is_static_listener func;
67 void *data;
68};
69
bc37ae52 70static
83509119 71void bt_ctf_trace_destroy(struct bt_object *obj);
bc37ae52 72static
09840de5 73void bt_ctf_trace_freeze(struct bt_ctf_trace *trace);
bc37ae52 74
bc37ae52
JG
75static
76const unsigned int field_type_aliases_alignments[] = {
77 [FIELD_TYPE_ALIAS_UINT5_T] = 1,
78 [FIELD_TYPE_ALIAS_UINT8_T ... FIELD_TYPE_ALIAS_UINT16_T] = 8,
79 [FIELD_TYPE_ALIAS_UINT27_T] = 1,
80 [FIELD_TYPE_ALIAS_UINT32_T ... FIELD_TYPE_ALIAS_UINT64_T] = 8,
81};
82
83static
84const unsigned int field_type_aliases_sizes[] = {
85 [FIELD_TYPE_ALIAS_UINT5_T] = 5,
86 [FIELD_TYPE_ALIAS_UINT8_T] = 8,
87 [FIELD_TYPE_ALIAS_UINT16_T] = 16,
88 [FIELD_TYPE_ALIAS_UINT27_T] = 27,
89 [FIELD_TYPE_ALIAS_UINT32_T] = 32,
90 [FIELD_TYPE_ALIAS_UINT64_T] = 64,
91};
92
bc37ae52
JG
93struct bt_ctf_trace *bt_ctf_trace_create(void)
94{
95 struct bt_ctf_trace *trace = NULL;
488e09a7 96 struct bt_ctf_field_type *packet_header_type = NULL;
bc37ae52
JG
97
98 trace = g_new0(struct bt_ctf_trace, 1);
99 if (!trace) {
95c09b3a 100 BT_LOGE_STR("Failed to allocate one trace.");
bc37ae52
JG
101 goto error;
102 }
103
95c09b3a 104 BT_LOGD_STR("Creating trace object.");
d41cff38 105 trace->native_byte_order = BT_CTF_BYTE_ORDER_NONE;
83509119 106 bt_object_init(trace, bt_ctf_trace_destroy);
bc37ae52 107 trace->clocks = g_ptr_array_new_with_free_func(
83509119 108 (GDestroyNotify) bt_put);
95c09b3a
PP
109 if (!trace->clocks) {
110 BT_LOGE_STR("Failed to allocate one GPtrArray.");
111 goto error;
112 }
113
bc37ae52 114 trace->streams = g_ptr_array_new_with_free_func(
e6a8e8e4 115 (GDestroyNotify) bt_object_release);
95c09b3a
PP
116 if (!trace->streams) {
117 BT_LOGE_STR("Failed to allocate one GPtrArray.");
118 goto error;
119 }
120
bc37ae52 121 trace->stream_classes = g_ptr_array_new_with_free_func(
e6a8e8e4 122 (GDestroyNotify) bt_object_release);
95c09b3a
PP
123 if (!trace->stream_classes) {
124 BT_LOGE_STR("Failed to allocate one GPtrArray.");
83509119 125 goto error;
bc37ae52
JG
126 }
127
488e09a7
PP
128 packet_header_type = bt_ctf_field_type_structure_create();
129 if (!packet_header_type) {
83509119 130 goto error;
bc37ae52
JG
131 }
132
488e09a7
PP
133 BT_MOVE(trace->packet_header_type, packet_header_type);
134
7f800dc7
PP
135 /* Create the environment array object */
136 trace->environment = bt_ctf_attributes_create();
137 if (!trace->environment) {
95c09b3a 138 BT_LOGE_STR("Cannot create empty attributes object.");
83509119 139 goto error;
7f800dc7
PP
140 }
141
9b888ff3
JG
142 trace->listeners = g_ptr_array_new_with_free_func(
143 (GDestroyNotify) g_free);
144 if (!trace->listeners) {
95c09b3a 145 BT_LOGE_STR("Failed to allocate one GPtrArray.");
9b888ff3
JG
146 goto error;
147 }
148
3602afb0
PP
149 trace->is_static_listeners = g_array_new(FALSE, TRUE,
150 sizeof(struct bt_ctf_trace_is_static_listener_elem));
151 if (!trace->is_static_listeners) {
152 BT_LOGE_STR("Failed to allocate one GArray.");
153 goto error;
154 }
155
95c09b3a 156 BT_LOGD("Created trace object: addr=%p", trace);
bc37ae52
JG
157 return trace;
158
bc37ae52 159error:
83509119 160 BT_PUT(trace);
488e09a7 161 bt_put(packet_header_type);
bc37ae52
JG
162 return trace;
163}
164
e96045d4
JG
165const char *bt_ctf_trace_get_name(struct bt_ctf_trace *trace)
166{
167 const char *name = NULL;
168
95c09b3a
PP
169 if (!trace) {
170 BT_LOGW_STR("Invalid parameter: trace is NULL.");
171 goto end;
172 }
173
174 if (!trace->name) {
e96045d4
JG
175 goto end;
176 }
177
178 name = trace->name->str;
179end:
180 return name;
181}
182
183int bt_ctf_trace_set_name(struct bt_ctf_trace *trace, const char *name)
184{
185 int ret = 0;
186
95c09b3a
PP
187 if (!trace) {
188 BT_LOGW_STR("Invalid parameter: trace is NULL.");
189 ret = -1;
190 goto end;
191 }
192
193 if (!name) {
194 BT_LOGW_STR("Invalid parameter: name is NULL.");
195 ret = -1;
196 goto end;
197 }
198
199 if (trace->frozen) {
200 BT_LOGW("Invalid parameter: trace is frozen: "
201 "addr=%p, name=\"%s\"",
202 trace, bt_ctf_trace_get_name(trace));
e96045d4
JG
203 ret = -1;
204 goto end;
205 }
206
207 trace->name = trace->name ? g_string_assign(trace->name, name) :
208 g_string_new(name);
209 if (!trace->name) {
95c09b3a 210 BT_LOGE_STR("Failed to allocate one GString.");
e96045d4
JG
211 ret = -1;
212 goto end;
213 }
95c09b3a
PP
214
215 BT_LOGV("Set trace's name: addr=%p, name=\"%s\"", trace, name);
216
e96045d4
JG
217end:
218 return ret;
219}
220
4a32fda0
PP
221const unsigned char *bt_ctf_trace_get_uuid(struct bt_ctf_trace *trace)
222{
223 return trace && trace->uuid_set ? trace->uuid : NULL;
224}
225
226int bt_ctf_trace_set_uuid(struct bt_ctf_trace *trace, const unsigned char *uuid)
227{
228 int ret = 0;
229
95c09b3a
PP
230 if (!trace) {
231 BT_LOGW_STR("Invalid parameter: trace is NULL.");
232 ret = -1;
233 goto end;
234 }
235
236 if (!uuid) {
237 BT_LOGW_STR("Invalid parameter: UUID is NULL.");
238 ret = -1;
239 goto end;
240 }
241
242 if (trace->frozen) {
243 BT_LOGW("Invalid parameter: trace is frozen: "
244 "addr=%p, name=\"%s\"",
245 trace, bt_ctf_trace_get_name(trace));
4a32fda0
PP
246 ret = -1;
247 goto end;
248 }
249
250 memcpy(trace->uuid, uuid, sizeof(uuid_t));
c55a9f58 251 trace->uuid_set = BT_TRUE;
95c09b3a
PP
252 BT_LOGV("Set trace's UUID: addr=%p, name=\"%s\", "
253 "uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\"",
254 trace, bt_ctf_trace_get_name(trace),
255 (unsigned int) uuid[0],
256 (unsigned int) uuid[1],
257 (unsigned int) uuid[2],
258 (unsigned int) uuid[3],
259 (unsigned int) uuid[4],
260 (unsigned int) uuid[5],
261 (unsigned int) uuid[6],
262 (unsigned int) uuid[7],
263 (unsigned int) uuid[8],
264 (unsigned int) uuid[9],
265 (unsigned int) uuid[10],
266 (unsigned int) uuid[11],
267 (unsigned int) uuid[12],
268 (unsigned int) uuid[13],
269 (unsigned int) uuid[14],
270 (unsigned int) uuid[15]);
4a32fda0
PP
271
272end:
273 return ret;
274}
275
83509119 276void bt_ctf_trace_destroy(struct bt_object *obj)
bc37ae52
JG
277{
278 struct bt_ctf_trace *trace;
bc37ae52 279
83509119 280 trace = container_of(obj, struct bt_ctf_trace, base);
95c09b3a
PP
281
282 BT_LOGD("Destroying trace object: addr=%p, name=\"%s\"",
283 trace, bt_ctf_trace_get_name(trace));
284
bc37ae52 285 if (trace->environment) {
95c09b3a 286 BT_LOGD_STR("Destroying environment attributes.");
7f800dc7 287 bt_ctf_attributes_destroy(trace->environment);
bc37ae52
JG
288 }
289
e96045d4
JG
290 if (trace->name) {
291 g_string_free(trace->name, TRUE);
292 }
293
bc37ae52 294 if (trace->clocks) {
95c09b3a 295 BT_LOGD_STR("Putting clock classes.");
bc37ae52
JG
296 g_ptr_array_free(trace->clocks, TRUE);
297 }
298
299 if (trace->streams) {
607ff9b8 300 BT_LOGD_STR("Destroying streams.");
bc37ae52
JG
301 g_ptr_array_free(trace->streams, TRUE);
302 }
303
304 if (trace->stream_classes) {
607ff9b8 305 BT_LOGD_STR("Destroying stream classes.");
bc37ae52
JG
306 g_ptr_array_free(trace->stream_classes, TRUE);
307 }
308
9b888ff3
JG
309 if (trace->listeners) {
310 g_ptr_array_free(trace->listeners, TRUE);
311 }
312
3602afb0
PP
313 if (trace->is_static_listeners) {
314 g_array_free(trace->is_static_listeners, TRUE);
315 }
316
95c09b3a 317 BT_LOGD_STR("Putting packet header field type.");
83509119 318 bt_put(trace->packet_header_type);
bc37ae52
JG
319 g_free(trace);
320}
321
7f800dc7 322int bt_ctf_trace_set_environment_field(struct bt_ctf_trace *trace,
dac5c838 323 const char *name, struct bt_value *value)
bc37ae52 324{
bc37ae52
JG
325 int ret = 0;
326
95c09b3a
PP
327 if (!trace) {
328 BT_LOGW_STR("Invalid parameter: trace is NULL.");
329 ret = -1;
330 goto end;
331 }
332
333 if (!name) {
334 BT_LOGW_STR("Invalid parameter: name is NULL.");
335 ret = -1;
336 goto end;
337 }
338
339 if (!value) {
340 BT_LOGW_STR("Invalid parameter: value is NULL.");
341 ret = -1;
342 goto end;
343 }
344
345 if (bt_ctf_validate_identifier(name)) {
346 BT_LOGW("Invalid parameter: environment field's name is not a valid CTF identifier: "
347 "trace-addr=%p, trace-name=\"%s\", "
348 "env-name=\"%s\"",
349 trace, bt_ctf_trace_get_name(trace), name);
bc37ae52 350 ret = -1;
7f800dc7 351 goto end;
bc37ae52
JG
352 }
353
95c09b3a
PP
354 if (!bt_value_is_integer(value) && !bt_value_is_string(value)) {
355 BT_LOGW("Invalid parameter: environment field's value is not an integer or string value: "
356 "trace-addr=%p, trace-name=\"%s\", "
357 "env-name=\"%s\", env-value-type=%s",
358 trace, bt_ctf_trace_get_name(trace), name,
359 bt_value_type_string(bt_value_get_type(value)));
360 ret = -1;
361 goto end;
362 }
363
364 if (trace->is_static) {
365 BT_LOGW("Invalid parameter: trace is static: "
366 "addr=%p, name=\"%s\"",
367 trace, bt_ctf_trace_get_name(trace));
bc37ae52 368 ret = -1;
7f800dc7 369 goto end;
bc37ae52
JG
370 }
371
a0d12916
JG
372 if (trace->frozen) {
373 /*
374 * New environment fields may be added to a frozen trace,
375 * but existing fields may not be changed.
376 *
377 * The object passed is frozen like all other attributes.
378 */
dac5c838 379 struct bt_value *attribute =
a0d12916
JG
380 bt_ctf_attributes_get_field_value_by_name(
381 trace->environment, name);
382
383 if (attribute) {
95c09b3a
PP
384 BT_LOGW("Invalid parameter: trace is frozen and environment field already exists with this name: "
385 "trace-addr=%p, trace-name=\"%s\", "
386 "env-name=\"%s\"",
387 trace, bt_ctf_trace_get_name(trace), name);
83509119 388 BT_PUT(attribute);
a0d12916
JG
389 ret = -1;
390 goto end;
391 }
392
dac5c838 393 bt_value_freeze(value);
a0d12916
JG
394 }
395
7f800dc7
PP
396 ret = bt_ctf_attributes_set_field_value(trace->environment, name,
397 value);
95c09b3a
PP
398 if (ret) {
399 BT_LOGE("Cannot set environment field's value: "
400 "trace-addr=%p, trace-name=\"%s\", "
401 "env-name=\"%s\"",
402 trace, bt_ctf_trace_get_name(trace), name);
403 } else {
404 BT_LOGV("Set environment field's value: "
405 "trace-addr=%p, trace-name=\"%s\", "
406 "env-name=\"%s\", value-addr=%p",
407 trace, bt_ctf_trace_get_name(trace), name, value);
408 }
bc37ae52 409
7f800dc7
PP
410end:
411 return ret;
412}
bc37ae52 413
7f800dc7
PP
414int bt_ctf_trace_set_environment_field_string(struct bt_ctf_trace *trace,
415 const char *name, const char *value)
416{
417 int ret = 0;
dac5c838 418 struct bt_value *env_value_string_obj = NULL;
7f800dc7 419
95c09b3a
PP
420 if (!value) {
421 BT_LOGW_STR("Invalid parameter: value is NULL.");
bc37ae52 422 ret = -1;
7f800dc7 423 goto end;
bc37ae52
JG
424 }
425
dac5c838 426 env_value_string_obj = bt_value_string_create_init(value);
7f800dc7 427 if (!env_value_string_obj) {
95c09b3a 428 BT_LOGE_STR("Cannot create string value object.");
7f800dc7
PP
429 ret = -1;
430 goto end;
bc37ae52
JG
431 }
432
95c09b3a 433 /* bt_ctf_trace_set_environment_field() logs errors */
7f800dc7
PP
434 ret = bt_ctf_trace_set_environment_field(trace, name,
435 env_value_string_obj);
436
437end:
95c09b3a 438 bt_put(env_value_string_obj);
3487c9f3
JG
439 return ret;
440}
441
7f800dc7
PP
442int bt_ctf_trace_set_environment_field_integer(struct bt_ctf_trace *trace,
443 const char *name, int64_t value)
3487c9f3 444{
3487c9f3 445 int ret = 0;
dac5c838 446 struct bt_value *env_value_integer_obj = NULL;
3487c9f3 447
dac5c838 448 env_value_integer_obj = bt_value_integer_create_init(value);
7f800dc7 449 if (!env_value_integer_obj) {
95c09b3a 450 BT_LOGE_STR("Cannot create integer value object.");
3487c9f3 451 ret = -1;
7f800dc7 452 goto end;
3487c9f3
JG
453 }
454
95c09b3a 455 /* bt_ctf_trace_set_environment_field() logs errors */
7f800dc7
PP
456 ret = bt_ctf_trace_set_environment_field(trace, name,
457 env_value_integer_obj);
95c09b3a 458
7f800dc7 459end:
95c09b3a 460 bt_put(env_value_integer_obj);
bc37ae52
JG
461 return ret;
462}
463
544d0515 464int64_t bt_ctf_trace_get_environment_field_count(struct bt_ctf_trace *trace)
e6fa2160 465{
544d0515 466 int64_t ret = 0;
e6fa2160
JG
467
468 if (!trace) {
95c09b3a 469 BT_LOGW_STR("Invalid parameter: trace is NULL.");
9ac68eb1 470 ret = (int64_t) -1;
e6fa2160
JG
471 goto end;
472 }
473
7f800dc7 474 ret = bt_ctf_attributes_get_count(trace->environment);
95c09b3a 475 assert(ret >= 0);
e6fa2160 476
e6fa2160 477end:
7f800dc7 478 return ret;
e6fa2160
JG
479}
480
481const char *
9ac68eb1
PP
482bt_ctf_trace_get_environment_field_name_by_index(struct bt_ctf_trace *trace,
483 uint64_t index)
e6fa2160 484{
e6fa2160
JG
485 const char *ret = NULL;
486
7f800dc7 487 if (!trace) {
95c09b3a 488 BT_LOGW_STR("Invalid parameter: trace is NULL.");
e6fa2160
JG
489 goto end;
490 }
491
7f800dc7
PP
492 ret = bt_ctf_attributes_get_field_name(trace->environment, index);
493
e6fa2160
JG
494end:
495 return ret;
496}
497
9ac68eb1
PP
498struct bt_value *bt_ctf_trace_get_environment_field_value_by_index(
499 struct bt_ctf_trace *trace, uint64_t index)
e6fa2160 500{
dac5c838 501 struct bt_value *ret = NULL;
e6fa2160 502
7f800dc7 503 if (!trace) {
95c09b3a 504 BT_LOGW_STR("Invalid parameter: trace is NULL.");
e6fa2160
JG
505 goto end;
506 }
507
7f800dc7
PP
508 ret = bt_ctf_attributes_get_field_value(trace->environment, index);
509
e6fa2160
JG
510end:
511 return ret;
512}
513
dac5c838 514struct bt_value *bt_ctf_trace_get_environment_field_value_by_name(
7f800dc7 515 struct bt_ctf_trace *trace, const char *name)
e6fa2160 516{
dac5c838 517 struct bt_value *ret = NULL;
e6fa2160 518
95c09b3a
PP
519 if (!trace) {
520 BT_LOGW_STR("Invalid parameter: trace is NULL.");
521 goto end;
522 }
523
524 if (!name) {
525 BT_LOGW_STR("Invalid parameter: name is NULL.");
e6fa2160
JG
526 goto end;
527 }
528
7f800dc7
PP
529 ret = bt_ctf_attributes_get_field_value_by_name(trace->environment,
530 name);
531
e6fa2160
JG
532end:
533 return ret;
534}
535
ac0c6bdd
PP
536int bt_ctf_trace_add_clock_class(struct bt_ctf_trace *trace,
537 struct bt_ctf_clock_class *clock_class)
bc37ae52
JG
538{
539 int ret = 0;
bc37ae52 540
95c09b3a
PP
541 if (!trace) {
542 BT_LOGW_STR("Invalid parameter: trace is NULL.");
543 ret = -1;
544 goto end;
545 }
546
547 if (trace->is_static) {
548 BT_LOGW("Invalid parameter: trace is static: "
549 "addr=%p, name=\"%s\"",
550 trace, bt_ctf_trace_get_name(trace));
551 ret = -1;
552 goto end;
553 }
554
555 if (!bt_ctf_clock_class_is_valid(clock_class)) {
556 BT_LOGW("Invalid parameter: clock class is invalid: "
557 "trace-addr=%p, trace-name=\"%s\", "
558 "clock-class-addr=%p, clock-class-name=\"%s\"",
559 trace, bt_ctf_trace_get_name(trace),
560 clock_class, bt_ctf_clock_class_get_name(clock_class));
bc37ae52
JG
561 ret = -1;
562 goto end;
563 }
564
ac0c6bdd 565 /* Check for duplicate clock classes */
c9d90a34 566 if (bt_ctf_trace_has_clock_class(trace, clock_class)) {
95c09b3a
PP
567 BT_LOGW("Invalid parameter: clock class already exists in trace: "
568 "trace-addr=%p, trace-name=\"%s\", "
569 "clock-class-addr=%p, clock-class-name=\"%s\"",
570 trace, bt_ctf_trace_get_name(trace),
571 clock_class, bt_ctf_clock_class_get_name(clock_class));
bc37ae52
JG
572 ret = -1;
573 goto end;
574 }
575
ac0c6bdd
PP
576 bt_get(clock_class);
577 g_ptr_array_add(trace->clocks, clock_class);
cfeb617e 578
6474e016 579 if (trace->frozen) {
95c09b3a 580 BT_LOGV_STR("Freezing added clock class because trace is frozen.");
ac0c6bdd 581 bt_ctf_clock_class_freeze(clock_class);
6474e016 582 }
95c09b3a
PP
583
584 BT_LOGV("Added clock class to trace: "
585 "trace-addr=%p, trace-name=\"%s\", "
586 "clock-class-addr=%p, clock-class-name=\"%s\"",
587 trace, bt_ctf_trace_get_name(trace),
588 clock_class, bt_ctf_clock_class_get_name(clock_class));
589
bc37ae52
JG
590end:
591 return ret;
592}
593
544d0515 594int64_t bt_ctf_trace_get_clock_class_count(struct bt_ctf_trace *trace)
884cd6c3 595{
9ac68eb1 596 int64_t ret = (int64_t) -1;
884cd6c3
JG
597
598 if (!trace) {
95c09b3a 599 BT_LOGW_STR("Invalid parameter: trace is NULL.");
884cd6c3
JG
600 goto end;
601 }
602
603 ret = trace->clocks->len;
604end:
605 return ret;
606}
607
9ac68eb1
PP
608struct bt_ctf_clock_class *bt_ctf_trace_get_clock_class_by_index(
609 struct bt_ctf_trace *trace, uint64_t index)
884cd6c3 610{
ac0c6bdd 611 struct bt_ctf_clock_class *clock_class = NULL;
884cd6c3 612
95c09b3a
PP
613 if (!trace) {
614 BT_LOGW_STR("Invalid parameter: trace is NULL.");
615 goto end;
616 }
617
618 if (index >= trace->clocks->len) {
619 BT_LOGW("Invalid parameter: index is out of bounds: "
620 "addr=%p, name=\"%s\", "
621 "index=%" PRIu64 ", count=%u",
622 trace, bt_ctf_trace_get_name(trace),
623 index, trace->clocks->len);
884cd6c3
JG
624 goto end;
625 }
626
ac0c6bdd
PP
627 clock_class = g_ptr_array_index(trace->clocks, index);
628 bt_get(clock_class);
884cd6c3 629end:
ac0c6bdd 630 return clock_class;
884cd6c3
JG
631}
632
e011d2c1
PP
633static
634bool packet_header_field_type_is_valid(struct bt_ctf_trace *trace,
635 struct bt_ctf_field_type *packet_header_type)
636{
637 int ret;
638 bool is_valid = true;
639 struct bt_ctf_field_type *field_type = NULL;
640
641 if (!packet_header_type) {
642 /*
643 * No packet header field type: trace must have only
644 * one stream. At this point the stream class being
645 * added is not part of the trace yet, so we validate
646 * that the trace contains no stream classes yet.
647 */
648 if (trace->stream_classes->len >= 1) {
649 BT_LOGW_STR("Invalid packet header field type: "
650 "packet header field type does not exist but there's more than one stream class in the trace.");
651 goto invalid;
652 }
653
654 /* No packet header field type: valid at this point */
655 goto end;
656 }
657
658 /* Packet header field type, if it exists, must be a structure */
659 if (!bt_ctf_field_type_is_structure(packet_header_type)) {
660 BT_LOGW("Invalid packet header field type: must be a structure field type if it exists: "
661 "ft-addr=%p, ft-id=%s",
662 packet_header_type,
663 bt_ctf_field_type_id_string(packet_header_type->id));
664 goto invalid;
665 }
666
667 /*
668 * If there's a `magic` field, it must be a 32-bit unsigned
669 * integer field type. Also it must be the first field of the
670 * packet header field type.
671 */
672 field_type = bt_ctf_field_type_structure_get_field_type_by_name(
673 packet_header_type, "magic");
674 if (field_type) {
675 const char *field_name;
676
677 if (!bt_ctf_field_type_is_integer(field_type)) {
678 BT_LOGW("Invalid packet header field type: `magic` field must be an integer field type: "
679 "magic-ft-addr=%p, magic-ft-id=%s",
680 field_type,
681 bt_ctf_field_type_id_string(field_type->id));
682 goto invalid;
683 }
684
685 if (bt_ctf_field_type_integer_is_signed(field_type)) {
686 BT_LOGW("Invalid packet header field type: `magic` field must be an unsigned integer field type: "
687 "magic-ft-addr=%p", field_type);
688 goto invalid;
689 }
690
691 if (bt_ctf_field_type_integer_get_size(field_type) != 32) {
692 BT_LOGW("Invalid packet header field type: `magic` field must be a 32-bit unsigned integer field type: "
693 "magic-ft-addr=%p, magic-ft-size=%u",
694 field_type,
695 bt_ctf_field_type_integer_get_size(field_type));
696 goto invalid;
697 }
698
699 ret = bt_ctf_field_type_structure_get_field_by_index(
700 packet_header_type, &field_name, NULL, 0);
701 assert(ret == 0);
702
703 if (strcmp(field_name, "magic") != 0) {
704 BT_LOGW("Invalid packet header field type: `magic` field must be the first field: "
705 "magic-ft-addr=%p, first-field-name=\"%s\"",
706 field_type, field_name);
707 goto invalid;
708 }
709
710 BT_PUT(field_type);
711 }
712
713 /*
714 * If there's a `uuid` field, it must be an array field type of
715 * length 16 with an 8-bit unsigned integer element field type.
716 */
717 field_type = bt_ctf_field_type_structure_get_field_type_by_name(
718 packet_header_type, "uuid");
719 if (field_type) {
720 struct bt_ctf_field_type *elem_ft;
721
722 if (!bt_ctf_field_type_is_array(field_type)) {
723 BT_LOGW("Invalid packet header field type: `uuid` field must be an array field type: "
724 "uuid-ft-addr=%p, uuid-ft-id=%s",
725 field_type,
726 bt_ctf_field_type_id_string(field_type->id));
727 goto invalid;
728 }
729
730 if (bt_ctf_field_type_array_get_length(field_type) != 16) {
731 BT_LOGW("Invalid packet header field type: `uuid` array field type's length must be 16: "
732 "uuid-ft-addr=%p, uuid-ft-length=%" PRId64,
733 field_type,
734 bt_ctf_field_type_array_get_length(field_type));
735 goto invalid;
736 }
737
738 elem_ft = bt_ctf_field_type_array_get_element_type(field_type);
739 assert(elem_ft);
740
741 if (!bt_ctf_field_type_is_integer(elem_ft)) {
742 BT_LOGW("Invalid packet header field type: `uuid` field's element field type must be an integer field type: "
743 "elem-ft-addr=%p, elem-ft-id=%s",
744 elem_ft,
745 bt_ctf_field_type_id_string(elem_ft->id));
746 bt_put(elem_ft);
747 goto invalid;
748 }
749
750 if (bt_ctf_field_type_integer_is_signed(elem_ft)) {
751 BT_LOGW("Invalid packet header field type: `uuid` field's element field type must be an unsigned integer field type: "
752 "elem-ft-addr=%p", elem_ft);
753 bt_put(elem_ft);
754 goto invalid;
755 }
756
757 if (bt_ctf_field_type_integer_get_size(elem_ft) != 8) {
758 BT_LOGW("Invalid packet header field type: `uuid` field's element field type must be an 8-bit unsigned integer field type: "
759 "elem-ft-addr=%p, elem-ft-size=%u",
760 elem_ft,
761 bt_ctf_field_type_integer_get_size(elem_ft));
762 bt_put(elem_ft);
763 goto invalid;
764 }
765
766 bt_put(elem_ft);
767 BT_PUT(field_type);
768 }
769
770 /*
771 * The `stream_id` field must exist if there's more than one
772 * stream classes in the trace.
773 */
774 field_type = bt_ctf_field_type_structure_get_field_type_by_name(
775 packet_header_type, "stream_id");
776
777 if (!field_type && trace->stream_classes->len >= 1) {
778 BT_LOGW_STR("Invalid packet header field type: "
779 "`stream_id` field does not exist but there's more than one stream class in the trace.");
780 goto invalid;
781 }
782
783 /*
784 * If there's a `stream_id` field, it must be an unsigned
785 * integer field type.
786 */
787 if (field_type) {
788 if (!bt_ctf_field_type_is_integer(field_type)) {
789 BT_LOGW("Invalid packet header field type: `stream_id` field must be an integer field type: "
790 "stream-id-ft-addr=%p, stream-id-ft-id=%s",
791 field_type,
792 bt_ctf_field_type_id_string(field_type->id));
793 goto invalid;
794 }
795
796 if (bt_ctf_field_type_integer_is_signed(field_type)) {
797 BT_LOGW("Invalid packet header field type: `stream_id` field must be an unsigned integer field type: "
798 "stream-id-ft-addr=%p", field_type);
799 goto invalid;
800 }
801
802 BT_PUT(field_type);
803 }
804
805 goto end;
806
807invalid:
808 is_valid = false;
809
810end:
811 bt_put(field_type);
812 return is_valid;
813}
814
815static
816bool packet_context_field_type_is_valid(struct bt_ctf_trace *trace,
817 struct bt_ctf_stream_class *stream_class,
818 struct bt_ctf_field_type *packet_context_type)
819{
820 bool is_valid = true;
821 struct bt_ctf_field_type *field_type = NULL;
822
823 if (!packet_context_type) {
824 /* No packet context field type: valid at this point */
825 goto end;
826 }
827
828 /* Packet context field type, if it exists, must be a structure */
829 if (!bt_ctf_field_type_is_structure(packet_context_type)) {
830 BT_LOGW("Invalid packet context field type: must be a structure field type if it exists: "
831 "ft-addr=%p, ft-id=%s",
832 packet_context_type,
833 bt_ctf_field_type_id_string(packet_context_type->id));
834 goto invalid;
835 }
836
837 /*
838 * If there's a `packet_size` field, it must be an unsigned
839 * integer field type.
840 */
841 field_type = bt_ctf_field_type_structure_get_field_type_by_name(
842 packet_context_type, "packet_size");
843 if (field_type) {
844 if (!bt_ctf_field_type_is_integer(field_type)) {
845 BT_LOGW("Invalid packet context field type: `packet_size` field must be an integer field type: "
846 "packet-size-ft-addr=%p, packet-size-ft-id=%s",
847 field_type,
848 bt_ctf_field_type_id_string(field_type->id));
849 goto invalid;
850 }
851
852 if (bt_ctf_field_type_integer_is_signed(field_type)) {
853 BT_LOGW("Invalid packet context field type: `packet_size` field must be an unsigned integer field type: "
854 "packet-size-ft-addr=%p", field_type);
855 goto invalid;
856 }
857
858 BT_PUT(field_type);
859 }
860
861 /*
862 * If there's a `content_size` field, it must be an unsigned
863 * integer field type.
864 */
865 field_type = bt_ctf_field_type_structure_get_field_type_by_name(
866 packet_context_type, "content_size");
867 if (field_type) {
868 if (!bt_ctf_field_type_is_integer(field_type)) {
869 BT_LOGW("Invalid packet context field type: `content_size` field must be an integer field type: "
870 "content-size-ft-addr=%p, content-size-ft-id=%s",
871 field_type,
872 bt_ctf_field_type_id_string(field_type->id));
873 goto invalid;
874 }
875
876 if (bt_ctf_field_type_integer_is_signed(field_type)) {
877 BT_LOGW("Invalid packet context field type: `content_size` field must be an unsigned integer field type: "
878 "content-size-ft-addr=%p", field_type);
879 goto invalid;
880 }
881
882 BT_PUT(field_type);
883 }
884
885 /*
886 * If there's a `events_discarded` field, it must be an unsigned
887 * integer field type.
888 */
889 field_type = bt_ctf_field_type_structure_get_field_type_by_name(
890 packet_context_type, "events_discarded");
891 if (field_type) {
892 if (!bt_ctf_field_type_is_integer(field_type)) {
893 BT_LOGW("Invalid packet context field type: `events_discarded` field must be an integer field type: "
894 "events-discarded-ft-addr=%p, events-discarded-ft-id=%s",
895 field_type,
896 bt_ctf_field_type_id_string(field_type->id));
897 goto invalid;
898 }
899
900 if (bt_ctf_field_type_integer_is_signed(field_type)) {
901 BT_LOGW("Invalid packet context field type: `events_discarded` field must be an unsigned integer field type: "
902 "events-discarded-ft-addr=%p", field_type);
903 goto invalid;
904 }
905
906 BT_PUT(field_type);
907 }
908
909 /*
910 * If there's a `timestamp_begin` field, it must be an unsigned
911 * integer field type. Also, if the trace is not a CTF writer's
912 * trace, then we cannot automatically set the mapped clock
913 * class of this field, so it must have a mapped clock class.
914 */
915 field_type = bt_ctf_field_type_structure_get_field_type_by_name(
916 packet_context_type, "timestamp_begin");
917 if (field_type) {
918 if (!bt_ctf_field_type_is_integer(field_type)) {
919 BT_LOGW("Invalid packet context field type: `timestamp_begin` field must be an integer field type: "
920 "timestamp-begin-ft-addr=%p, timestamp-begin-ft-id=%s",
921 field_type,
922 bt_ctf_field_type_id_string(field_type->id));
923 goto invalid;
924 }
925
926 if (bt_ctf_field_type_integer_is_signed(field_type)) {
927 BT_LOGW("Invalid packet context field type: `timestamp_begin` field must be an unsigned integer field type: "
928 "timestamp-begin-ft-addr=%p", field_type);
929 goto invalid;
930 }
931
932 if (!trace->is_created_by_writer) {
933 struct bt_ctf_clock_class *clock_class =
934 bt_ctf_field_type_integer_get_mapped_clock_class(
935 field_type);
936
937 bt_put(clock_class);
938 if (!clock_class) {
939 BT_LOGW("Invalid packet context field type: `timestamp_begin` field must be mapped to a clock class: "
940 "timestamp-begin-ft-addr=%p", field_type);
941 goto invalid;
942 }
943 }
944
945 BT_PUT(field_type);
946 }
947
948 /*
949 * If there's a `timestamp_end` field, it must be an unsigned
950 * integer field type. Also, if the trace is not a CTF writer's
951 * trace, then we cannot automatically set the mapped clock
952 * class of this field, so it must have a mapped clock class.
953 */
954 field_type = bt_ctf_field_type_structure_get_field_type_by_name(
955 packet_context_type, "timestamp_end");
956 if (field_type) {
957 if (!bt_ctf_field_type_is_integer(field_type)) {
958 BT_LOGW("Invalid packet context field type: `timestamp_end` field must be an integer field type: "
959 "timestamp-end-ft-addr=%p, timestamp-end-ft-id=%s",
960 field_type,
961 bt_ctf_field_type_id_string(field_type->id));
962 goto invalid;
963 }
964
965 if (bt_ctf_field_type_integer_is_signed(field_type)) {
966 BT_LOGW("Invalid packet context field type: `timestamp_end` field must be an unsigned integer field type: "
967 "timestamp-end-ft-addr=%p", field_type);
968 goto invalid;
969 }
970
971 if (!trace->is_created_by_writer) {
972 struct bt_ctf_clock_class *clock_class =
973 bt_ctf_field_type_integer_get_mapped_clock_class(
974 field_type);
975
976 bt_put(clock_class);
977 if (!clock_class) {
978 BT_LOGW("Invalid packet context field type: `timestamp_end` field must be mapped to a clock class: "
979 "timestamp-end-ft-addr=%p", field_type);
980 goto invalid;
981 }
982 }
983
984 BT_PUT(field_type);
985 }
986
987 goto end;
988
989invalid:
990 is_valid = false;
991
992end:
993 bt_put(field_type);
994 return is_valid;
995}
996
997static
998bool event_header_field_type_is_valid(struct bt_ctf_trace *trace,
999 struct bt_ctf_stream_class *stream_class,
1000 struct bt_ctf_field_type *event_header_type)
1001{
1002 bool is_valid = true;
1003 struct bt_ctf_field_type *field_type = NULL;
1004
1005 /*
1006 * We do not validate that the `timestamp` field exists here
1007 * because CTF does not require this exact name to be mapped to
1008 * a clock class.
1009 */
1010
1011 if (!event_header_type) {
1012 /*
1013 * No event header field type: stream class must have
1014 * only one event class.
1015 */
1016 if (bt_ctf_stream_class_get_event_class_count(stream_class) > 1) {
1017 BT_LOGW_STR("Invalid event header field type: "
1018 "event header field type does not exist but there's more than one event class in the stream class.");
1019 goto invalid;
1020 }
1021
1022 /* No event header field type: valid at this point */
1023 goto end;
1024 }
1025
1026 /* Event header field type, if it exists, must be a structure */
1027 if (!bt_ctf_field_type_is_structure(event_header_type)) {
1028 BT_LOGW("Invalid event header field type: must be a structure field type if it exists: "
1029 "ft-addr=%p, ft-id=%s",
1030 event_header_type,
1031 bt_ctf_field_type_id_string(event_header_type->id));
1032 goto invalid;
1033 }
1034
1035 /*
1036 * If there's an `id` field, it must be an unsigned integer
1037 * field type or an enumeration field type with an unsigned
1038 * integer container field type.
1039 */
1040 field_type = bt_ctf_field_type_structure_get_field_type_by_name(
1041 event_header_type, "id");
1042 if (field_type) {
1043 struct bt_ctf_field_type *int_ft;
1044
1045 if (bt_ctf_field_type_is_integer(field_type)) {
1046 int_ft = bt_get(field_type);
1047 } else if (bt_ctf_field_type_is_enumeration(field_type)) {
1048 int_ft = bt_ctf_field_type_enumeration_get_container_type(
1049 field_type);
1050 } else {
1051 BT_LOGW("Invalid event header field type: `id` field must be an integer or enumeration field type: "
1052 "id-ft-addr=%p, id-ft-id=%s",
1053 field_type,
1054 bt_ctf_field_type_id_string(field_type->id));
1055 goto invalid;
1056 }
1057
1058 assert(int_ft);
1059 if (bt_ctf_field_type_integer_is_signed(int_ft)) {
1060 BT_LOGW("Invalid event header field type: `id` field must be an unsigned integer or enumeration field type: "
1061 "id-ft-addr=%p", int_ft);
1062 goto invalid;
1063 }
1064
1065 bt_put(int_ft);
1066 BT_PUT(field_type);
1067 }
1068
1069 goto end;
1070
1071invalid:
1072 is_valid = false;
1073
1074end:
1075 bt_put(field_type);
1076 return is_valid;
1077}
1078
ef0c4a15
JG
1079int bt_ctf_trace_add_stream_class(struct bt_ctf_trace *trace,
1080 struct bt_ctf_stream_class *stream_class)
1081{
544d0515
PP
1082 int ret;
1083 int64_t i;
ef0c4a15 1084 int64_t stream_id;
09840de5
PP
1085 struct bt_ctf_validation_output trace_sc_validation_output = { 0 };
1086 struct bt_ctf_validation_output *ec_validation_outputs = NULL;
1087 const enum bt_ctf_validation_flag trace_sc_validation_flags =
1088 BT_CTF_VALIDATION_FLAG_TRACE |
1089 BT_CTF_VALIDATION_FLAG_STREAM;
1090 const enum bt_ctf_validation_flag ec_validation_flags =
1091 BT_CTF_VALIDATION_FLAG_EVENT;
1092 struct bt_ctf_field_type *packet_header_type = NULL;
1093 struct bt_ctf_field_type *packet_context_type = NULL;
1094 struct bt_ctf_field_type *event_header_type = NULL;
1095 struct bt_ctf_field_type *stream_event_ctx_type = NULL;
544d0515 1096 int64_t event_class_count;
2789e5d9 1097 struct bt_ctf_trace *current_parent_trace = NULL;
ef0c4a15 1098
95c09b3a
PP
1099 if (!trace) {
1100 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1101 ret = -1;
1102 goto end;
1103 }
1104
1105 if (!stream_class) {
1106 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
1107 ret = -1;
1108 goto end;
1109 }
1110
1111 if (trace->is_static) {
1112 BT_LOGW_STR("Invalid parameter: trace is static.");
ef0c4a15
JG
1113 ret = -1;
1114 goto end;
1115 }
1116
95c09b3a
PP
1117 BT_LOGD("Adding stream class to trace: "
1118 "trace-addr=%p, trace-name=\"%s\", "
1119 "stream-class-addr=%p, stream-class-name=\"%s\", "
1120 "stream-class-id=%" PRId64,
1121 trace, bt_ctf_trace_get_name(trace),
1122 stream_class, bt_ctf_stream_class_get_name(stream_class),
1123 bt_ctf_stream_class_get_id(stream_class));
1124
2789e5d9
JG
1125 current_parent_trace = bt_ctf_stream_class_get_trace(stream_class);
1126 if (current_parent_trace) {
1127 /* Stream class is already associated to a trace, abort. */
95c09b3a
PP
1128 BT_LOGW("Invalid parameter: stream class is already part of a trace: "
1129 "stream-class-trace-addr=%p, "
1130 "stream-class-trace-name=\"%s\"",
1131 current_parent_trace,
1132 bt_ctf_trace_get_name(current_parent_trace));
2789e5d9
JG
1133 ret = -1;
1134 goto end;
1135 }
1136
09840de5
PP
1137 event_class_count =
1138 bt_ctf_stream_class_get_event_class_count(stream_class);
1139 assert(event_class_count >= 0);
1140
fe13b5c0 1141 if (stream_class->clock) {
ac0c6bdd
PP
1142 struct bt_ctf_clock_class *stream_clock_class =
1143 stream_class->clock->clock_class;
1144
1145 if (trace->is_created_by_writer) {
1146 /*
1147 * Make sure this clock was also added to the
1148 * trace (potentially through its CTF writer
1149 * owner).
1150 */
1151 size_t i;
1152
1153 for (i = 0; i < trace->clocks->len; i++) {
1154 if (trace->clocks->pdata[i] ==
1155 stream_clock_class) {
1156 /* Found! */
1157 break;
1158 }
1159 }
1160
1161 if (i == trace->clocks->len) {
1162 /* Not found */
95c09b3a
PP
1163 BT_LOGW("Stream class's clock's class is not part of the trace: "
1164 "clock-class-addr=%p, clock-class-name=\"%s\"",
1165 stream_clock_class,
1166 bt_ctf_clock_class_get_name(stream_clock_class));
fe13b5c0
PP
1167 ret = -1;
1168 goto end;
1169 }
1170 } else {
ac0c6bdd
PP
1171 /*
1172 * This trace was NOT created by a CTF writer,
1173 * thus do not allow the stream class to add to
1174 * have a clock at all. Those are two
1175 * independent APIs (non-writer and writer
1176 * APIs), and isolating them simplifies things.
1177 */
95c09b3a
PP
1178 BT_LOGW("Cannot add stream class with a clock to a trace which was not created by a CTF writer object: "
1179 "clock-class-addr=%p, clock-class-name=\"%s\"",
1180 stream_clock_class,
1181 bt_ctf_clock_class_get_name(stream_clock_class));
ac0c6bdd
PP
1182 ret = -1;
1183 goto end;
fe13b5c0
PP
1184 }
1185 }
1186
09840de5
PP
1187 /*
1188 * We're about to freeze both the trace and the stream class.
1189 * Also, each event class contained in this stream class are
1190 * already frozen.
1191 *
1192 * This trace, this stream class, and all its event classes
1193 * should be valid at this point.
1194 *
1195 * Validate trace and stream class first, then each event
1196 * class of this stream class can be validated individually.
1197 */
1198 packet_header_type =
1199 bt_ctf_trace_get_packet_header_type(trace);
1200 packet_context_type =
1201 bt_ctf_stream_class_get_packet_context_type(stream_class);
1202 event_header_type =
1203 bt_ctf_stream_class_get_event_header_type(stream_class);
1204 stream_event_ctx_type =
1205 bt_ctf_stream_class_get_event_context_type(stream_class);
95c09b3a
PP
1206
1207 BT_LOGD("Validating trace and stream class field types.");
09840de5
PP
1208 ret = bt_ctf_validate_class_types(trace->environment,
1209 packet_header_type, packet_context_type, event_header_type,
1210 stream_event_ctx_type, NULL, NULL, trace->valid,
1211 stream_class->valid, 1, &trace_sc_validation_output,
1212 trace_sc_validation_flags);
1213 BT_PUT(packet_header_type);
1214 BT_PUT(packet_context_type);
1215 BT_PUT(event_header_type);
1216 BT_PUT(stream_event_ctx_type);
1217
2bd7f864 1218 if (ret) {
09840de5
PP
1219 /*
1220 * This means something went wrong during the validation
1221 * process, not that the objects are invalid.
1222 */
95c09b3a
PP
1223 BT_LOGE("Failed to validate trace and stream class field types: "
1224 "ret=%d", ret);
2bd7f864
JG
1225 goto end;
1226 }
1227
09840de5
PP
1228 if ((trace_sc_validation_output.valid_flags &
1229 trace_sc_validation_flags) !=
1230 trace_sc_validation_flags) {
1231 /* Invalid trace/stream class */
95c09b3a
PP
1232 BT_LOGW("Invalid trace or stream class field types: "
1233 "valid-flags=0x%x",
1234 trace_sc_validation_output.valid_flags);
09840de5
PP
1235 ret = -1;
1236 goto end;
1237 }
1238
1239 if (event_class_count > 0) {
1240 ec_validation_outputs = g_new0(struct bt_ctf_validation_output,
1241 event_class_count);
1242 if (!ec_validation_outputs) {
95c09b3a 1243 BT_LOGE_STR("Failed to allocate one validation output structure.");
09840de5
PP
1244 ret = -1;
1245 goto end;
1246 }
1247 }
1248
1249 /* Validate each event class individually */
6474e016 1250 for (i = 0; i < event_class_count; i++) {
09840de5 1251 struct bt_ctf_event_class *event_class =
9ac68eb1
PP
1252 bt_ctf_stream_class_get_event_class_by_index(
1253 stream_class, i);
09840de5
PP
1254 struct bt_ctf_field_type *event_context_type = NULL;
1255 struct bt_ctf_field_type *event_payload_type = NULL;
1256
1257 event_context_type =
1258 bt_ctf_event_class_get_context_type(event_class);
1259 event_payload_type =
1260 bt_ctf_event_class_get_payload_type(event_class);
1261
1262 /*
1263 * It is important to use the field types returned by
1264 * the previous trace and stream class validation here
1265 * because copies could have been made.
1266 */
95c09b3a
PP
1267 BT_LOGD("Validating event class's field types: "
1268 "addr=%p, name=\"%s\", id=%" PRId64,
1269 event_class, bt_ctf_event_class_get_name(event_class),
1270 bt_ctf_event_class_get_id(event_class));
09840de5
PP
1271 ret = bt_ctf_validate_class_types(trace->environment,
1272 trace_sc_validation_output.packet_header_type,
1273 trace_sc_validation_output.packet_context_type,
1274 trace_sc_validation_output.event_header_type,
1275 trace_sc_validation_output.stream_event_ctx_type,
1276 event_context_type, event_payload_type,
1277 1, 1, event_class->valid, &ec_validation_outputs[i],
1278 ec_validation_flags);
1279 BT_PUT(event_context_type);
1280 BT_PUT(event_payload_type);
1281 BT_PUT(event_class);
1282
1283 if (ret) {
95c09b3a
PP
1284 BT_LOGE("Failed to validate event class field types: "
1285 "ret=%d", ret);
09840de5
PP
1286 goto end;
1287 }
1288
1289 if ((ec_validation_outputs[i].valid_flags &
1290 ec_validation_flags) != ec_validation_flags) {
1291 /* Invalid event class */
95c09b3a
PP
1292 BT_LOGW("Invalid event class field types: "
1293 "valid-flags=0x%x",
1294 ec_validation_outputs[i].valid_flags);
09840de5
PP
1295 ret = -1;
1296 goto end;
1297 }
1298 }
1299
ef0c4a15
JG
1300 stream_id = bt_ctf_stream_class_get_id(stream_class);
1301 if (stream_id < 0) {
1302 stream_id = trace->next_stream_id++;
9ac68eb1 1303 if (stream_id < 0) {
95c09b3a 1304 BT_LOGE_STR("No more stream class IDs available.");
9ac68eb1
PP
1305 ret = -1;
1306 goto end;
1307 }
ef0c4a15
JG
1308
1309 /* Try to assign a new stream id */
1310 for (i = 0; i < trace->stream_classes->len; i++) {
1311 if (stream_id == bt_ctf_stream_class_get_id(
1312 trace->stream_classes->pdata[i])) {
1313 /* Duplicate stream id found */
95c09b3a
PP
1314 BT_LOGW("Duplicate stream class ID: "
1315 "id=%" PRId64, (int64_t) stream_id);
ef0c4a15
JG
1316 ret = -1;
1317 goto end;
1318 }
1319 }
1320
0ddffae5 1321 if (bt_ctf_stream_class_set_id_no_check(stream_class,
95c09b3a 1322 stream_id)) {
ef0c4a15 1323 /* TODO Should retry with a different stream id */
95c09b3a
PP
1324 BT_LOGE("Cannot set stream class's ID: "
1325 "id=%" PRId64, (int64_t) stream_id);
ef0c4a15
JG
1326 ret = -1;
1327 goto end;
1328 }
1329 }
1330
e011d2c1
PP
1331 /*
1332 * At this point all the field types in the validation output
1333 * are valid. Validate the semantics of some scopes according to
1334 * the CTF specification.
1335 */
1336 if (!packet_header_field_type_is_valid(trace,
1337 trace_sc_validation_output.packet_header_type)) {
95c09b3a 1338 BT_LOGW_STR("Invalid trace's packet header field type.");
e011d2c1
PP
1339 ret = -1;
1340 goto end;
1341 }
1342
1343 if (!packet_context_field_type_is_valid(trace,
1344 stream_class,
1345 trace_sc_validation_output.packet_context_type)) {
95c09b3a 1346 BT_LOGW_STR("Invalid stream class's packet context field type.");
e011d2c1
PP
1347 ret = -1;
1348 goto end;
1349 }
1350
1351 if (!event_header_field_type_is_valid(trace,
1352 stream_class,
1353 trace_sc_validation_output.event_header_type)) {
95c09b3a 1354 BT_LOGW_STR("Invalid steam class's event header field type.");
e011d2c1
PP
1355 ret = -1;
1356 goto end;
1357 }
1358
1359 /*
1360 * Now is the time to automatically map specific field types of
1361 * the stream class's packet context and event header field
1362 * types to the stream class's clock's class if they are not
1363 * mapped to a clock class yet. We do it here because we know
1364 * that after this point, everything is frozen so it won't be
1365 * possible for the user to modify the stream class's clock, or
1366 * to map those field types to other clock classes.
1367 */
1368 if (trace->is_created_by_writer) {
1369 if (bt_ctf_stream_class_map_clock_class(stream_class,
1370 trace_sc_validation_output.packet_context_type,
1371 trace_sc_validation_output.event_header_type)) {
95c09b3a 1372 BT_LOGW_STR("Cannot automatically map selected stream class's field types to stream class's clock's class.");
e011d2c1
PP
1373 ret = -1;
1374 goto end;
1375 }
1376 }
1377
e6a8e8e4 1378 bt_object_set_parent(stream_class, trace);
ef0c4a15
JG
1379 g_ptr_array_add(trace->stream_classes, stream_class);
1380
1381 /*
09840de5
PP
1382 * At this point we know that the function will be successful.
1383 * Therefore we can replace the trace and stream class field
1384 * types with what's in their validation output structure and
1385 * mark them as valid. We can also replace the field types of
1386 * all the event classes of the stream class and mark them as
1387 * valid.
1388 */
1389 bt_ctf_validation_replace_types(trace, stream_class, NULL,
1390 &trace_sc_validation_output, trace_sc_validation_flags);
1391 trace->valid = 1;
1392 stream_class->valid = 1;
1393
1394 /*
1395 * Put what was not moved in bt_ctf_validation_replace_types().
1396 */
1397 bt_ctf_validation_output_put_types(&trace_sc_validation_output);
1398
6474e016 1399 for (i = 0; i < event_class_count; i++) {
09840de5 1400 struct bt_ctf_event_class *event_class =
9ac68eb1
PP
1401 bt_ctf_stream_class_get_event_class_by_index(
1402 stream_class, i);
09840de5
PP
1403
1404 bt_ctf_validation_replace_types(NULL, NULL, event_class,
1405 &ec_validation_outputs[i], ec_validation_flags);
1406 event_class->valid = 1;
1407 BT_PUT(event_class);
1408
1409 /*
1410 * Put what was not moved in
1411 * bt_ctf_validation_replace_types().
1412 */
1413 bt_ctf_validation_output_put_types(&ec_validation_outputs[i]);
1414 }
1415
09840de5
PP
1416 /*
1417 * Freeze the trace and the stream class.
1418 */
f67f3a6e 1419 bt_ctf_stream_class_freeze(stream_class);
09840de5
PP
1420 bt_ctf_trace_freeze(trace);
1421
9b888ff3
JG
1422 /* Notifiy listeners of the trace's schema modification. */
1423 bt_ctf_stream_class_visit(stream_class,
d9a13d86 1424 bt_ctf_trace_object_modification, trace);
95c09b3a
PP
1425 BT_LOGD("Added stream class to trace: "
1426 "trace-addr=%p, trace-name=\"%s\", "
1427 "stream-class-addr=%p, stream-class-name=\"%s\", "
1428 "stream-class-id=%" PRId64,
1429 trace, bt_ctf_trace_get_name(trace),
1430 stream_class, bt_ctf_stream_class_get_name(stream_class),
1431 bt_ctf_stream_class_get_id(stream_class));
1432
ef0c4a15 1433end:
d3814b54 1434 if (ret) {
e6a8e8e4 1435 bt_object_set_parent(stream_class, NULL);
09840de5
PP
1436
1437 if (ec_validation_outputs) {
6474e016 1438 for (i = 0; i < event_class_count; i++) {
09840de5
PP
1439 bt_ctf_validation_output_put_types(
1440 &ec_validation_outputs[i]);
1441 }
1442 }
d3814b54 1443 }
09840de5
PP
1444
1445 g_free(ec_validation_outputs);
1446 bt_ctf_validation_output_put_types(&trace_sc_validation_output);
2789e5d9 1447 bt_put(current_parent_trace);
09840de5
PP
1448 assert(!packet_header_type);
1449 assert(!packet_context_type);
1450 assert(!event_header_type);
1451 assert(!stream_event_ctx_type);
ef0c4a15
JG
1452 return ret;
1453}
1454
544d0515 1455int64_t bt_ctf_trace_get_stream_count(struct bt_ctf_trace *trace)
c1e730fe 1456{
544d0515 1457 int64_t ret;
c1e730fe
PP
1458
1459 if (!trace) {
95c09b3a 1460 BT_LOGW_STR("Invalid parameter: trace is NULL.");
9ac68eb1 1461 ret = (int64_t) -1;
c1e730fe
PP
1462 goto end;
1463 }
1464
9ac68eb1 1465 ret = (int64_t) trace->streams->len;
c1e730fe
PP
1466
1467end:
1468 return ret;
1469}
1470
9ac68eb1
PP
1471struct bt_ctf_stream *bt_ctf_trace_get_stream_by_index(
1472 struct bt_ctf_trace *trace,
1473 uint64_t index)
c1e730fe
PP
1474{
1475 struct bt_ctf_stream *stream = NULL;
1476
95c09b3a
PP
1477 if (!trace) {
1478 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1479 goto end;
1480 }
1481
1482 if (index >= trace->streams->len) {
1483 BT_LOGW("Invalid parameter: index is out of bounds: "
1484 "addr=%p, name=\"%s\", "
1485 "index=%" PRIu64 ", count=%u",
1486 trace, bt_ctf_trace_get_name(trace),
1487 index, trace->streams->len);
c1e730fe
PP
1488 goto end;
1489 }
1490
1491 stream = bt_get(g_ptr_array_index(trace->streams, index));
1492
1493end:
1494 return stream;
1495}
1496
544d0515 1497int64_t bt_ctf_trace_get_stream_class_count(struct bt_ctf_trace *trace)
ef0c4a15 1498{
544d0515 1499 int64_t ret;
ef0c4a15
JG
1500
1501 if (!trace) {
95c09b3a 1502 BT_LOGW_STR("Invalid parameter: trace is NULL.");
9ac68eb1 1503 ret = (int64_t) -1;
ef0c4a15
JG
1504 goto end;
1505 }
1506
9ac68eb1 1507 ret = (int64_t) trace->stream_classes->len;
ef0c4a15
JG
1508end:
1509 return ret;
1510}
1511
9ac68eb1
PP
1512struct bt_ctf_stream_class *bt_ctf_trace_get_stream_class_by_index(
1513 struct bt_ctf_trace *trace, uint64_t index)
ef0c4a15
JG
1514{
1515 struct bt_ctf_stream_class *stream_class = NULL;
1516
95c09b3a
PP
1517 if (!trace) {
1518 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1519 goto end;
1520 }
1521
1522 if (index >= trace->stream_classes->len) {
1523 BT_LOGW("Invalid parameter: index is out of bounds: "
1524 "addr=%p, name=\"%s\", "
1525 "index=%" PRIu64 ", count=%u",
1526 trace, bt_ctf_trace_get_name(trace),
1527 index, trace->stream_classes->len);
ef0c4a15
JG
1528 goto end;
1529 }
1530
1531 stream_class = g_ptr_array_index(trace->stream_classes, index);
83509119 1532 bt_get(stream_class);
ef0c4a15
JG
1533end:
1534 return stream_class;
1535}
1536
4841ccc1 1537struct bt_ctf_stream_class *bt_ctf_trace_get_stream_class_by_id(
9ac68eb1 1538 struct bt_ctf_trace *trace, uint64_t id_param)
4841ccc1
PP
1539{
1540 int i;
1541 struct bt_ctf_stream_class *stream_class = NULL;
9ac68eb1 1542 int64_t id = (int64_t) id_param;
4841ccc1 1543
95c09b3a
PP
1544 if (!trace) {
1545 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1546 goto end;
1547 }
1548
1549 if (id < 0) {
1550 BT_LOGW("Invalid parameter: invalid stream class's ID: "
1551 "trace-addr=%p, trace-name=\"%s\", id=%" PRIu64,
1552 trace, bt_ctf_trace_get_name(trace), id_param);
4841ccc1
PP
1553 goto end;
1554 }
1555
6474e016 1556 for (i = 0; i < trace->stream_classes->len; i++) {
4841ccc1
PP
1557 struct bt_ctf_stream_class *stream_class_candidate;
1558
1559 stream_class_candidate =
1560 g_ptr_array_index(trace->stream_classes, i);
1561
1562 if (bt_ctf_stream_class_get_id(stream_class_candidate) ==
1563 (int64_t) id) {
1564 stream_class = stream_class_candidate;
83509119 1565 bt_get(stream_class);
4841ccc1
PP
1566 goto end;
1567 }
1568 }
1569
1570end:
1571 return stream_class;
1572}
1573
ac0c6bdd 1574struct bt_ctf_clock_class *bt_ctf_trace_get_clock_class_by_name(
7e4347a3
PP
1575 struct bt_ctf_trace *trace, const char *name)
1576{
1577 size_t i;
ac0c6bdd 1578 struct bt_ctf_clock_class *clock_class = NULL;
7e4347a3 1579
95c09b3a
PP
1580 if (!trace) {
1581 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1582 goto end;
1583 }
1584
1585 if (!name) {
1586 BT_LOGW_STR("Invalid parameter: name is NULL.");
7e4347a3
PP
1587 goto end;
1588 }
1589
6474e016 1590 for (i = 0; i < trace->clocks->len; i++) {
ac0c6bdd 1591 struct bt_ctf_clock_class *cur_clk =
7e4347a3 1592 g_ptr_array_index(trace->clocks, i);
ac0c6bdd 1593 const char *cur_clk_name = bt_ctf_clock_class_get_name(cur_clk);
7e4347a3
PP
1594
1595 if (!cur_clk_name) {
1596 goto end;
1597 }
1598
1599 if (!strcmp(cur_clk_name, name)) {
ac0c6bdd
PP
1600 clock_class = cur_clk;
1601 bt_get(clock_class);
7e4347a3
PP
1602 goto end;
1603 }
1604 }
1605
1606end:
ac0c6bdd 1607 return clock_class;
7e4347a3
PP
1608}
1609
c9d90a34 1610BT_HIDDEN
c55a9f58 1611bt_bool bt_ctf_trace_has_clock_class(struct bt_ctf_trace *trace,
c9d90a34
PP
1612 struct bt_ctf_clock_class *clock_class)
1613{
1614 struct search_query query = { .value = clock_class, .found = 0 };
1615
1616 assert(trace);
1617 assert(clock_class);
1618
1619 g_ptr_array_foreach(trace->clocks, value_exists, &query);
1620 return query.found;
1621}
1622
bc37ae52 1623BT_HIDDEN
dc3fffef 1624const char *get_byte_order_string(enum bt_ctf_byte_order byte_order)
bc37ae52
JG
1625{
1626 const char *string;
1627
1628 switch (byte_order) {
dc3fffef 1629 case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN:
bc37ae52
JG
1630 string = "le";
1631 break;
dc3fffef 1632 case BT_CTF_BYTE_ORDER_BIG_ENDIAN:
bc37ae52
JG
1633 string = "be";
1634 break;
dc3fffef
PP
1635 case BT_CTF_BYTE_ORDER_NATIVE:
1636 string = "native";
bc37ae52 1637 break;
dc3fffef 1638 default:
0fbb9a9f 1639 abort();
bc37ae52
JG
1640 }
1641
1642 return string;
1643}
1644
1645static
1646int append_trace_metadata(struct bt_ctf_trace *trace,
1647 struct metadata_context *context)
1648{
1649 unsigned char *uuid = trace->uuid;
e011d2c1 1650 int ret = 0;
bc37ae52 1651
d41cff38
PP
1652 if (trace->native_byte_order == BT_CTF_BYTE_ORDER_NATIVE ||
1653 trace->native_byte_order == BT_CTF_BYTE_ORDER_NONE) {
1654 BT_LOGW("Invalid parameter: trace's byte order cannot be BT_CTF_BYTE_ORDER_NATIVE or BT_CTF_BYTE_ORDER_NONE at this point; "
95c09b3a
PP
1655 "set it with bt_ctf_trace_set_native_byte_order(): "
1656 "addr=%p, name=\"%s\"",
1657 trace, bt_ctf_trace_get_name(trace));
4a32fda0
PP
1658 ret = -1;
1659 goto end;
1660 }
bc37ae52 1661
4a32fda0 1662 g_string_append(context->string, "trace {\n");
bc37ae52
JG
1663 g_string_append(context->string, "\tmajor = 1;\n");
1664 g_string_append(context->string, "\tminor = 8;\n");
dc3fffef
PP
1665 assert(trace->native_byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN ||
1666 trace->native_byte_order == BT_CTF_BYTE_ORDER_BIG_ENDIAN ||
1667 trace->native_byte_order == BT_CTF_BYTE_ORDER_NETWORK);
4a32fda0
PP
1668
1669 if (trace->uuid_set) {
1670 g_string_append_printf(context->string,
1671 "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
1672 uuid[0], uuid[1], uuid[2], uuid[3],
1673 uuid[4], uuid[5], uuid[6], uuid[7],
1674 uuid[8], uuid[9], uuid[10], uuid[11],
1675 uuid[12], uuid[13], uuid[14], uuid[15]);
1676 }
1677
bc37ae52 1678 g_string_append_printf(context->string, "\tbyte_order = %s;\n",
dc3fffef 1679 get_byte_order_string(trace->native_byte_order));
bc37ae52 1680
e011d2c1
PP
1681 if (trace->packet_header_type) {
1682 g_string_append(context->string, "\tpacket.header := ");
1683 context->current_indentation_level++;
1684 g_string_assign(context->field_name, "");
95c09b3a 1685 BT_LOGD_STR("Serializing trace's packet header field type's metadata.");
e011d2c1
PP
1686 ret = bt_ctf_field_type_serialize(trace->packet_header_type,
1687 context);
1688 if (ret) {
1689 goto end;
1690 }
1691 context->current_indentation_level--;
bc37ae52 1692 }
bc37ae52
JG
1693
1694 g_string_append(context->string, ";\n};\n\n");
1695end:
1696 return ret;
1697}
1698
bc37ae52
JG
1699static
1700void append_env_metadata(struct bt_ctf_trace *trace,
1701 struct metadata_context *context)
1702{
544d0515
PP
1703 int64_t i;
1704 int64_t env_size;
7f800dc7
PP
1705
1706 env_size = bt_ctf_attributes_get_count(trace->environment);
7f800dc7 1707 if (env_size <= 0) {
bc37ae52
JG
1708 return;
1709 }
1710
1711 g_string_append(context->string, "env {\n");
7f800dc7 1712
6474e016 1713 for (i = 0; i < env_size; i++) {
dac5c838 1714 struct bt_value *env_field_value_obj = NULL;
7f800dc7 1715 const char *entry_name;
7f800dc7
PP
1716
1717 entry_name = bt_ctf_attributes_get_field_name(
1718 trace->environment, i);
1719 env_field_value_obj = bt_ctf_attributes_get_field_value(
1720 trace->environment, i);
1721
95c09b3a
PP
1722 assert(entry_name);
1723 assert(env_field_value_obj);
7f800dc7 1724
dac5c838
PP
1725 switch (bt_value_get_type(env_field_value_obj)) {
1726 case BT_VALUE_TYPE_INTEGER:
b8248cc0
PP
1727 {
1728 int ret;
1729 int64_t int_value;
1730
dac5c838 1731 ret = bt_value_integer_get(env_field_value_obj,
7f800dc7 1732 &int_value);
95c09b3a 1733 assert(ret == 0);
7f800dc7
PP
1734 g_string_append_printf(context->string,
1735 "\t%s = %" PRId64 ";\n", entry_name,
1736 int_value);
1737 break;
b8248cc0 1738 }
dac5c838 1739 case BT_VALUE_TYPE_STRING:
7f800dc7
PP
1740 {
1741 int ret;
1742 const char *str_value;
1743 char *escaped_str = NULL;
1744
dac5c838 1745 ret = bt_value_string_get(env_field_value_obj,
7f800dc7 1746 &str_value);
95c09b3a 1747 assert(ret == 0);
7f800dc7 1748 escaped_str = g_strescape(str_value, NULL);
7f800dc7 1749 if (!escaped_str) {
95c09b3a
PP
1750 BT_LOGE("Cannot escape string: string=\"%s\"",
1751 str_value);
7f800dc7
PP
1752 goto loop_next;
1753 }
1754
1755 g_string_append_printf(context->string,
1756 "\t%s = \"%s\";\n", entry_name, escaped_str);
1757 free(escaped_str);
1758 break;
1759 }
7f800dc7
PP
1760 default:
1761 goto loop_next;
1762 }
1763
1764loop_next:
83509119 1765 BT_PUT(env_field_value_obj);
7f800dc7
PP
1766 }
1767
bc37ae52
JG
1768 g_string_append(context->string, "};\n\n");
1769}
1770
1771char *bt_ctf_trace_get_metadata_string(struct bt_ctf_trace *trace)
1772{
1773 char *metadata = NULL;
1774 struct metadata_context *context = NULL;
1775 int err = 0;
1776 size_t i;
1777
1778 if (!trace) {
95c09b3a 1779 BT_LOGW_STR("Invalid parameter: trace is NULL.");
bc37ae52
JG
1780 goto end;
1781 }
1782
1783 context = g_new0(struct metadata_context, 1);
1784 if (!context) {
95c09b3a 1785 BT_LOGE_STR("Failed to allocate one metadata context.");
bc37ae52
JG
1786 goto end;
1787 }
1788
1789 context->field_name = g_string_sized_new(DEFAULT_IDENTIFIER_SIZE);
1790 context->string = g_string_sized_new(DEFAULT_METADATA_STRING_SIZE);
1791 g_string_append(context->string, "/* CTF 1.8 */\n\n");
1792 if (append_trace_metadata(trace, context)) {
95c09b3a 1793 /* append_trace_metadata() logs errors */
bc37ae52
JG
1794 goto error;
1795 }
1796 append_env_metadata(trace, context);
1797 g_ptr_array_foreach(trace->clocks,
ac0c6bdd 1798 (GFunc)bt_ctf_clock_class_serialize, context);
bc37ae52
JG
1799
1800 for (i = 0; i < trace->stream_classes->len; i++) {
95c09b3a 1801 /* bt_ctf_stream_class_serialize() logs details */
bc37ae52
JG
1802 err = bt_ctf_stream_class_serialize(
1803 trace->stream_classes->pdata[i], context);
1804 if (err) {
95c09b3a 1805 /* bt_ctf_stream_class_serialize() logs errors */
bc37ae52
JG
1806 goto error;
1807 }
1808 }
1809
1810 metadata = context->string->str;
95c09b3a 1811
bc37ae52
JG
1812error:
1813 g_string_free(context->string, err ? TRUE : FALSE);
1814 g_string_free(context->field_name, TRUE);
1815 g_free(context);
95c09b3a 1816
bc37ae52
JG
1817end:
1818 return metadata;
1819}
1820
8a716c8d
PP
1821enum bt_ctf_byte_order bt_ctf_trace_get_native_byte_order(
1822 struct bt_ctf_trace *trace)
4ed90fb3
JG
1823{
1824 enum bt_ctf_byte_order ret = BT_CTF_BYTE_ORDER_UNKNOWN;
1825
1826 if (!trace) {
95c09b3a 1827 BT_LOGW_STR("Invalid parameter: trace is NULL.");
4ed90fb3
JG
1828 goto end;
1829 }
1830
dc3fffef
PP
1831 ret = trace->native_byte_order;
1832
4ed90fb3
JG
1833end:
1834 return ret;
1835}
1836
391c8f0d 1837int bt_ctf_trace_set_native_byte_order(struct bt_ctf_trace *trace,
bc37ae52
JG
1838 enum bt_ctf_byte_order byte_order)
1839{
1840 int ret = 0;
bc37ae52 1841
95c09b3a
PP
1842 if (!trace) {
1843 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1844 ret = -1;
1845 goto end;
1846 }
1847
1848 if (trace->frozen) {
1849 BT_LOGW("Invalid parameter: trace is frozen: "
1850 "addr=%p, name=\"%s\"",
1851 trace, bt_ctf_trace_get_name(trace));
bc37ae52
JG
1852 ret = -1;
1853 goto end;
1854 }
1855
d41cff38
PP
1856 if (trace->is_created_by_writer &&
1857 byte_order == BT_CTF_BYTE_ORDER_NONE) {
1858 BT_LOGW("Invalid parameter: BT_CTF_BYTE_ORDER_NONE byte order is not allowed for a CTF writer trace: "
1859 "addr=%p, name=\"%s\"",
1860 trace, bt_ctf_trace_get_name(trace));
1861 ret = -1;
1862 goto end;
1863 }
1864
dc3fffef
PP
1865 if (byte_order != BT_CTF_BYTE_ORDER_LITTLE_ENDIAN &&
1866 byte_order != BT_CTF_BYTE_ORDER_BIG_ENDIAN &&
1867 byte_order != BT_CTF_BYTE_ORDER_NETWORK) {
95c09b3a
PP
1868 BT_LOGW("Invalid parameter: invalid byte order: "
1869 "addr=%p, name=\"%s\", bo=%s",
1870 trace, bt_ctf_trace_get_name(trace),
1871 bt_ctf_byte_order_string(byte_order));
bc37ae52
JG
1872 ret = -1;
1873 goto end;
1874 }
1875
dc3fffef 1876 trace->native_byte_order = byte_order;
95c09b3a
PP
1877 BT_LOGV("Set trace's native byte order: "
1878 "addr=%p, name=\"%s\", bo=%s",
1879 trace, bt_ctf_trace_get_name(trace),
1880 bt_ctf_byte_order_string(byte_order));
dc3fffef 1881
bc37ae52
JG
1882end:
1883 return ret;
1884}
1885
d246b111
JG
1886struct bt_ctf_field_type *bt_ctf_trace_get_packet_header_type(
1887 struct bt_ctf_trace *trace)
1888{
1889 struct bt_ctf_field_type *field_type = NULL;
1890
1891 if (!trace) {
95c09b3a 1892 BT_LOGW_STR("Invalid parameter: trace is NULL.");
d246b111
JG
1893 goto end;
1894 }
1895
83509119 1896 bt_get(trace->packet_header_type);
d246b111
JG
1897 field_type = trace->packet_header_type;
1898end:
1899 return field_type;
1900}
1901
1902int bt_ctf_trace_set_packet_header_type(struct bt_ctf_trace *trace,
1903 struct bt_ctf_field_type *packet_header_type)
1904{
1905 int ret = 0;
1906
95c09b3a
PP
1907 if (!trace) {
1908 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1909 ret = -1;
1910 goto end;
1911 }
1912
1913 if (trace->frozen) {
1914 BT_LOGW("Invalid parameter: trace is frozen: "
1915 "addr=%p, name=\"%s\"",
1916 trace, bt_ctf_trace_get_name(trace));
d246b111
JG
1917 ret = -1;
1918 goto end;
1919 }
1920
835b2d10
JG
1921 /* packet_header_type must be a structure. */
1922 if (packet_header_type &&
95c09b3a
PP
1923 !bt_ctf_field_type_is_structure(packet_header_type)) {
1924 BT_LOGW("Invalid parameter: packet header field type must be a structure field type if it exists: "
1925 "addr=%p, name=\"%s\", ft-addr=%p, ft-id=%s",
1926 trace, bt_ctf_trace_get_name(trace),
1927 packet_header_type,
1928 bt_ctf_field_type_id_string(packet_header_type->id));
d246b111
JG
1929 ret = -1;
1930 goto end;
1931 }
1932
83509119 1933 bt_put(trace->packet_header_type);
835b2d10 1934 trace->packet_header_type = bt_get(packet_header_type);
95c09b3a
PP
1935 BT_LOGV("Set trace's packet header field type: "
1936 "addr=%p, name=\"%s\", packet-context-ft-addr=%p",
1937 trace, bt_ctf_trace_get_name(trace), packet_header_type);
d246b111
JG
1938end:
1939 return ret;
1940}
1941
8bf65fbd 1942static
544d0515 1943int64_t get_stream_class_count(void *element)
8bf65fbd
JG
1944{
1945 return bt_ctf_trace_get_stream_class_count(
1946 (struct bt_ctf_trace *) element);
1947}
1948
1949static
1950void *get_stream_class(void *element, int i)
1951{
9ac68eb1 1952 return bt_ctf_trace_get_stream_class_by_index(
8bf65fbd
JG
1953 (struct bt_ctf_trace *) element, i);
1954}
1955
1956static
d9a13d86 1957int visit_stream_class(void *object, bt_ctf_visitor visitor,void *data)
8bf65fbd 1958{
d9a13d86 1959 return bt_ctf_stream_class_visit(object, visitor, data);
8bf65fbd
JG
1960}
1961
1962int bt_ctf_trace_visit(struct bt_ctf_trace *trace,
d9a13d86 1963 bt_ctf_visitor visitor, void *data)
8bf65fbd
JG
1964{
1965 int ret;
d9a13d86
PP
1966 struct bt_ctf_object obj =
1967 { .object = trace, .type = BT_CTF_OBJECT_TYPE_TRACE };
8bf65fbd 1968
95c09b3a
PP
1969 if (!trace) {
1970 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1971 ret = -1;
1972 goto end;
1973 }
1974
1975 if (!visitor) {
1976 BT_LOGW_STR("Invalid parameter: visitor is NULL.");
8bf65fbd
JG
1977 ret = -1;
1978 goto end;
1979 }
1980
95c09b3a
PP
1981 BT_LOGV("Visiting trace: addr=%p, name=\"%s\"",
1982 trace, bt_ctf_trace_get_name(trace));
d9a13d86 1983 ret = visitor_helper(&obj, get_stream_class_count,
8bf65fbd
JG
1984 get_stream_class, visit_stream_class, visitor, data);
1985end:
1986 return ret;
1987}
1988
1989static
d9a13d86 1990int invoke_listener(struct bt_ctf_object *object, void *data)
8bf65fbd 1991{
9b888ff3 1992 struct listener_wrapper *listener_wrapper = data;
8bf65fbd 1993
d9a13d86 1994 listener_wrapper->listener(object, listener_wrapper->data);
9b888ff3 1995 return 0;
8bf65fbd
JG
1996}
1997
95c09b3a 1998// TODO: add logging to this function once we use it internally.
50ad4244
JG
1999int bt_ctf_trace_add_listener(struct bt_ctf_trace *trace,
2000 bt_ctf_listener_cb listener, void *listener_data)
2204c381
JG
2001{
2002 int ret = 0;
50ad4244
JG
2003 struct listener_wrapper *listener_wrapper =
2004 g_new0(struct listener_wrapper, 1);
2204c381 2005
50ad4244 2006 if (!trace || !listener || !listener_wrapper) {
2204c381
JG
2007 ret = -1;
2008 goto error;
2009 }
2010
50ad4244
JG
2011 listener_wrapper->listener = listener;
2012 listener_wrapper->data = listener_data;
8bf65fbd 2013
50ad4244 2014 /* Visit the current schema. */
9b888ff3 2015 ret = bt_ctf_trace_visit(trace, invoke_listener, listener_wrapper);
8bf65fbd
JG
2016 if (ret) {
2017 goto error;
2018 }
2019
50ad4244
JG
2020 /*
2021 * Add listener to the array of callbacks which will be invoked on
2022 * schema changes.
2023 */
2024 g_ptr_array_add(trace->listeners, listener_wrapper);
2204c381
JG
2025 return ret;
2026error:
50ad4244 2027 g_free(listener_wrapper);
2204c381
JG
2028 return ret;
2029}
2030
bc37ae52 2031BT_HIDDEN
d9a13d86 2032int bt_ctf_trace_object_modification(struct bt_ctf_object *object,
9b888ff3
JG
2033 void *trace_ptr)
2034{
2035 size_t i;
2036 struct bt_ctf_trace *trace = trace_ptr;
2037
2038 assert(trace);
d9a13d86 2039 assert(object);
9b888ff3
JG
2040
2041 if (trace->listeners->len == 0) {
2042 goto end;
2043 }
2044
2045 for (i = 0; i < trace->listeners->len; i++) {
2046 struct listener_wrapper *listener =
2047 g_ptr_array_index(trace->listeners, i);
2048
d9a13d86 2049 listener->listener(object, listener->data);
9b888ff3
JG
2050 }
2051end:
2052 return 0;
2053}
2054
2055BT_HIDDEN
bc37ae52
JG
2056struct bt_ctf_field_type *get_field_type(enum field_type_alias alias)
2057{
a25e0d14 2058 int ret;
bc37ae52 2059 unsigned int alignment, size;
8bdcb82e 2060 struct bt_ctf_field_type *field_type = NULL;
bc37ae52
JG
2061
2062 if (alias >= NR_FIELD_TYPE_ALIAS) {
8bdcb82e 2063 goto end;
bc37ae52
JG
2064 }
2065
2066 alignment = field_type_aliases_alignments[alias];
2067 size = field_type_aliases_sizes[alias];
2068 field_type = bt_ctf_field_type_integer_create(size);
a25e0d14
JG
2069 ret = bt_ctf_field_type_set_alignment(field_type, alignment);
2070 if (ret) {
2071 BT_PUT(field_type);
2072 }
8bdcb82e 2073end:
bc37ae52
JG
2074 return field_type;
2075}
2076
f67f3a6e 2077static
09840de5 2078void bt_ctf_trace_freeze(struct bt_ctf_trace *trace)
f67f3a6e 2079{
6474e016
PP
2080 int i;
2081
95c09b3a
PP
2082 if (trace->frozen) {
2083 return;
2084 }
2085
2086 BT_LOGD("Freezing trace: addr=%p, name=\"%s\"",
2087 trace, bt_ctf_trace_get_name(trace));
2088 BT_LOGD_STR("Freezing packet header field type.");
09840de5 2089 bt_ctf_field_type_freeze(trace->packet_header_type);
95c09b3a 2090 BT_LOGD_STR("Freezing environment attributes.");
f67f3a6e 2091 bt_ctf_attributes_freeze(trace->environment);
6474e016 2092
95c09b3a
PP
2093 if (trace->clocks->len > 0) {
2094 BT_LOGD_STR("Freezing clock classes.");
2095 }
2096
6474e016 2097 for (i = 0; i < trace->clocks->len; i++) {
ac0c6bdd 2098 struct bt_ctf_clock_class *clock_class =
6474e016
PP
2099 g_ptr_array_index(trace->clocks, i);
2100
ac0c6bdd 2101 bt_ctf_clock_class_freeze(clock_class);
6474e016
PP
2102 }
2103
f67f3a6e
JG
2104 trace->frozen = 1;
2105}
2106
c55a9f58 2107bt_bool bt_ctf_trace_is_static(struct bt_ctf_trace *trace)
5acf2ae6 2108{
c55a9f58 2109 bt_bool is_static = BT_FALSE;
5acf2ae6
PP
2110
2111 if (!trace) {
95c09b3a 2112 BT_LOGW_STR("Invalid parameter: trace is NULL.");
5acf2ae6
PP
2113 goto end;
2114 }
2115
2116 is_static = trace->is_static;
2117
2118end:
2119 return is_static;
2120}
2121
2122int bt_ctf_trace_set_is_static(struct bt_ctf_trace *trace)
2123{
2124 int ret = 0;
3602afb0 2125 size_t i;
5acf2ae6
PP
2126
2127 if (!trace) {
95c09b3a 2128 BT_LOGW_STR("Invalid parameter: trace is NULL.");
5acf2ae6
PP
2129 ret = -1;
2130 goto end;
2131 }
2132
c55a9f58 2133 trace->is_static = BT_TRUE;
5acf2ae6 2134 bt_ctf_trace_freeze(trace);
95c09b3a
PP
2135 BT_LOGV("Set trace static: addr=%p, name=\"%s\"",
2136 trace, bt_ctf_trace_get_name(trace));
5acf2ae6 2137
3602afb0
PP
2138 /* Call all the "trace is static" listeners */
2139 for (i = 0; i < trace->is_static_listeners->len; i++) {
2140 struct bt_ctf_trace_is_static_listener_elem elem =
2141 g_array_index(trace->is_static_listeners,
2142 struct bt_ctf_trace_is_static_listener_elem, i);
2143
2144 if (elem.func) {
2145 elem.func(trace, elem.data);
2146 }
2147 }
2148
2149end:
2150 return ret;
2151}
2152
2153int bt_ctf_trace_add_is_static_listener(struct bt_ctf_trace *trace,
2154 bt_ctf_trace_is_static_listener listener, void *data)
2155{
2156 int i;
2157 struct bt_ctf_trace_is_static_listener_elem new_elem = {
2158 .func = listener,
2159 .data = data,
2160 };
2161
2162 if (!trace) {
2163 BT_LOGW_STR("Invalid parameter: trace is NULL.");
2164 i = -1;
2165 goto end;
2166 }
2167
2168 if (!listener) {
2169 BT_LOGW_STR("Invalid parameter: listener is NULL.");
2170 i = -1;
2171 goto end;
2172 }
2173
2174 if (trace->is_static) {
2175 BT_LOGW("Invalid parameter: trace is already static: "
2176 "addr=%p, name=\"%s\"",
2177 trace, bt_ctf_trace_get_name(trace));
2178 i = -1;
2179 goto end;
2180 }
2181
2182 /* Find the next available spot */
2183 for (i = 0; i < trace->is_static_listeners->len; i++) {
2184 struct bt_ctf_trace_is_static_listener_elem elem =
2185 g_array_index(trace->is_static_listeners,
2186 struct bt_ctf_trace_is_static_listener_elem, i);
2187
2188 if (!elem.func) {
2189 break;
2190 }
2191 }
2192
2193 if (i == trace->is_static_listeners->len) {
2194 g_array_append_val(trace->is_static_listeners, new_elem);
2195 } else {
2196 g_array_insert_val(trace->is_static_listeners, i, new_elem);
2197 }
2198
2199 BT_LOGV("Added \"trace is static\" listener: "
2200 "trace-addr=%p, trace-name=\"%s\", func-addr=%p, "
2201 "data-addr=%p, listener-id=%d",
2202 trace, bt_ctf_trace_get_name(trace), listener, data, i);
2203
2204end:
2205 return i;
2206}
2207
2208int bt_ctf_trace_remove_is_static_listener(
2209 struct bt_ctf_trace *trace, int listener_id)
2210{
2211 int ret = 0;
2212 struct bt_ctf_trace_is_static_listener_elem *elem;
2213
2214 if (!trace) {
2215 BT_LOGW_STR("Invalid parameter: trace is NULL.");
2216 ret = -1;
2217 goto end;
2218 }
2219
2220 if (listener_id < 0) {
2221 BT_LOGW("Invalid listener ID: must be zero or positive: "
2222 "listener-id=%d", listener_id);
2223 ret = -1;
2224 goto end;
2225 }
2226
2227 if (listener_id >= trace->is_static_listeners->len) {
2228 BT_LOGW("Invalid parameter: no listener with this listener ID: "
2229 "addr=%p, name=\"%s\", listener-id=%d",
2230 trace, bt_ctf_trace_get_name(trace),
2231 listener_id);
2232 ret = -1;
2233 goto end;
2234 }
2235
2236 elem = &g_array_index(trace->is_static_listeners,
2237 struct bt_ctf_trace_is_static_listener_elem,
2238 listener_id);
2239 if (!elem->func) {
2240 BT_LOGW("Invalid parameter: no listener with this listener ID: "
2241 "addr=%p, name=\"%s\", listener-id=%d",
2242 trace, bt_ctf_trace_get_name(trace),
2243 listener_id);
2244 ret = -1;
2245 goto end;
2246 }
2247
2248 elem->func = NULL;
2249 elem->data = NULL;
2250 BT_LOGV("Removed \"trace is static\" listener: "
2251 "trace-addr=%p, trace-name=\"%s\", "
2252 "listener-id=%d", trace, bt_ctf_trace_get_name(trace),
2253 listener_id);
2254
5acf2ae6
PP
2255end:
2256 return ret;
2257}
This page took 0.141319 seconds and 4 git commands to generate.