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