lib: add internal object pool API and use it; adapt plugins/tests
[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
3dca2276 32#include <babeltrace/assert-pre-internal.h>
bc37ae52 33#include <babeltrace/ctf-ir/trace-internal.h>
ac0c6bdd 34#include <babeltrace/ctf-ir/clock-class-internal.h>
bc37ae52
JG
35#include <babeltrace/ctf-ir/stream-internal.h>
36#include <babeltrace/ctf-ir/stream-class-internal.h>
09840de5 37#include <babeltrace/ctf-ir/event-internal.h>
272df73e
PP
38#include <babeltrace/ctf-ir/event-class.h>
39#include <babeltrace/ctf-ir/event-class-internal.h>
bc37ae52 40#include <babeltrace/ctf-writer/functor-internal.h>
ac0c6bdd 41#include <babeltrace/ctf-writer/clock-internal.h>
312c056a 42#include <babeltrace/ctf-ir/field-wrapper-internal.h>
2e33ac5a 43#include <babeltrace/ctf-ir/field-types-internal.h>
44e0a4f5 44#include <babeltrace/ctf-ir/attributes-internal.h>
09840de5 45#include <babeltrace/ctf-ir/validation-internal.h>
8bf65fbd 46#include <babeltrace/ctf-ir/visitor-internal.h>
654c1444 47#include <babeltrace/ctf-ir/utils.h>
726106d3 48#include <babeltrace/ctf-ir/utils-internal.h>
3d9990ac 49#include <babeltrace/compiler-internal.h>
dac5c838 50#include <babeltrace/values.h>
95c09b3a 51#include <babeltrace/values-internal.h>
83509119 52#include <babeltrace/ref.h>
c55a9f58 53#include <babeltrace/types.h>
3d9990ac 54#include <babeltrace/endian-internal.h>
f6ccaed9 55#include <babeltrace/assert-internal.h>
dc3fffef 56#include <inttypes.h>
544d0515 57#include <stdint.h>
4a32fda0 58#include <string.h>
0fbb9a9f 59#include <stdlib.h>
bc37ae52
JG
60
61#define DEFAULT_IDENTIFIER_SIZE 128
62#define DEFAULT_METADATA_STRING_SIZE 4096
63
50ad4244 64struct listener_wrapper {
50842bdc 65 bt_listener_cb listener;
2204c381
JG
66 void *data;
67};
68
50842bdc
PP
69struct bt_trace_is_static_listener_elem {
70 bt_trace_is_static_listener func;
71 bt_trace_listener_removed removed;
3602afb0
PP
72 void *data;
73};
74
bc37ae52 75static
3dca2276
PP
76void bt_trace_destroy(struct bt_object *obj)
77{
78 struct bt_trace *trace = (void *) obj;
bc37ae52 79
3dca2276
PP
80 BT_LOGD("Destroying trace object: addr=%p, name=\"%s\"",
81 trace, bt_trace_get_name(trace));
bc37ae52 82
3dca2276
PP
83 /*
84 * Call remove listeners first so that everything else still
85 * exists in the trace.
86 */
87 if (trace->is_static_listeners) {
88 size_t i;
bc37ae52 89
3dca2276
PP
90 for (i = 0; i < trace->is_static_listeners->len; i++) {
91 struct bt_trace_is_static_listener_elem elem =
92 g_array_index(trace->is_static_listeners,
93 struct bt_trace_is_static_listener_elem, i);
bc37ae52 94
3dca2276
PP
95 if (elem.removed) {
96 elem.removed(trace, elem.data);
97 }
98 }
99
100 g_array_free(trace->is_static_listeners, TRUE);
bc37ae52
JG
101 }
102
3dca2276
PP
103 if (trace->listeners) {
104 g_ptr_array_free(trace->listeners, TRUE);
105 }
106
312c056a 107 bt_object_pool_finalize(&trace->packet_header_field_pool);
3dca2276
PP
108 bt_trace_common_finalize(BT_TO_COMMON(trace));
109 g_free(trace);
110}
111
112BT_HIDDEN
113int bt_trace_common_initialize(struct bt_trace_common *trace,
114 bt_object_release_func release_func)
115{
116 int ret = 0;
117
118 BT_LOGD_STR("Initializing common trace object.");
50842bdc 119 trace->native_byte_order = BT_BYTE_ORDER_UNSPECIFIED;
3dca2276
PP
120 bt_object_init(trace, release_func);
121 trace->clock_classes = g_ptr_array_new_with_free_func(
83509119 122 (GDestroyNotify) bt_put);
3dca2276 123 if (!trace->clock_classes) {
95c09b3a
PP
124 BT_LOGE_STR("Failed to allocate one GPtrArray.");
125 goto error;
126 }
127
bc37ae52 128 trace->streams = g_ptr_array_new_with_free_func(
e6a8e8e4 129 (GDestroyNotify) bt_object_release);
95c09b3a
PP
130 if (!trace->streams) {
131 BT_LOGE_STR("Failed to allocate one GPtrArray.");
132 goto error;
133 }
134
bc37ae52 135 trace->stream_classes = g_ptr_array_new_with_free_func(
e6a8e8e4 136 (GDestroyNotify) bt_object_release);
95c09b3a
PP
137 if (!trace->stream_classes) {
138 BT_LOGE_STR("Failed to allocate one GPtrArray.");
83509119 139 goto error;
bc37ae52
JG
140 }
141
7f800dc7 142 /* Create the environment array object */
50842bdc 143 trace->environment = bt_attributes_create();
7f800dc7 144 if (!trace->environment) {
95c09b3a 145 BT_LOGE_STR("Cannot create empty attributes object.");
83509119 146 goto error;
7f800dc7
PP
147 }
148
3dca2276
PP
149 BT_LOGD("Initialized common trace object: addr=%p", trace);
150 goto end;
151
152error:
153 ret = -1;
154
155end:
156 return ret;
157}
158
159BT_HIDDEN
160void bt_trace_common_finalize(struct bt_trace_common *trace)
161{
162 BT_LOGD("Finalizing common trace object: addr=%p, name=\"%s\"",
163 trace, bt_trace_common_get_name(trace));
164
165 if (trace->environment) {
166 BT_LOGD_STR("Destroying environment attributes.");
167 bt_attributes_destroy(trace->environment);
168 }
169
170 if (trace->name) {
171 g_string_free(trace->name, TRUE);
172 }
173
174 if (trace->clock_classes) {
175 BT_LOGD_STR("Putting clock classes.");
176 g_ptr_array_free(trace->clock_classes, TRUE);
177 }
178
179 if (trace->streams) {
180 BT_LOGD_STR("Destroying streams.");
181 g_ptr_array_free(trace->streams, TRUE);
182 }
183
184 if (trace->stream_classes) {
185 BT_LOGD_STR("Destroying stream classes.");
186 g_ptr_array_free(trace->stream_classes, TRUE);
187 }
188
189 BT_LOGD_STR("Putting packet header field type.");
190 bt_put(trace->packet_header_field_type);
191}
192
312c056a
PP
193static
194void free_packet_header_field(struct bt_field_wrapper *field_wrapper,
195 struct bt_trace *trace)
196{
197 bt_field_wrapper_destroy(field_wrapper);
198}
199
3dca2276
PP
200struct bt_trace *bt_trace_create(void)
201{
202 struct bt_trace *trace = NULL;
203 int ret;
204
205 BT_LOGD_STR("Creating trace object.");
206 trace = g_new0(struct bt_trace, 1);
207 if (!trace) {
208 BT_LOGE_STR("Failed to allocate one trace.");
209 goto error;
210 }
211
212 ret = bt_trace_common_initialize(BT_TO_COMMON(trace), bt_trace_destroy);
213 if (ret) {
214 /* bt_trace_common_initialize() logs errors */
215 goto error;
216 }
217
9b888ff3
JG
218 trace->listeners = g_ptr_array_new_with_free_func(
219 (GDestroyNotify) g_free);
220 if (!trace->listeners) {
95c09b3a 221 BT_LOGE_STR("Failed to allocate one GPtrArray.");
9b888ff3
JG
222 goto error;
223 }
224
3602afb0 225 trace->is_static_listeners = g_array_new(FALSE, TRUE,
50842bdc 226 sizeof(struct bt_trace_is_static_listener_elem));
3602afb0
PP
227 if (!trace->is_static_listeners) {
228 BT_LOGE_STR("Failed to allocate one GArray.");
229 goto error;
230 }
231
312c056a
PP
232 ret = bt_object_pool_initialize(&trace->packet_header_field_pool,
233 (bt_object_pool_new_object_func) bt_field_wrapper_new,
234 (bt_object_pool_destroy_object_func) free_packet_header_field,
235 trace);
236 if (ret) {
237 BT_LOGE("Failed to initialize packet header field pool: ret=%d",
238 ret);
239 goto error;
240 }
241
95c09b3a 242 BT_LOGD("Created trace object: addr=%p", trace);
bc37ae52
JG
243 return trace;
244
bc37ae52 245error:
83509119 246 BT_PUT(trace);
bc37ae52
JG
247 return trace;
248}
249
50842bdc 250const char *bt_trace_get_name(struct bt_trace *trace)
e96045d4 251{
3dca2276 252 return bt_trace_common_get_name(BT_TO_COMMON(trace));
e96045d4
JG
253}
254
3dca2276
PP
255BT_HIDDEN
256int bt_trace_common_set_name(struct bt_trace_common *trace, const char *name)
e96045d4
JG
257{
258 int ret = 0;
259
95c09b3a
PP
260 if (!trace) {
261 BT_LOGW_STR("Invalid parameter: trace is NULL.");
262 ret = -1;
263 goto end;
264 }
265
266 if (!name) {
267 BT_LOGW_STR("Invalid parameter: name is NULL.");
268 ret = -1;
269 goto end;
270 }
271
272 if (trace->frozen) {
273 BT_LOGW("Invalid parameter: trace is frozen: "
274 "addr=%p, name=\"%s\"",
3dca2276 275 trace, bt_trace_common_get_name(trace));
e96045d4
JG
276 ret = -1;
277 goto end;
278 }
279
280 trace->name = trace->name ? g_string_assign(trace->name, name) :
281 g_string_new(name);
282 if (!trace->name) {
95c09b3a 283 BT_LOGE_STR("Failed to allocate one GString.");
e96045d4
JG
284 ret = -1;
285 goto end;
286 }
95c09b3a
PP
287
288 BT_LOGV("Set trace's name: addr=%p, name=\"%s\"", trace, name);
289
e96045d4
JG
290end:
291 return ret;
292}
293
3dca2276
PP
294int bt_trace_set_name(struct bt_trace *trace, const char *name)
295{
296 return bt_trace_common_set_name(BT_TO_COMMON(trace), name);
297}
298
50842bdc 299const unsigned char *bt_trace_get_uuid(struct bt_trace *trace)
4a32fda0 300{
3dca2276 301 return bt_trace_common_get_uuid(BT_TO_COMMON(trace));
4a32fda0
PP
302}
303
3dca2276
PP
304BT_HIDDEN
305int bt_trace_common_set_uuid(struct bt_trace_common *trace,
306 const unsigned char *uuid)
4a32fda0
PP
307{
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 (!uuid) {
317 BT_LOGW_STR("Invalid parameter: UUID is NULL.");
318 ret = -1;
319 goto end;
320 }
321
322 if (trace->frozen) {
323 BT_LOGW("Invalid parameter: trace is frozen: "
324 "addr=%p, name=\"%s\"",
3dca2276 325 trace, bt_trace_common_get_name(trace));
4a32fda0
PP
326 ret = -1;
327 goto end;
328 }
329
20eee76e 330 memcpy(trace->uuid, uuid, BABELTRACE_UUID_LEN);
c55a9f58 331 trace->uuid_set = BT_TRUE;
95c09b3a
PP
332 BT_LOGV("Set trace's UUID: addr=%p, name=\"%s\", "
333 "uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\"",
3dca2276 334 trace, bt_trace_common_get_name(trace),
95c09b3a
PP
335 (unsigned int) uuid[0],
336 (unsigned int) uuid[1],
337 (unsigned int) uuid[2],
338 (unsigned int) uuid[3],
339 (unsigned int) uuid[4],
340 (unsigned int) uuid[5],
341 (unsigned int) uuid[6],
342 (unsigned int) uuid[7],
343 (unsigned int) uuid[8],
344 (unsigned int) uuid[9],
345 (unsigned int) uuid[10],
346 (unsigned int) uuid[11],
347 (unsigned int) uuid[12],
348 (unsigned int) uuid[13],
349 (unsigned int) uuid[14],
350 (unsigned int) uuid[15]);
4a32fda0
PP
351
352end:
353 return ret;
354}
355
3dca2276
PP
356int bt_trace_set_uuid(struct bt_trace *trace,
357 const unsigned char *uuid)
bc37ae52 358{
3dca2276 359 return bt_trace_common_set_uuid(BT_TO_COMMON(trace), uuid);
bc37ae52
JG
360}
361
3dca2276
PP
362BT_HIDDEN
363int bt_trace_common_set_environment_field(struct bt_trace_common *trace,
dac5c838 364 const char *name, struct bt_value *value)
bc37ae52 365{
bc37ae52
JG
366 int ret = 0;
367
95c09b3a
PP
368 if (!trace) {
369 BT_LOGW_STR("Invalid parameter: trace is NULL.");
370 ret = -1;
371 goto end;
372 }
373
374 if (!name) {
375 BT_LOGW_STR("Invalid parameter: name is NULL.");
376 ret = -1;
377 goto end;
378 }
379
380 if (!value) {
381 BT_LOGW_STR("Invalid parameter: value is NULL.");
382 ret = -1;
383 goto end;
384 }
385
f4cc9a21 386 if (!bt_identifier_is_valid(name)) {
95c09b3a
PP
387 BT_LOGW("Invalid parameter: environment field's name is not a valid CTF identifier: "
388 "trace-addr=%p, trace-name=\"%s\", "
389 "env-name=\"%s\"",
3dca2276 390 trace, bt_trace_common_get_name(trace), name);
bc37ae52 391 ret = -1;
7f800dc7 392 goto end;
bc37ae52
JG
393 }
394
95c09b3a
PP
395 if (!bt_value_is_integer(value) && !bt_value_is_string(value)) {
396 BT_LOGW("Invalid parameter: environment field's value is not an integer or string value: "
397 "trace-addr=%p, trace-name=\"%s\", "
398 "env-name=\"%s\", env-value-type=%s",
3dca2276 399 trace, bt_trace_common_get_name(trace), name,
95c09b3a
PP
400 bt_value_type_string(bt_value_get_type(value)));
401 ret = -1;
402 goto end;
403 }
404
a0d12916
JG
405 if (trace->frozen) {
406 /*
407 * New environment fields may be added to a frozen trace,
408 * but existing fields may not be changed.
409 *
410 * The object passed is frozen like all other attributes.
411 */
dac5c838 412 struct bt_value *attribute =
094ff7c0 413 bt_attributes_borrow_field_value_by_name(
a0d12916
JG
414 trace->environment, name);
415
416 if (attribute) {
95c09b3a
PP
417 BT_LOGW("Invalid parameter: trace is frozen and environment field already exists with this name: "
418 "trace-addr=%p, trace-name=\"%s\", "
419 "env-name=\"%s\"",
3dca2276 420 trace, bt_trace_common_get_name(trace), name);
a0d12916
JG
421 ret = -1;
422 goto end;
423 }
424
dac5c838 425 bt_value_freeze(value);
a0d12916
JG
426 }
427
50842bdc 428 ret = bt_attributes_set_field_value(trace->environment, name,
7f800dc7 429 value);
95c09b3a
PP
430 if (ret) {
431 BT_LOGE("Cannot set environment field's value: "
432 "trace-addr=%p, trace-name=\"%s\", "
433 "env-name=\"%s\"",
3dca2276 434 trace, bt_trace_common_get_name(trace), name);
95c09b3a
PP
435 } else {
436 BT_LOGV("Set environment field's value: "
437 "trace-addr=%p, trace-name=\"%s\", "
438 "env-name=\"%s\", value-addr=%p",
3dca2276 439 trace, bt_trace_common_get_name(trace), name, value);
95c09b3a 440 }
bc37ae52 441
7f800dc7
PP
442end:
443 return ret;
444}
bc37ae52 445
3dca2276
PP
446int bt_trace_set_environment_field(struct bt_trace *trace,
447 const char *name, struct bt_value *value)
448{
449 int ret;
450
451 if (trace->is_static) {
452 BT_LOGW("Invalid parameter: trace is static: "
453 "addr=%p, name=\"%s\"",
454 trace, bt_trace_get_name(trace));
455 ret = -1;
456 goto end;
457 }
458
459 ret = bt_trace_common_set_environment_field(BT_TO_COMMON(trace),
460 name, value);
461
462end:
463 return ret;
464}
465
466BT_HIDDEN
467int bt_trace_common_set_environment_field_string(struct bt_trace_common *trace,
7f800dc7
PP
468 const char *name, const char *value)
469{
470 int ret = 0;
dac5c838 471 struct bt_value *env_value_string_obj = NULL;
7f800dc7 472
95c09b3a
PP
473 if (!value) {
474 BT_LOGW_STR("Invalid parameter: value is NULL.");
bc37ae52 475 ret = -1;
7f800dc7 476 goto end;
bc37ae52
JG
477 }
478
dac5c838 479 env_value_string_obj = bt_value_string_create_init(value);
7f800dc7 480 if (!env_value_string_obj) {
95c09b3a 481 BT_LOGE_STR("Cannot create string value object.");
7f800dc7
PP
482 ret = -1;
483 goto end;
bc37ae52
JG
484 }
485
3dca2276
PP
486 /* bt_trace_common_set_environment_field() logs errors */
487 ret = bt_trace_common_set_environment_field(trace, name,
7f800dc7
PP
488 env_value_string_obj);
489
490end:
95c09b3a 491 bt_put(env_value_string_obj);
3487c9f3
JG
492 return ret;
493}
494
3dca2276
PP
495int bt_trace_set_environment_field_string(struct bt_trace *trace,
496 const char *name, const char *value)
497{
498 return bt_trace_common_set_environment_field_string(BT_TO_COMMON(trace),
499 name, value);
500}
501
502BT_HIDDEN
503int bt_trace_common_set_environment_field_integer(
504 struct bt_trace_common *trace, const char *name, int64_t value)
3487c9f3 505{
3487c9f3 506 int ret = 0;
dac5c838 507 struct bt_value *env_value_integer_obj = NULL;
3487c9f3 508
dac5c838 509 env_value_integer_obj = bt_value_integer_create_init(value);
7f800dc7 510 if (!env_value_integer_obj) {
95c09b3a 511 BT_LOGE_STR("Cannot create integer value object.");
3487c9f3 512 ret = -1;
7f800dc7 513 goto end;
3487c9f3
JG
514 }
515
3dca2276
PP
516 /* bt_trace_common_set_environment_field() logs errors */
517 ret = bt_trace_common_set_environment_field(trace, name,
7f800dc7 518 env_value_integer_obj);
95c09b3a 519
7f800dc7 520end:
95c09b3a 521 bt_put(env_value_integer_obj);
bc37ae52
JG
522 return ret;
523}
524
3dca2276
PP
525int bt_trace_set_environment_field_integer(
526 struct bt_trace *trace, const char *name, int64_t value)
e6fa2160 527{
3dca2276
PP
528 return bt_trace_common_set_environment_field_integer(
529 BT_TO_COMMON(trace), name, value);
530}
e6fa2160 531
3dca2276
PP
532int64_t bt_trace_get_environment_field_count(struct bt_trace *trace)
533{
534 return bt_trace_common_get_environment_field_count(BT_TO_COMMON(trace));
e6fa2160
JG
535}
536
537const char *
50842bdc 538bt_trace_get_environment_field_name_by_index(struct bt_trace *trace,
9ac68eb1 539 uint64_t index)
e6fa2160 540{
3dca2276
PP
541 return bt_trace_common_get_environment_field_name_by_index(
542 BT_TO_COMMON(trace), index);
e6fa2160
JG
543}
544
094ff7c0 545struct bt_value *bt_trace_borrow_environment_field_value_by_index(
50842bdc 546 struct bt_trace *trace, uint64_t index)
e6fa2160 547{
094ff7c0 548 return bt_trace_common_borrow_environment_field_value_by_index(
3dca2276 549 BT_TO_COMMON(trace), index);
e6fa2160
JG
550}
551
094ff7c0 552struct bt_value *bt_trace_borrow_environment_field_value_by_name(
50842bdc 553 struct bt_trace *trace, const char *name)
e6fa2160 554{
094ff7c0 555 return bt_trace_common_borrow_environment_field_value_by_name(
3dca2276 556 BT_TO_COMMON(trace), name);
e6fa2160
JG
557}
558
3dca2276
PP
559BT_HIDDEN
560int bt_trace_common_add_clock_class(struct bt_trace_common *trace,
50842bdc 561 struct bt_clock_class *clock_class)
bc37ae52
JG
562{
563 int ret = 0;
bc37ae52 564
95c09b3a
PP
565 if (!trace) {
566 BT_LOGW_STR("Invalid parameter: trace is NULL.");
567 ret = -1;
568 goto end;
569 }
570
50842bdc 571 if (!bt_clock_class_is_valid(clock_class)) {
95c09b3a
PP
572 BT_LOGW("Invalid parameter: clock class is invalid: "
573 "trace-addr=%p, trace-name=\"%s\", "
574 "clock-class-addr=%p, clock-class-name=\"%s\"",
3dca2276 575 trace, bt_trace_common_get_name(trace),
50842bdc 576 clock_class, bt_clock_class_get_name(clock_class));
bc37ae52
JG
577 ret = -1;
578 goto end;
579 }
580
ac0c6bdd 581 /* Check for duplicate clock classes */
3dca2276 582 if (bt_trace_common_has_clock_class(trace, clock_class)) {
95c09b3a
PP
583 BT_LOGW("Invalid parameter: clock class already exists in trace: "
584 "trace-addr=%p, trace-name=\"%s\", "
585 "clock-class-addr=%p, clock-class-name=\"%s\"",
3dca2276 586 trace, bt_trace_common_get_name(trace),
50842bdc 587 clock_class, bt_clock_class_get_name(clock_class));
bc37ae52
JG
588 ret = -1;
589 goto end;
590 }
591
ac0c6bdd 592 bt_get(clock_class);
3dca2276 593 g_ptr_array_add(trace->clock_classes, clock_class);
cfeb617e 594
6474e016 595 if (trace->frozen) {
95c09b3a 596 BT_LOGV_STR("Freezing added clock class because trace is frozen.");
50842bdc 597 bt_clock_class_freeze(clock_class);
6474e016 598 }
95c09b3a
PP
599
600 BT_LOGV("Added clock class to trace: "
601 "trace-addr=%p, trace-name=\"%s\", "
602 "clock-class-addr=%p, clock-class-name=\"%s\"",
3dca2276 603 trace, bt_trace_common_get_name(trace),
50842bdc 604 clock_class, bt_clock_class_get_name(clock_class));
95c09b3a 605
bc37ae52
JG
606end:
607 return ret;
608}
609
3dca2276
PP
610int bt_trace_add_clock_class(struct bt_trace *trace,
611 struct bt_clock_class *clock_class)
612{
613 int ret;
614
615 if (trace->is_static) {
616 BT_LOGW("Invalid parameter: trace is static: "
617 "addr=%p, name=\"%s\"",
618 trace, bt_trace_get_name(trace));
619 ret = -1;
620 goto end;
621 }
622
623 ret = bt_trace_common_add_clock_class(BT_TO_COMMON(trace),
624 clock_class);
625
626end:
627 return ret;
628}
629
50842bdc 630int64_t bt_trace_get_clock_class_count(struct bt_trace *trace)
884cd6c3 631{
3dca2276 632 return bt_trace_common_get_clock_class_count(BT_TO_COMMON(trace));
884cd6c3
JG
633}
634
094ff7c0 635struct bt_clock_class *bt_trace_borrow_clock_class_by_index(
50842bdc 636 struct bt_trace *trace, uint64_t index)
884cd6c3 637{
094ff7c0 638 return bt_trace_common_borrow_clock_class_by_index(
3dca2276 639 BT_TO_COMMON(trace), index);
884cd6c3
JG
640}
641
e011d2c1 642static
3dca2276
PP
643bool packet_header_field_type_is_valid(struct bt_trace_common *trace,
644 struct bt_field_type_common *packet_header_type)
e011d2c1
PP
645{
646 int ret;
647 bool is_valid = true;
3dca2276 648 struct bt_field_type_common *field_type = NULL;
e011d2c1
PP
649
650 if (!packet_header_type) {
651 /*
652 * No packet header field type: trace must have only
653 * one stream. At this point the stream class being
654 * added is not part of the trace yet, so we validate
655 * that the trace contains no stream classes yet.
656 */
657 if (trace->stream_classes->len >= 1) {
658 BT_LOGW_STR("Invalid packet header field type: "
659 "packet header field type does not exist but there's more than one stream class in the trace.");
660 goto invalid;
661 }
662
663 /* No packet header field type: valid at this point */
664 goto end;
665 }
666
667 /* Packet header field type, if it exists, must be a structure */
3dca2276 668 if (packet_header_type->id != BT_FIELD_TYPE_ID_STRUCT) {
e011d2c1
PP
669 BT_LOGW("Invalid packet header field type: must be a structure field type if it exists: "
670 "ft-addr=%p, ft-id=%s",
671 packet_header_type,
3dca2276 672 bt_common_field_type_id_string(packet_header_type->id));
e011d2c1
PP
673 goto invalid;
674 }
675
676 /*
677 * If there's a `magic` field, it must be a 32-bit unsigned
678 * integer field type. Also it must be the first field of the
679 * packet header field type.
680 */
094ff7c0 681 field_type = bt_field_type_common_structure_borrow_field_type_by_name(
e011d2c1
PP
682 packet_header_type, "magic");
683 if (field_type) {
684 const char *field_name;
685
3dca2276 686 if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
e011d2c1
PP
687 BT_LOGW("Invalid packet header field type: `magic` field must be an integer field type: "
688 "magic-ft-addr=%p, magic-ft-id=%s",
689 field_type,
3dca2276 690 bt_common_field_type_id_string(field_type->id));
e011d2c1
PP
691 goto invalid;
692 }
693
3dca2276 694 if (bt_field_type_common_integer_is_signed(field_type)) {
e011d2c1
PP
695 BT_LOGW("Invalid packet header field type: `magic` field must be an unsigned integer field type: "
696 "magic-ft-addr=%p", field_type);
697 goto invalid;
698 }
699
3dca2276 700 if (bt_field_type_common_integer_get_size(field_type) != 32) {
e011d2c1
PP
701 BT_LOGW("Invalid packet header field type: `magic` field must be a 32-bit unsigned integer field type: "
702 "magic-ft-addr=%p, magic-ft-size=%u",
703 field_type,
3dca2276 704 bt_field_type_common_integer_get_size(field_type));
e011d2c1
PP
705 goto invalid;
706 }
707
094ff7c0 708 ret = bt_field_type_common_structure_borrow_field_by_index(
e011d2c1 709 packet_header_type, &field_name, NULL, 0);
f6ccaed9 710 BT_ASSERT(ret == 0);
e011d2c1
PP
711
712 if (strcmp(field_name, "magic") != 0) {
713 BT_LOGW("Invalid packet header field type: `magic` field must be the first field: "
714 "magic-ft-addr=%p, first-field-name=\"%s\"",
715 field_type, field_name);
716 goto invalid;
717 }
e011d2c1
PP
718 }
719
720 /*
721 * If there's a `uuid` field, it must be an array field type of
722 * length 16 with an 8-bit unsigned integer element field type.
723 */
094ff7c0 724 field_type = bt_field_type_common_structure_borrow_field_type_by_name(
e011d2c1
PP
725 packet_header_type, "uuid");
726 if (field_type) {
3dca2276 727 struct bt_field_type_common *elem_ft;
e011d2c1 728
3dca2276 729 if (field_type->id != BT_FIELD_TYPE_ID_ARRAY) {
e011d2c1
PP
730 BT_LOGW("Invalid packet header field type: `uuid` field must be an array field type: "
731 "uuid-ft-addr=%p, uuid-ft-id=%s",
732 field_type,
3dca2276 733 bt_common_field_type_id_string(field_type->id));
e011d2c1
PP
734 goto invalid;
735 }
736
3dca2276 737 if (bt_field_type_common_array_get_length(field_type) != 16) {
e011d2c1
PP
738 BT_LOGW("Invalid packet header field type: `uuid` array field type's length must be 16: "
739 "uuid-ft-addr=%p, uuid-ft-length=%" PRId64,
740 field_type,
3dca2276 741 bt_field_type_common_array_get_length(field_type));
e011d2c1
PP
742 goto invalid;
743 }
744
094ff7c0 745 elem_ft = bt_field_type_common_array_borrow_element_field_type(field_type);
f6ccaed9 746 BT_ASSERT(elem_ft);
e011d2c1 747
3dca2276 748 if (elem_ft->id != BT_FIELD_TYPE_ID_INTEGER) {
e011d2c1
PP
749 BT_LOGW("Invalid packet header field type: `uuid` field's element field type must be an integer field type: "
750 "elem-ft-addr=%p, elem-ft-id=%s",
751 elem_ft,
3dca2276 752 bt_common_field_type_id_string(elem_ft->id));
e011d2c1
PP
753 goto invalid;
754 }
755
3dca2276 756 if (bt_field_type_common_integer_is_signed(elem_ft)) {
e011d2c1
PP
757 BT_LOGW("Invalid packet header field type: `uuid` field's element field type must be an unsigned integer field type: "
758 "elem-ft-addr=%p", elem_ft);
e011d2c1
PP
759 goto invalid;
760 }
761
3dca2276 762 if (bt_field_type_common_integer_get_size(elem_ft) != 8) {
e011d2c1
PP
763 BT_LOGW("Invalid packet header field type: `uuid` field's element field type must be an 8-bit unsigned integer field type: "
764 "elem-ft-addr=%p, elem-ft-size=%u",
765 elem_ft,
3dca2276 766 bt_field_type_common_integer_get_size(elem_ft));
e011d2c1
PP
767 goto invalid;
768 }
e011d2c1
PP
769 }
770
771 /*
772 * The `stream_id` field must exist if there's more than one
773 * stream classes in the trace.
774 */
094ff7c0 775 field_type = bt_field_type_common_structure_borrow_field_type_by_name(
e011d2c1
PP
776 packet_header_type, "stream_id");
777
778 if (!field_type && trace->stream_classes->len >= 1) {
779 BT_LOGW_STR("Invalid packet header field type: "
780 "`stream_id` field does not exist but there's more than one stream class in the trace.");
781 goto invalid;
782 }
783
784 /*
785 * If there's a `stream_id` field, it must be an unsigned
786 * integer field type.
787 */
788 if (field_type) {
3dca2276 789 if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
e011d2c1
PP
790 BT_LOGW("Invalid packet header field type: `stream_id` field must be an integer field type: "
791 "stream-id-ft-addr=%p, stream-id-ft-id=%s",
792 field_type,
3dca2276 793 bt_common_field_type_id_string(field_type->id));
e011d2c1
PP
794 goto invalid;
795 }
796
3dca2276 797 if (bt_field_type_common_integer_is_signed(field_type)) {
e011d2c1
PP
798 BT_LOGW("Invalid packet header field type: `stream_id` field must be an unsigned integer field type: "
799 "stream-id-ft-addr=%p", field_type);
800 goto invalid;
801 }
e011d2c1
PP
802 }
803
708ab211
PP
804 /*
805 * If there's a `packet_seq_num` field, it must be an unsigned
806 * integer field type.
807 */
094ff7c0 808 field_type = bt_field_type_common_structure_borrow_field_type_by_name(
708ab211
PP
809 packet_header_type, "packet_seq_num");
810 if (field_type) {
3dca2276 811 if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
708ab211
PP
812 BT_LOGW("Invalid packet header field type: `packet_seq_num` field must be an integer field type: "
813 "stream-id-ft-addr=%p, packet-seq-num-ft-id=%s",
814 field_type,
3dca2276 815 bt_common_field_type_id_string(field_type->id));
708ab211
PP
816 goto invalid;
817 }
818
3dca2276 819 if (bt_field_type_common_integer_is_signed(field_type)) {
708ab211
PP
820 BT_LOGW("Invalid packet header field type: `packet_seq_num` field must be an unsigned integer field type: "
821 "packet-seq-num-ft-addr=%p", field_type);
822 goto invalid;
823 }
708ab211
PP
824 }
825
e011d2c1
PP
826 goto end;
827
828invalid:
829 is_valid = false;
830
831end:
e011d2c1
PP
832 return is_valid;
833}
834
835static
3dca2276
PP
836bool packet_context_field_type_is_valid(struct bt_trace_common *trace,
837 struct bt_stream_class_common *stream_class,
838 struct bt_field_type_common *packet_context_type,
839 bool check_ts_begin_end_mapped)
e011d2c1
PP
840{
841 bool is_valid = true;
3dca2276 842 struct bt_field_type_common *field_type = NULL;
e011d2c1
PP
843
844 if (!packet_context_type) {
845 /* No packet context field type: valid at this point */
846 goto end;
847 }
848
849 /* Packet context field type, if it exists, must be a structure */
3dca2276 850 if (packet_context_type->id != BT_FIELD_TYPE_ID_STRUCT) {
e011d2c1
PP
851 BT_LOGW("Invalid packet context field type: must be a structure field type if it exists: "
852 "ft-addr=%p, ft-id=%s",
853 packet_context_type,
3dca2276 854 bt_common_field_type_id_string(packet_context_type->id));
e011d2c1
PP
855 goto invalid;
856 }
857
858 /*
859 * If there's a `packet_size` field, it must be an unsigned
860 * integer field type.
861 */
094ff7c0 862 field_type = bt_field_type_common_structure_borrow_field_type_by_name(
e011d2c1
PP
863 packet_context_type, "packet_size");
864 if (field_type) {
3dca2276 865 if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
e011d2c1
PP
866 BT_LOGW("Invalid packet context field type: `packet_size` field must be an integer field type: "
867 "packet-size-ft-addr=%p, packet-size-ft-id=%s",
868 field_type,
3dca2276 869 bt_common_field_type_id_string(field_type->id));
e011d2c1
PP
870 goto invalid;
871 }
872
3dca2276 873 if (bt_field_type_common_integer_is_signed(field_type)) {
e011d2c1
PP
874 BT_LOGW("Invalid packet context field type: `packet_size` field must be an unsigned integer field type: "
875 "packet-size-ft-addr=%p", field_type);
876 goto invalid;
877 }
e011d2c1
PP
878 }
879
880 /*
881 * If there's a `content_size` field, it must be an unsigned
882 * integer field type.
883 */
094ff7c0 884 field_type = bt_field_type_common_structure_borrow_field_type_by_name(
e011d2c1
PP
885 packet_context_type, "content_size");
886 if (field_type) {
3dca2276 887 if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
e011d2c1
PP
888 BT_LOGW("Invalid packet context field type: `content_size` field must be an integer field type: "
889 "content-size-ft-addr=%p, content-size-ft-id=%s",
890 field_type,
3dca2276 891 bt_common_field_type_id_string(field_type->id));
e011d2c1
PP
892 goto invalid;
893 }
894
3dca2276 895 if (bt_field_type_common_integer_is_signed(field_type)) {
e011d2c1
PP
896 BT_LOGW("Invalid packet context field type: `content_size` field must be an unsigned integer field type: "
897 "content-size-ft-addr=%p", field_type);
898 goto invalid;
899 }
e011d2c1
PP
900 }
901
902 /*
903 * If there's a `events_discarded` field, it must be an unsigned
904 * integer field type.
905 */
094ff7c0 906 field_type = bt_field_type_common_structure_borrow_field_type_by_name(
e011d2c1
PP
907 packet_context_type, "events_discarded");
908 if (field_type) {
3dca2276 909 if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
e011d2c1
PP
910 BT_LOGW("Invalid packet context field type: `events_discarded` field must be an integer field type: "
911 "events-discarded-ft-addr=%p, events-discarded-ft-id=%s",
912 field_type,
3dca2276 913 bt_common_field_type_id_string(field_type->id));
e011d2c1
PP
914 goto invalid;
915 }
916
3dca2276 917 if (bt_field_type_common_integer_is_signed(field_type)) {
e011d2c1
PP
918 BT_LOGW("Invalid packet context field type: `events_discarded` field must be an unsigned integer field type: "
919 "events-discarded-ft-addr=%p", field_type);
920 goto invalid;
921 }
e011d2c1
PP
922 }
923
924 /*
925 * If there's a `timestamp_begin` field, it must be an unsigned
926 * integer field type. Also, if the trace is not a CTF writer's
927 * trace, then we cannot automatically set the mapped clock
928 * class of this field, so it must have a mapped clock class.
929 */
094ff7c0 930 field_type = bt_field_type_common_structure_borrow_field_type_by_name(
e011d2c1
PP
931 packet_context_type, "timestamp_begin");
932 if (field_type) {
3dca2276 933 if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
e011d2c1
PP
934 BT_LOGW("Invalid packet context field type: `timestamp_begin` field must be an integer field type: "
935 "timestamp-begin-ft-addr=%p, timestamp-begin-ft-id=%s",
936 field_type,
3dca2276 937 bt_common_field_type_id_string(field_type->id));
e011d2c1
PP
938 goto invalid;
939 }
940
3dca2276 941 if (bt_field_type_common_integer_is_signed(field_type)) {
e011d2c1
PP
942 BT_LOGW("Invalid packet context field type: `timestamp_begin` field must be an unsigned integer field type: "
943 "timestamp-begin-ft-addr=%p", field_type);
944 goto invalid;
945 }
946
3dca2276 947 if (check_ts_begin_end_mapped) {
50842bdc 948 struct bt_clock_class *clock_class =
094ff7c0 949 bt_field_type_common_integer_borrow_mapped_clock_class(
e011d2c1
PP
950 field_type);
951
e011d2c1
PP
952 if (!clock_class) {
953 BT_LOGW("Invalid packet context field type: `timestamp_begin` field must be mapped to a clock class: "
954 "timestamp-begin-ft-addr=%p", field_type);
955 goto invalid;
956 }
957 }
e011d2c1
PP
958 }
959
960 /*
961 * If there's a `timestamp_end` field, it must be an unsigned
962 * integer field type. Also, if the trace is not a CTF writer's
963 * trace, then we cannot automatically set the mapped clock
964 * class of this field, so it must have a mapped clock class.
965 */
094ff7c0 966 field_type = bt_field_type_common_structure_borrow_field_type_by_name(
e011d2c1
PP
967 packet_context_type, "timestamp_end");
968 if (field_type) {
3dca2276 969 if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
e011d2c1
PP
970 BT_LOGW("Invalid packet context field type: `timestamp_end` field must be an integer field type: "
971 "timestamp-end-ft-addr=%p, timestamp-end-ft-id=%s",
972 field_type,
3dca2276 973 bt_common_field_type_id_string(field_type->id));
e011d2c1
PP
974 goto invalid;
975 }
976
3dca2276 977 if (bt_field_type_common_integer_is_signed(field_type)) {
e011d2c1
PP
978 BT_LOGW("Invalid packet context field type: `timestamp_end` field must be an unsigned integer field type: "
979 "timestamp-end-ft-addr=%p", field_type);
980 goto invalid;
981 }
982
3dca2276 983 if (check_ts_begin_end_mapped) {
50842bdc 984 struct bt_clock_class *clock_class =
094ff7c0 985 bt_field_type_common_integer_borrow_mapped_clock_class(
e011d2c1
PP
986 field_type);
987
e011d2c1
PP
988 if (!clock_class) {
989 BT_LOGW("Invalid packet context field type: `timestamp_end` field must be mapped to a clock class: "
990 "timestamp-end-ft-addr=%p", field_type);
991 goto invalid;
992 }
993 }
e011d2c1
PP
994 }
995
996 goto end;
997
998invalid:
999 is_valid = false;
1000
1001end:
e011d2c1
PP
1002 return is_valid;
1003}
1004
1005static
3dca2276
PP
1006bool event_header_field_type_is_valid(struct bt_trace_common *trace,
1007 struct bt_stream_class_common *stream_class,
1008 struct bt_field_type_common *event_header_type)
e011d2c1
PP
1009{
1010 bool is_valid = true;
3dca2276 1011 struct bt_field_type_common *field_type = NULL;
e011d2c1
PP
1012
1013 /*
1014 * We do not validate that the `timestamp` field exists here
1015 * because CTF does not require this exact name to be mapped to
1016 * a clock class.
1017 */
1018
1019 if (!event_header_type) {
1020 /*
1021 * No event header field type: stream class must have
1022 * only one event class.
1023 */
3dca2276 1024 if (bt_stream_class_common_get_event_class_count(stream_class) > 1) {
e011d2c1
PP
1025 BT_LOGW_STR("Invalid event header field type: "
1026 "event header field type does not exist but there's more than one event class in the stream class.");
1027 goto invalid;
1028 }
1029
1030 /* No event header field type: valid at this point */
1031 goto end;
1032 }
1033
1034 /* Event header field type, if it exists, must be a structure */
3dca2276 1035 if (event_header_type->id != BT_FIELD_TYPE_ID_STRUCT) {
e011d2c1
PP
1036 BT_LOGW("Invalid event header field type: must be a structure field type if it exists: "
1037 "ft-addr=%p, ft-id=%s",
1038 event_header_type,
3dca2276 1039 bt_common_field_type_id_string(event_header_type->id));
e011d2c1
PP
1040 goto invalid;
1041 }
1042
1043 /*
1044 * If there's an `id` field, it must be an unsigned integer
1045 * field type or an enumeration field type with an unsigned
1046 * integer container field type.
1047 */
094ff7c0 1048 field_type = bt_field_type_common_structure_borrow_field_type_by_name(
e011d2c1
PP
1049 event_header_type, "id");
1050 if (field_type) {
3dca2276 1051 struct bt_field_type_common *int_ft;
e011d2c1 1052
3dca2276 1053 if (field_type->id == BT_FIELD_TYPE_ID_INTEGER) {
094ff7c0 1054 int_ft = field_type;
3dca2276 1055 } else if (field_type->id == BT_FIELD_TYPE_ID_ENUM) {
094ff7c0 1056 int_ft = bt_field_type_common_enumeration_borrow_container_field_type(
e011d2c1
PP
1057 field_type);
1058 } else {
1059 BT_LOGW("Invalid event header field type: `id` field must be an integer or enumeration field type: "
1060 "id-ft-addr=%p, id-ft-id=%s",
1061 field_type,
3dca2276 1062 bt_common_field_type_id_string(field_type->id));
e011d2c1
PP
1063 goto invalid;
1064 }
1065
f6ccaed9 1066 BT_ASSERT(int_ft);
3dca2276 1067 if (bt_field_type_common_integer_is_signed(int_ft)) {
e011d2c1
PP
1068 BT_LOGW("Invalid event header field type: `id` field must be an unsigned integer or enumeration field type: "
1069 "id-ft-addr=%p", int_ft);
1070 goto invalid;
1071 }
e011d2c1
PP
1072 }
1073
1074 goto end;
1075
1076invalid:
1077 is_valid = false;
1078
1079end:
e011d2c1
PP
1080 return is_valid;
1081}
1082
726106d3 1083static
3dca2276 1084int check_packet_header_type_has_no_clock_class(struct bt_trace_common *trace)
726106d3
PP
1085{
1086 int ret = 0;
1087
3dca2276 1088 if (trace->packet_header_field_type) {
726106d3
PP
1089 struct bt_clock_class *clock_class = NULL;
1090
3dca2276
PP
1091 ret = bt_field_type_common_validate_single_clock_class(
1092 trace->packet_header_field_type,
726106d3
PP
1093 &clock_class);
1094 bt_put(clock_class);
1095 if (ret || clock_class) {
1096 BT_LOGW("Trace's packet header field type cannot "
1097 "contain a field type which is mapped to "
1098 "a clock class: "
1099 "trace-addr=%p, trace-name=\"%s\", "
1100 "clock-class-name=\"%s\"",
3dca2276 1101 trace, bt_trace_common_get_name(trace),
726106d3
PP
1102 clock_class ?
1103 bt_clock_class_get_name(clock_class) :
1104 NULL);
1105 ret = -1;
1106 }
1107 }
1108
1109 return ret;
1110}
1111
3dca2276
PP
1112BT_HIDDEN
1113int bt_trace_common_add_stream_class(struct bt_trace_common *trace,
1114 struct bt_stream_class_common *stream_class,
1115 bt_validation_flag_copy_field_type_func copy_field_type_func,
1116 struct bt_clock_class *init_expected_clock_class,
1117 int (*map_clock_classes_func)(struct bt_stream_class_common *stream_class,
1118 struct bt_field_type_common *packet_context_field_type,
1119 struct bt_field_type_common *event_header_field_type),
1120 bool check_ts_begin_end_mapped)
ef0c4a15 1121{
544d0515
PP
1122 int ret;
1123 int64_t i;
ef0c4a15 1124 int64_t stream_id;
50842bdc
PP
1125 struct bt_validation_output trace_sc_validation_output = { 0 };
1126 struct bt_validation_output *ec_validation_outputs = NULL;
1127 const enum bt_validation_flag trace_sc_validation_flags =
1128 BT_VALIDATION_FLAG_TRACE |
1129 BT_VALIDATION_FLAG_STREAM;
1130 const enum bt_validation_flag ec_validation_flags =
1131 BT_VALIDATION_FLAG_EVENT;
3dca2276
PP
1132 struct bt_field_type_common *packet_header_type = NULL;
1133 struct bt_field_type_common *packet_context_type = NULL;
1134 struct bt_field_type_common *event_header_type = NULL;
1135 struct bt_field_type_common *stream_event_ctx_type = NULL;
544d0515 1136 int64_t event_class_count;
3dca2276
PP
1137 struct bt_trace_common *current_parent_trace = NULL;
1138 struct bt_clock_class *expected_clock_class =
1139 bt_get(init_expected_clock_class);
1140
1141 BT_ASSERT(copy_field_type_func);
ef0c4a15 1142
95c09b3a
PP
1143 if (!trace) {
1144 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1145 ret = -1;
1146 goto end;
1147 }
1148
1149 if (!stream_class) {
1150 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
1151 ret = -1;
1152 goto end;
1153 }
1154
95c09b3a
PP
1155 BT_LOGD("Adding stream class to trace: "
1156 "trace-addr=%p, trace-name=\"%s\", "
1157 "stream-class-addr=%p, stream-class-name=\"%s\", "
1158 "stream-class-id=%" PRId64,
3dca2276
PP
1159 trace, bt_trace_common_get_name(trace),
1160 stream_class, bt_stream_class_common_get_name(stream_class),
1161 bt_stream_class_common_get_id(stream_class));
95c09b3a 1162
094ff7c0 1163 current_parent_trace = bt_stream_class_common_borrow_trace(stream_class);
2789e5d9
JG
1164 if (current_parent_trace) {
1165 /* Stream class is already associated to a trace, abort. */
95c09b3a
PP
1166 BT_LOGW("Invalid parameter: stream class is already part of a trace: "
1167 "stream-class-trace-addr=%p, "
1168 "stream-class-trace-name=\"%s\"",
1169 current_parent_trace,
3dca2276 1170 bt_trace_common_get_name(current_parent_trace));
2789e5d9
JG
1171 ret = -1;
1172 goto end;
1173 }
1174
09840de5 1175 event_class_count =
3dca2276 1176 bt_stream_class_common_get_event_class_count(stream_class);
f6ccaed9 1177 BT_ASSERT(event_class_count >= 0);
09840de5 1178
2a3ced3c
PP
1179 if (!stream_class->frozen) {
1180 /*
1181 * Stream class is not frozen yet. Validate that the
1182 * stream class contains at most a single clock class
1183 * because the previous
3dca2276
PP
1184 * bt_stream_class_common_add_event_class() calls did
1185 * not make this validation since the stream class's
1186 * direct field types (packet context, event header,
1187 * event context) could change afterwards. This stream
1188 * class is about to be frozen and those field types
1189 * won't be changed if this function succeeds.
2a3ced3c
PP
1190 *
1191 * At this point we're also sure that the stream class's
1192 * clock, if any, has the same class as the stream
1193 * class's expected clock class, if any. This is why, if
3dca2276 1194 * bt_stream_class_common_validate_single_clock_class()
2a3ced3c
PP
1195 * succeeds below, the call to
1196 * bt_stream_class_map_clock_class() at the end of this
1197 * function is safe because it maps to the same, single
1198 * clock class.
1199 */
3dca2276
PP
1200 ret = bt_stream_class_common_validate_single_clock_class(
1201 stream_class, &expected_clock_class);
2a3ced3c
PP
1202 if (ret) {
1203 BT_LOGW("Invalid parameter: stream class or one of its "
1204 "event classes contains a field type which is "
1205 "not recursively mapped to the expected "
1206 "clock class: "
1207 "stream-class-addr=%p, "
1208 "stream-class-id=%" PRId64 ", "
1209 "stream-class-name=\"%s\", "
1210 "expected-clock-class-addr=%p, "
1211 "expected-clock-class-name=\"%s\"",
3dca2276
PP
1212 stream_class, bt_stream_class_common_get_id(stream_class),
1213 bt_stream_class_common_get_name(stream_class),
2a3ced3c
PP
1214 expected_clock_class,
1215 expected_clock_class ?
1216 bt_clock_class_get_name(expected_clock_class) :
1217 NULL);
1218 goto end;
1219 }
fe13b5c0
PP
1220 }
1221
726106d3
PP
1222 ret = check_packet_header_type_has_no_clock_class(trace);
1223 if (ret) {
1224 /* check_packet_header_type_has_no_clock_class() logs errors */
1225 goto end;
1226 }
1227
09840de5
PP
1228 /*
1229 * We're about to freeze both the trace and the stream class.
1230 * Also, each event class contained in this stream class are
1231 * already frozen.
1232 *
1233 * This trace, this stream class, and all its event classes
1234 * should be valid at this point.
1235 *
1236 * Validate trace and stream class first, then each event
1237 * class of this stream class can be validated individually.
1238 */
1239 packet_header_type =
094ff7c0 1240 bt_trace_common_borrow_packet_header_field_type(trace);
09840de5 1241 packet_context_type =
094ff7c0 1242 bt_stream_class_common_borrow_packet_context_field_type(stream_class);
09840de5 1243 event_header_type =
094ff7c0 1244 bt_stream_class_common_borrow_event_header_field_type(stream_class);
09840de5 1245 stream_event_ctx_type =
094ff7c0 1246 bt_stream_class_common_borrow_event_context_field_type(stream_class);
95c09b3a
PP
1247
1248 BT_LOGD("Validating trace and stream class field types.");
50842bdc 1249 ret = bt_validate_class_types(trace->environment,
09840de5
PP
1250 packet_header_type, packet_context_type, event_header_type,
1251 stream_event_ctx_type, NULL, NULL, trace->valid,
1252 stream_class->valid, 1, &trace_sc_validation_output,
3dca2276 1253 trace_sc_validation_flags, copy_field_type_func);
09840de5 1254
2bd7f864 1255 if (ret) {
09840de5
PP
1256 /*
1257 * This means something went wrong during the validation
1258 * process, not that the objects are invalid.
1259 */
95c09b3a
PP
1260 BT_LOGE("Failed to validate trace and stream class field types: "
1261 "ret=%d", ret);
2bd7f864
JG
1262 goto end;
1263 }
1264
09840de5
PP
1265 if ((trace_sc_validation_output.valid_flags &
1266 trace_sc_validation_flags) !=
1267 trace_sc_validation_flags) {
1268 /* Invalid trace/stream class */
95c09b3a
PP
1269 BT_LOGW("Invalid trace or stream class field types: "
1270 "valid-flags=0x%x",
1271 trace_sc_validation_output.valid_flags);
09840de5
PP
1272 ret = -1;
1273 goto end;
1274 }
1275
1276 if (event_class_count > 0) {
50842bdc 1277 ec_validation_outputs = g_new0(struct bt_validation_output,
09840de5
PP
1278 event_class_count);
1279 if (!ec_validation_outputs) {
95c09b3a 1280 BT_LOGE_STR("Failed to allocate one validation output structure.");
09840de5
PP
1281 ret = -1;
1282 goto end;
1283 }
1284 }
1285
1286 /* Validate each event class individually */
6474e016 1287 for (i = 0; i < event_class_count; i++) {
3dca2276 1288 struct bt_event_class_common *event_class =
094ff7c0 1289 bt_stream_class_common_borrow_event_class_by_index(
9ac68eb1 1290 stream_class, i);
3dca2276
PP
1291 struct bt_field_type_common *event_context_type = NULL;
1292 struct bt_field_type_common *event_payload_type = NULL;
09840de5
PP
1293
1294 event_context_type =
094ff7c0
PP
1295 bt_event_class_common_borrow_context_field_type(
1296 event_class);
09840de5 1297 event_payload_type =
094ff7c0
PP
1298 bt_event_class_common_borrow_payload_field_type(
1299 event_class);
09840de5
PP
1300
1301 /*
1302 * It is important to use the field types returned by
1303 * the previous trace and stream class validation here
1304 * because copies could have been made.
1305 */
95c09b3a
PP
1306 BT_LOGD("Validating event class's field types: "
1307 "addr=%p, name=\"%s\", id=%" PRId64,
3dca2276
PP
1308 event_class, bt_event_class_common_get_name(event_class),
1309 bt_event_class_common_get_id(event_class));
50842bdc 1310 ret = bt_validate_class_types(trace->environment,
09840de5
PP
1311 trace_sc_validation_output.packet_header_type,
1312 trace_sc_validation_output.packet_context_type,
1313 trace_sc_validation_output.event_header_type,
1314 trace_sc_validation_output.stream_event_ctx_type,
1315 event_context_type, event_payload_type,
1316 1, 1, event_class->valid, &ec_validation_outputs[i],
3dca2276 1317 ec_validation_flags, copy_field_type_func);
09840de5
PP
1318
1319 if (ret) {
95c09b3a
PP
1320 BT_LOGE("Failed to validate event class field types: "
1321 "ret=%d", ret);
09840de5
PP
1322 goto end;
1323 }
1324
1325 if ((ec_validation_outputs[i].valid_flags &
1326 ec_validation_flags) != ec_validation_flags) {
1327 /* Invalid event class */
95c09b3a
PP
1328 BT_LOGW("Invalid event class field types: "
1329 "valid-flags=0x%x",
1330 ec_validation_outputs[i].valid_flags);
09840de5
PP
1331 ret = -1;
1332 goto end;
1333 }
1334 }
1335
3dca2276 1336 stream_id = bt_stream_class_common_get_id(stream_class);
ef0c4a15
JG
1337 if (stream_id < 0) {
1338 stream_id = trace->next_stream_id++;
9ac68eb1 1339 if (stream_id < 0) {
95c09b3a 1340 BT_LOGE_STR("No more stream class IDs available.");
9ac68eb1
PP
1341 ret = -1;
1342 goto end;
1343 }
ef0c4a15
JG
1344
1345 /* Try to assign a new stream id */
1346 for (i = 0; i < trace->stream_classes->len; i++) {
3dca2276 1347 if (stream_id == bt_stream_class_common_get_id(
ef0c4a15
JG
1348 trace->stream_classes->pdata[i])) {
1349 /* Duplicate stream id found */
95c09b3a
PP
1350 BT_LOGW("Duplicate stream class ID: "
1351 "id=%" PRId64, (int64_t) stream_id);
ef0c4a15
JG
1352 ret = -1;
1353 goto end;
1354 }
1355 }
1356
3dca2276 1357 if (bt_stream_class_common_set_id_no_check(stream_class,
95c09b3a 1358 stream_id)) {
ef0c4a15 1359 /* TODO Should retry with a different stream id */
95c09b3a
PP
1360 BT_LOGE("Cannot set stream class's ID: "
1361 "id=%" PRId64, (int64_t) stream_id);
ef0c4a15
JG
1362 ret = -1;
1363 goto end;
1364 }
1365 }
1366
e011d2c1
PP
1367 /*
1368 * At this point all the field types in the validation output
1369 * are valid. Validate the semantics of some scopes according to
1370 * the CTF specification.
1371 */
1372 if (!packet_header_field_type_is_valid(trace,
1373 trace_sc_validation_output.packet_header_type)) {
95c09b3a 1374 BT_LOGW_STR("Invalid trace's packet header field type.");
e011d2c1
PP
1375 ret = -1;
1376 goto end;
1377 }
1378
1379 if (!packet_context_field_type_is_valid(trace,
1380 stream_class,
3dca2276
PP
1381 trace_sc_validation_output.packet_context_type,
1382 check_ts_begin_end_mapped)) {
95c09b3a 1383 BT_LOGW_STR("Invalid stream class's packet context field type.");
e011d2c1
PP
1384 ret = -1;
1385 goto end;
1386 }
1387
1388 if (!event_header_field_type_is_valid(trace,
1389 stream_class,
1390 trace_sc_validation_output.event_header_type)) {
95c09b3a 1391 BT_LOGW_STR("Invalid steam class's event header field type.");
e011d2c1
PP
1392 ret = -1;
1393 goto end;
1394 }
1395
1396 /*
1397 * Now is the time to automatically map specific field types of
1398 * the stream class's packet context and event header field
1399 * types to the stream class's clock's class if they are not
1400 * mapped to a clock class yet. We do it here because we know
1401 * that after this point, everything is frozen so it won't be
1402 * possible for the user to modify the stream class's clock, or
1403 * to map those field types to other clock classes.
1404 */
3dca2276
PP
1405 if (map_clock_classes_func) {
1406 if (map_clock_classes_func(stream_class,
e011d2c1
PP
1407 trace_sc_validation_output.packet_context_type,
1408 trace_sc_validation_output.event_header_type)) {
3dca2276 1409 /* map_clock_classes_func() logs errors */
e011d2c1
PP
1410 ret = -1;
1411 goto end;
1412 }
1413 }
1414
e6a8e8e4 1415 bt_object_set_parent(stream_class, trace);
ef0c4a15
JG
1416 g_ptr_array_add(trace->stream_classes, stream_class);
1417
1418 /*
09840de5
PP
1419 * At this point we know that the function will be successful.
1420 * Therefore we can replace the trace and stream class field
1421 * types with what's in their validation output structure and
1422 * mark them as valid. We can also replace the field types of
1423 * all the event classes of the stream class and mark them as
1424 * valid.
1425 */
50842bdc 1426 bt_validation_replace_types(trace, stream_class, NULL,
09840de5
PP
1427 &trace_sc_validation_output, trace_sc_validation_flags);
1428 trace->valid = 1;
1429 stream_class->valid = 1;
1430
1431 /*
50842bdc 1432 * Put what was not moved in bt_validation_replace_types().
09840de5 1433 */
50842bdc 1434 bt_validation_output_put_types(&trace_sc_validation_output);
09840de5 1435
6474e016 1436 for (i = 0; i < event_class_count; i++) {
3dca2276 1437 struct bt_event_class_common *event_class =
094ff7c0 1438 bt_stream_class_common_borrow_event_class_by_index(
9ac68eb1 1439 stream_class, i);
09840de5 1440
50842bdc 1441 bt_validation_replace_types(NULL, NULL, event_class,
09840de5
PP
1442 &ec_validation_outputs[i], ec_validation_flags);
1443 event_class->valid = 1;
09840de5
PP
1444
1445 /*
1446 * Put what was not moved in
50842bdc 1447 * bt_validation_replace_types().
09840de5 1448 */
50842bdc 1449 bt_validation_output_put_types(&ec_validation_outputs[i]);
09840de5
PP
1450 }
1451
09840de5
PP
1452 /*
1453 * Freeze the trace and the stream class.
1454 */
3dca2276
PP
1455 bt_stream_class_common_freeze(stream_class);
1456 bt_trace_common_freeze(trace);
09840de5 1457
2a3ced3c
PP
1458 /*
1459 * It is safe to set the stream class's unique clock class
1460 * now because the stream class is frozen.
1461 */
1462 if (expected_clock_class) {
1463 BT_MOVE(stream_class->clock_class, expected_clock_class);
1464 }
1465
95c09b3a
PP
1466 BT_LOGD("Added stream class to trace: "
1467 "trace-addr=%p, trace-name=\"%s\", "
1468 "stream-class-addr=%p, stream-class-name=\"%s\", "
1469 "stream-class-id=%" PRId64,
3dca2276
PP
1470 trace, bt_trace_common_get_name(trace),
1471 stream_class, bt_stream_class_common_get_name(stream_class),
1472 bt_stream_class_common_get_id(stream_class));
95c09b3a 1473
ef0c4a15 1474end:
d3814b54 1475 if (ret) {
e6a8e8e4 1476 bt_object_set_parent(stream_class, NULL);
09840de5
PP
1477
1478 if (ec_validation_outputs) {
6474e016 1479 for (i = 0; i < event_class_count; i++) {
50842bdc 1480 bt_validation_output_put_types(
09840de5
PP
1481 &ec_validation_outputs[i]);
1482 }
1483 }
d3814b54 1484 }
09840de5
PP
1485
1486 g_free(ec_validation_outputs);
50842bdc 1487 bt_validation_output_put_types(&trace_sc_validation_output);
2a3ced3c 1488 bt_put(expected_clock_class);
ef0c4a15
JG
1489 return ret;
1490}
1491
3dca2276
PP
1492int bt_trace_add_stream_class(struct bt_trace *trace,
1493 struct bt_stream_class *stream_class)
1494{
1495 int ret = 0;
1496
1497 if (!trace) {
1498 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1499 ret = -1;
1500 goto end;
1501 }
1502
1503 if (trace->is_static) {
1504 BT_LOGW_STR("Invalid parameter: trace is static.");
1505 ret = -1;
1506 goto end;
1507 }
1508
1509 ret = bt_trace_common_add_stream_class(BT_TO_COMMON(trace),
1510 BT_TO_COMMON(stream_class),
1511 (bt_validation_flag_copy_field_type_func) bt_field_type_copy,
1512 NULL, NULL, true);
1513 if (ret) {
1514 goto end;
1515 }
1516
1517 /* Notifiy listeners of the trace's schema modification. */
1518 bt_stream_class_common_visit(BT_TO_COMMON(stream_class),
1519 bt_trace_object_modification, trace);
1520
1521end:
1522 return ret;
1523}
1524
50842bdc 1525int64_t bt_trace_get_stream_count(struct bt_trace *trace)
c1e730fe 1526{
3dca2276 1527 return bt_trace_common_get_stream_count(BT_TO_COMMON(trace));
c1e730fe
PP
1528}
1529
094ff7c0
PP
1530struct bt_stream *bt_trace_borrow_stream_by_index(
1531 struct bt_trace *trace, uint64_t index)
c1e730fe 1532{
094ff7c0 1533 return BT_FROM_COMMON(bt_trace_common_borrow_stream_by_index(
3dca2276 1534 BT_TO_COMMON(trace), index));
c1e730fe
PP
1535}
1536
50842bdc 1537int64_t bt_trace_get_stream_class_count(struct bt_trace *trace)
ef0c4a15 1538{
3dca2276 1539 return bt_trace_common_get_stream_class_count(BT_TO_COMMON(trace));
ef0c4a15
JG
1540}
1541
094ff7c0 1542struct bt_stream_class *bt_trace_borrow_stream_class_by_index(
50842bdc 1543 struct bt_trace *trace, uint64_t index)
ef0c4a15 1544{
094ff7c0 1545 return BT_FROM_COMMON(bt_trace_common_borrow_stream_class_by_index(
3dca2276 1546 BT_TO_COMMON(trace), index));
ef0c4a15
JG
1547}
1548
094ff7c0 1549struct bt_stream_class *bt_trace_borrow_stream_class_by_id(
3dca2276 1550 struct bt_trace *trace, uint64_t id)
4841ccc1 1551{
3dca2276 1552 return BT_FROM_COMMON(
094ff7c0 1553 bt_trace_common_borrow_stream_class_by_id(
3dca2276 1554 BT_TO_COMMON(trace), id));
4841ccc1
PP
1555}
1556
094ff7c0 1557struct bt_clock_class *bt_trace_borrow_clock_class_by_name(
50842bdc 1558 struct bt_trace *trace, const char *name)
7e4347a3 1559{
094ff7c0 1560 return bt_trace_common_borrow_clock_class_by_name(BT_TO_COMMON(trace),
3dca2276 1561 name);
7e4347a3
PP
1562}
1563
c9d90a34 1564BT_HIDDEN
3dca2276 1565bt_bool bt_trace_common_has_clock_class(struct bt_trace_common *trace,
50842bdc 1566 struct bt_clock_class *clock_class)
c9d90a34
PP
1567{
1568 struct search_query query = { .value = clock_class, .found = 0 };
1569
f6ccaed9
PP
1570 BT_ASSERT(trace);
1571 BT_ASSERT(clock_class);
c9d90a34 1572
3dca2276 1573 g_ptr_array_foreach(trace->clock_classes, value_exists, &query);
c9d90a34
PP
1574 return query.found;
1575}
1576
50842bdc
PP
1577enum bt_byte_order bt_trace_get_native_byte_order(
1578 struct bt_trace *trace)
4ed90fb3 1579{
3dca2276 1580 return bt_trace_common_get_native_byte_order(BT_TO_COMMON(trace));
4ed90fb3
JG
1581}
1582
3dca2276
PP
1583BT_HIDDEN
1584int bt_trace_common_set_native_byte_order(struct bt_trace_common *trace,
1585 enum bt_byte_order byte_order, bool allow_unspecified)
bc37ae52
JG
1586{
1587 int ret = 0;
bc37ae52 1588
95c09b3a
PP
1589 if (!trace) {
1590 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1591 ret = -1;
1592 goto end;
1593 }
1594
1595 if (trace->frozen) {
1596 BT_LOGW("Invalid parameter: trace is frozen: "
1597 "addr=%p, name=\"%s\"",
3dca2276 1598 trace, bt_trace_common_get_name(trace));
bc37ae52
JG
1599 ret = -1;
1600 goto end;
1601 }
1602
3dca2276
PP
1603 if (byte_order == BT_BYTE_ORDER_UNSPECIFIED && !allow_unspecified) {
1604 BT_LOGW("Invalid parameter: BT_BYTE_ORDER_UNSPECIFIED byte order is not allowed: "
d41cff38 1605 "addr=%p, name=\"%s\"",
3dca2276 1606 trace, bt_trace_common_get_name(trace));
d41cff38
PP
1607 ret = -1;
1608 goto end;
1609 }
1610
50842bdc
PP
1611 if (byte_order != BT_BYTE_ORDER_LITTLE_ENDIAN &&
1612 byte_order != BT_BYTE_ORDER_BIG_ENDIAN &&
1613 byte_order != BT_BYTE_ORDER_NETWORK) {
95c09b3a
PP
1614 BT_LOGW("Invalid parameter: invalid byte order: "
1615 "addr=%p, name=\"%s\", bo=%s",
3dca2276
PP
1616 trace, bt_trace_common_get_name(trace),
1617 bt_common_byte_order_string(byte_order));
bc37ae52
JG
1618 ret = -1;
1619 goto end;
1620 }
1621
dc3fffef 1622 trace->native_byte_order = byte_order;
95c09b3a
PP
1623 BT_LOGV("Set trace's native byte order: "
1624 "addr=%p, name=\"%s\", bo=%s",
3dca2276
PP
1625 trace, bt_trace_common_get_name(trace),
1626 bt_common_byte_order_string(byte_order));
dc3fffef 1627
bc37ae52
JG
1628end:
1629 return ret;
1630}
1631
3dca2276
PP
1632int bt_trace_set_native_byte_order(struct bt_trace *trace,
1633 enum bt_byte_order byte_order)
1634{
1635 return bt_trace_common_set_native_byte_order(BT_TO_COMMON(trace),
1636 byte_order, true);
1637}
1638
094ff7c0 1639struct bt_field_type *bt_trace_borrow_packet_header_field_type(
50842bdc 1640 struct bt_trace *trace)
d246b111 1641{
094ff7c0 1642 return BT_FROM_COMMON(bt_trace_common_borrow_packet_header_field_type(
3dca2276 1643 BT_TO_COMMON(trace)));
d246b111
JG
1644}
1645
3dca2276
PP
1646BT_HIDDEN
1647int bt_trace_common_set_packet_header_field_type(struct bt_trace_common *trace,
1648 struct bt_field_type_common *packet_header_type)
d246b111
JG
1649{
1650 int ret = 0;
1651
95c09b3a
PP
1652 if (!trace) {
1653 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1654 ret = -1;
1655 goto end;
1656 }
1657
1658 if (trace->frozen) {
1659 BT_LOGW("Invalid parameter: trace is frozen: "
1660 "addr=%p, name=\"%s\"",
3dca2276 1661 trace, bt_trace_common_get_name(trace));
d246b111
JG
1662 ret = -1;
1663 goto end;
1664 }
1665
835b2d10
JG
1666 /* packet_header_type must be a structure. */
1667 if (packet_header_type &&
3dca2276 1668 packet_header_type->id != BT_FIELD_TYPE_ID_STRUCT) {
95c09b3a
PP
1669 BT_LOGW("Invalid parameter: packet header field type must be a structure field type if it exists: "
1670 "addr=%p, name=\"%s\", ft-addr=%p, ft-id=%s",
3dca2276 1671 trace, bt_trace_common_get_name(trace),
95c09b3a 1672 packet_header_type,
3dca2276 1673 bt_common_field_type_id_string(packet_header_type->id));
d246b111
JG
1674 ret = -1;
1675 goto end;
1676 }
1677
3dca2276
PP
1678 bt_put(trace->packet_header_field_type);
1679 trace->packet_header_field_type = bt_get(packet_header_type);
95c09b3a
PP
1680 BT_LOGV("Set trace's packet header field type: "
1681 "addr=%p, name=\"%s\", packet-context-ft-addr=%p",
3dca2276 1682 trace, bt_trace_common_get_name(trace), packet_header_type);
d246b111
JG
1683end:
1684 return ret;
1685}
1686
3dca2276
PP
1687int bt_trace_set_packet_header_field_type(struct bt_trace *trace,
1688 struct bt_field_type *packet_header_type)
1689{
1690 return bt_trace_common_set_packet_header_field_type(BT_TO_COMMON(trace),
1691 (void *) packet_header_type);
1692}
1693
8bf65fbd 1694static
544d0515 1695int64_t get_stream_class_count(void *element)
8bf65fbd 1696{
50842bdc
PP
1697 return bt_trace_get_stream_class_count(
1698 (struct bt_trace *) element);
8bf65fbd
JG
1699}
1700
1701static
1702void *get_stream_class(void *element, int i)
1703{
50842bdc
PP
1704 return bt_trace_get_stream_class_by_index(
1705 (struct bt_trace *) element, i);
8bf65fbd
JG
1706}
1707
1708static
50842bdc 1709int visit_stream_class(void *object, bt_visitor visitor,void *data)
8bf65fbd 1710{
50842bdc 1711 return bt_stream_class_visit(object, visitor, data);
8bf65fbd
JG
1712}
1713
50842bdc
PP
1714int bt_trace_visit(struct bt_trace *trace,
1715 bt_visitor visitor, void *data)
8bf65fbd
JG
1716{
1717 int ret;
50842bdc
PP
1718 struct bt_visitor_object obj = {
1719 .object = trace,
1720 .type = BT_VISITOR_OBJECT_TYPE_TRACE
1721 };
8bf65fbd 1722
95c09b3a
PP
1723 if (!trace) {
1724 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1725 ret = -1;
1726 goto end;
1727 }
1728
1729 if (!visitor) {
1730 BT_LOGW_STR("Invalid parameter: visitor is NULL.");
8bf65fbd
JG
1731 ret = -1;
1732 goto end;
1733 }
1734
95c09b3a 1735 BT_LOGV("Visiting trace: addr=%p, name=\"%s\"",
50842bdc 1736 trace, bt_trace_get_name(trace));
d9a13d86 1737 ret = visitor_helper(&obj, get_stream_class_count,
8bf65fbd
JG
1738 get_stream_class, visit_stream_class, visitor, data);
1739end:
1740 return ret;
1741}
1742
1743static
50842bdc 1744int invoke_listener(struct bt_visitor_object *object, void *data)
8bf65fbd 1745{
9b888ff3 1746 struct listener_wrapper *listener_wrapper = data;
8bf65fbd 1747
d9a13d86 1748 listener_wrapper->listener(object, listener_wrapper->data);
9b888ff3 1749 return 0;
8bf65fbd
JG
1750}
1751
95c09b3a 1752// TODO: add logging to this function once we use it internally.
50842bdc
PP
1753int bt_trace_add_listener(struct bt_trace *trace,
1754 bt_listener_cb listener, void *listener_data)
2204c381
JG
1755{
1756 int ret = 0;
50ad4244
JG
1757 struct listener_wrapper *listener_wrapper =
1758 g_new0(struct listener_wrapper, 1);
2204c381 1759
50ad4244 1760 if (!trace || !listener || !listener_wrapper) {
2204c381
JG
1761 ret = -1;
1762 goto error;
1763 }
1764
50ad4244
JG
1765 listener_wrapper->listener = listener;
1766 listener_wrapper->data = listener_data;
8bf65fbd 1767
50ad4244 1768 /* Visit the current schema. */
50842bdc 1769 ret = bt_trace_visit(trace, invoke_listener, listener_wrapper);
8bf65fbd
JG
1770 if (ret) {
1771 goto error;
1772 }
1773
50ad4244
JG
1774 /*
1775 * Add listener to the array of callbacks which will be invoked on
1776 * schema changes.
1777 */
1778 g_ptr_array_add(trace->listeners, listener_wrapper);
2204c381
JG
1779 return ret;
1780error:
50ad4244 1781 g_free(listener_wrapper);
2204c381
JG
1782 return ret;
1783}
1784
bc37ae52 1785BT_HIDDEN
50842bdc 1786int bt_trace_object_modification(struct bt_visitor_object *object,
9b888ff3
JG
1787 void *trace_ptr)
1788{
1789 size_t i;
50842bdc 1790 struct bt_trace *trace = trace_ptr;
9b888ff3 1791
f6ccaed9
PP
1792 BT_ASSERT(trace);
1793 BT_ASSERT(object);
9b888ff3
JG
1794
1795 if (trace->listeners->len == 0) {
1796 goto end;
1797 }
1798
1799 for (i = 0; i < trace->listeners->len; i++) {
1800 struct listener_wrapper *listener =
1801 g_ptr_array_index(trace->listeners, i);
1802
d9a13d86 1803 listener->listener(object, listener->data);
9b888ff3
JG
1804 }
1805end:
1806 return 0;
1807}
1808
50842bdc 1809bt_bool bt_trace_is_static(struct bt_trace *trace)
5acf2ae6 1810{
d975f66c
PP
1811 BT_ASSERT_PRE_NON_NULL(trace, "Trace");
1812 return trace->is_static;
5acf2ae6
PP
1813}
1814
50842bdc 1815int bt_trace_set_is_static(struct bt_trace *trace)
5acf2ae6
PP
1816{
1817 int ret = 0;
3602afb0 1818 size_t i;
5acf2ae6
PP
1819
1820 if (!trace) {
95c09b3a 1821 BT_LOGW_STR("Invalid parameter: trace is NULL.");
5acf2ae6
PP
1822 ret = -1;
1823 goto end;
1824 }
1825
3dca2276 1826 ret = check_packet_header_type_has_no_clock_class(BT_TO_COMMON(trace));
726106d3
PP
1827 if (ret) {
1828 /* check_packet_header_type_has_no_clock_class() logs errors */
1829 goto end;
1830 }
1831
c55a9f58 1832 trace->is_static = BT_TRUE;
3dca2276 1833 bt_trace_common_freeze(BT_TO_COMMON(trace));
95c09b3a 1834 BT_LOGV("Set trace static: addr=%p, name=\"%s\"",
50842bdc 1835 trace, bt_trace_get_name(trace));
5acf2ae6 1836
3602afb0
PP
1837 /* Call all the "trace is static" listeners */
1838 for (i = 0; i < trace->is_static_listeners->len; i++) {
50842bdc 1839 struct bt_trace_is_static_listener_elem elem =
3602afb0 1840 g_array_index(trace->is_static_listeners,
50842bdc 1841 struct bt_trace_is_static_listener_elem, i);
3602afb0
PP
1842
1843 if (elem.func) {
1844 elem.func(trace, elem.data);
1845 }
1846 }
1847
1848end:
1849 return ret;
1850}
1851
50842bdc
PP
1852int bt_trace_add_is_static_listener(struct bt_trace *trace,
1853 bt_trace_is_static_listener listener,
1854 bt_trace_listener_removed listener_removed, void *data)
3602afb0
PP
1855{
1856 int i;
50842bdc 1857 struct bt_trace_is_static_listener_elem new_elem = {
3602afb0 1858 .func = listener,
8480c8cc 1859 .removed = listener_removed,
3602afb0
PP
1860 .data = data,
1861 };
1862
1863 if (!trace) {
1864 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1865 i = -1;
1866 goto end;
1867 }
1868
1869 if (!listener) {
1870 BT_LOGW_STR("Invalid parameter: listener is NULL.");
1871 i = -1;
1872 goto end;
1873 }
1874
1875 if (trace->is_static) {
1876 BT_LOGW("Invalid parameter: trace is already static: "
1877 "addr=%p, name=\"%s\"",
50842bdc 1878 trace, bt_trace_get_name(trace));
3602afb0
PP
1879 i = -1;
1880 goto end;
1881 }
1882
8480c8cc
PP
1883 if (trace->in_remove_listener) {
1884 BT_LOGW("Cannot call this function during the execution of a remove listener: "
1885 "addr=%p, name=\"%s\"",
50842bdc 1886 trace, bt_trace_get_name(trace));
8480c8cc
PP
1887 i = -1;
1888 goto end;
1889 }
1890
3602afb0
PP
1891 /* Find the next available spot */
1892 for (i = 0; i < trace->is_static_listeners->len; i++) {
50842bdc 1893 struct bt_trace_is_static_listener_elem elem =
3602afb0 1894 g_array_index(trace->is_static_listeners,
50842bdc 1895 struct bt_trace_is_static_listener_elem, i);
3602afb0
PP
1896
1897 if (!elem.func) {
1898 break;
1899 }
1900 }
1901
1902 if (i == trace->is_static_listeners->len) {
1903 g_array_append_val(trace->is_static_listeners, new_elem);
1904 } else {
1905 g_array_insert_val(trace->is_static_listeners, i, new_elem);
1906 }
1907
1908 BT_LOGV("Added \"trace is static\" listener: "
1909 "trace-addr=%p, trace-name=\"%s\", func-addr=%p, "
1910 "data-addr=%p, listener-id=%d",
50842bdc 1911 trace, bt_trace_get_name(trace), listener, data, i);
3602afb0
PP
1912
1913end:
1914 return i;
1915}
1916
50842bdc
PP
1917int bt_trace_remove_is_static_listener(
1918 struct bt_trace *trace, int listener_id)
3602afb0
PP
1919{
1920 int ret = 0;
50842bdc 1921 struct bt_trace_is_static_listener_elem *elem;
3602afb0
PP
1922
1923 if (!trace) {
1924 BT_LOGW_STR("Invalid parameter: trace is NULL.");
1925 ret = -1;
1926 goto end;
1927 }
1928
8480c8cc
PP
1929 if (trace->in_remove_listener) {
1930 BT_LOGW("Cannot call this function during the execution of a remove listener: "
1931 "addr=%p, name=\"%s\", listener-id=%d",
50842bdc 1932 trace, bt_trace_get_name(trace),
8480c8cc
PP
1933 listener_id);
1934 ret = -1;
1935 goto end;
1936 }
1937
3602afb0
PP
1938 if (listener_id < 0) {
1939 BT_LOGW("Invalid listener ID: must be zero or positive: "
1940 "listener-id=%d", listener_id);
1941 ret = -1;
1942 goto end;
1943 }
1944
1945 if (listener_id >= trace->is_static_listeners->len) {
1946 BT_LOGW("Invalid parameter: no listener with this listener ID: "
1947 "addr=%p, name=\"%s\", listener-id=%d",
50842bdc 1948 trace, bt_trace_get_name(trace),
3602afb0
PP
1949 listener_id);
1950 ret = -1;
1951 goto end;
1952 }
1953
1954 elem = &g_array_index(trace->is_static_listeners,
50842bdc 1955 struct bt_trace_is_static_listener_elem,
3602afb0
PP
1956 listener_id);
1957 if (!elem->func) {
1958 BT_LOGW("Invalid parameter: no listener with this listener ID: "
1959 "addr=%p, name=\"%s\", listener-id=%d",
50842bdc 1960 trace, bt_trace_get_name(trace),
3602afb0
PP
1961 listener_id);
1962 ret = -1;
1963 goto end;
1964 }
1965
8480c8cc
PP
1966 if (elem->removed) {
1967 /* Call remove listener */
1968 BT_LOGV("Calling remove listener: "
1969 "trace-addr=%p, trace-name=\"%s\", "
50842bdc 1970 "listener-id=%d", trace, bt_trace_get_name(trace),
8480c8cc
PP
1971 listener_id);
1972 trace->in_remove_listener = BT_TRUE;
1973 elem->removed(trace, elem->data);
1974 trace->in_remove_listener = BT_FALSE;
1975 }
1976
3602afb0 1977 elem->func = NULL;
8480c8cc 1978 elem->removed = NULL;
3602afb0
PP
1979 elem->data = NULL;
1980 BT_LOGV("Removed \"trace is static\" listener: "
1981 "trace-addr=%p, trace-name=\"%s\", "
50842bdc 1982 "listener-id=%d", trace, bt_trace_get_name(trace),
3602afb0
PP
1983 listener_id);
1984
5acf2ae6
PP
1985end:
1986 return ret;
1987}
312c056a
PP
1988
1989struct bt_packet_header_field *bt_trace_create_packet_header_field(
1990 struct bt_trace *trace)
1991{
1992 struct bt_field_wrapper *field_wrapper;
1993
1994 BT_ASSERT_PRE_NON_NULL(trace, "Trace");
1995 BT_ASSERT_PRE(trace->common.packet_header_field_type,
1996 "Trace has no packet header field type: %!+t",
1997 trace);
1998 field_wrapper = bt_field_wrapper_create(
1999 &trace->packet_header_field_pool,
2000 (void *) trace->common.packet_header_field_type);
2001 if (!field_wrapper) {
2002 BT_LIB_LOGE("Cannot allocate one packet header field from trace: "
2003 "%![trace-]+t", trace);
2004 goto error;
2005 }
2006
2007 BT_ASSERT(field_wrapper->field);
2008 bt_trace_common_freeze(BT_TO_COMMON(trace));
2009 goto end;
2010
2011error:
2012 if (field_wrapper) {
2013 bt_field_wrapper_destroy(field_wrapper);
2014 field_wrapper = NULL;
2015 }
2016
2017end:
2018 return (void *) field_wrapper;
2019}
This page took 0.149719 seconds and 4 git commands to generate.