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