lib: metadata: transform fast path precond. checks to BT_ASSERT_PRE()
[babeltrace.git] / lib / ctf-ir / stream-class.c
CommitLineData
11b0cdc8 1/*
3f043b05 2 * stream-class.c
11b0cdc8 3 *
d2dc44b6 4 * Babeltrace CTF IR - Stream Class
11b0cdc8 5 *
de9dd397 6 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
11b0cdc8
JG
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
d2f71f12
PP
29#define BT_LOG_TAG "STREAM-CLASS"
30#include <babeltrace/lib-logging-internal.h>
31
11b0cdc8 32#include <babeltrace/ctf-writer/clock.h>
ac0c6bdd
PP
33#include <babeltrace/ctf-writer/clock-internal.h>
34#include <babeltrace/ctf-ir/clock-class-internal.h>
11b0cdc8 35#include <babeltrace/ctf-writer/event.h>
272df73e 36#include <babeltrace/ctf-ir/event-class-internal.h>
11b0cdc8 37#include <babeltrace/ctf-ir/event-internal.h>
2e33ac5a
PP
38#include <babeltrace/ctf-ir/field-types-internal.h>
39#include <babeltrace/ctf-ir/fields-internal.h>
11b0cdc8
JG
40#include <babeltrace/ctf-writer/stream.h>
41#include <babeltrace/ctf-ir/stream-class-internal.h>
09840de5 42#include <babeltrace/ctf-ir/validation-internal.h>
8bf65fbd 43#include <babeltrace/ctf-ir/visitor-internal.h>
11b0cdc8 44#include <babeltrace/ctf-writer/functor-internal.h>
654c1444 45#include <babeltrace/ctf-ir/utils.h>
2a3ced3c 46#include <babeltrace/ctf-ir/utils-internal.h>
83509119 47#include <babeltrace/ref.h>
3d9990ac
PP
48#include <babeltrace/compiler-internal.h>
49#include <babeltrace/align-internal.h>
50#include <babeltrace/endian-internal.h>
f6ccaed9 51#include <babeltrace/assert-internal.h>
d975f66c 52#include <babeltrace/assert-pre-internal.h>
dc3fffef 53#include <inttypes.h>
544d0515 54#include <stdint.h>
e011d2c1 55#include <stdbool.h>
11b0cdc8
JG
56
57static
50842bdc 58void bt_stream_class_destroy(struct bt_object *obj);
11b0cdc8 59static
50842bdc 60int init_event_header(struct bt_stream_class *stream_class);
11b0cdc8 61static
50842bdc 62int init_packet_context(struct bt_stream_class *stream_class);
11b0cdc8 63
50842bdc 64struct bt_stream_class *bt_stream_class_create(const char *name)
11b0cdc8 65{
50842bdc 66 struct bt_stream_class *stream_class;
12c8a1a3 67 int ret;
e0e2946b 68
d2f71f12 69 BT_LOGD("Creating default stream class object: name=\"%s\"", name);
50842bdc 70 stream_class = bt_stream_class_create_empty(name);
e0e2946b 71 if (!stream_class) {
d2f71f12 72 BT_LOGD_STR("Cannot create empty stream class.");
e0e2946b
PP
73 goto error;
74 }
75
76 ret = init_event_header(stream_class);
77 if (ret) {
d2f71f12 78 BT_LOGE_STR("Cannot initialize stream class's event header field type.");
e0e2946b
PP
79 goto error;
80 }
81
82 ret = init_packet_context(stream_class);
83 if (ret) {
d2f71f12 84 BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
e0e2946b
PP
85 goto error;
86 }
87
d2f71f12
PP
88 BT_LOGD("Created default stream class object: addr=%p, name=\"%s\"",
89 stream_class, name);
e0e2946b
PP
90 return stream_class;
91
92error:
93 BT_PUT(stream_class);
94 return stream_class;
95}
96
50842bdc 97struct bt_stream_class *bt_stream_class_create_empty(const char *name)
e0e2946b 98{
50842bdc 99 struct bt_stream_class *stream_class = NULL;
11b0cdc8 100
d2f71f12
PP
101 BT_LOGD("Creating empty stream class object: name=\"%s\"", name);
102
50842bdc 103 stream_class = g_new0(struct bt_stream_class, 1);
11b0cdc8 104 if (!stream_class) {
d2f71f12 105 BT_LOGE_STR("Failed to allocate one stream class.");
11b0cdc8
JG
106 goto error;
107 }
108
109 stream_class->name = g_string_new(name);
110 stream_class->event_classes = g_ptr_array_new_with_free_func(
e6a8e8e4 111 (GDestroyNotify) bt_object_release);
11b0cdc8 112 if (!stream_class->event_classes) {
d2f71f12 113 BT_LOGE_STR("Failed to allocate a GPtrArray.");
83509119 114 goto error;
11b0cdc8
JG
115 }
116
0b9ce69f
JG
117 stream_class->event_classes_ht = g_hash_table_new_full(g_int64_hash,
118 g_int64_equal, g_free, NULL);
d2f71f12
PP
119 if (!stream_class->event_classes_ht) {
120 BT_LOGE_STR("Failed to allocate a GHashTable.");
121 goto error;
122 }
0b9ce69f 123
50842bdc 124 bt_object_init(stream_class, bt_stream_class_destroy);
d2f71f12
PP
125 BT_LOGD("Created empty stream class object: addr=%p, name=\"%s\"",
126 stream_class, name);
11b0cdc8
JG
127 return stream_class;
128
11b0cdc8 129error:
e0e2946b 130 BT_PUT(stream_class);
11b0cdc8
JG
131 return stream_class;
132}
133
50842bdc
PP
134struct bt_trace *bt_stream_class_get_trace(
135 struct bt_stream_class *stream_class)
142c5610 136{
d975f66c
PP
137 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
138 return bt_get(bt_stream_class_borrow_trace(stream_class));
142c5610
JG
139}
140
50842bdc
PP
141const char *bt_stream_class_get_name(
142 struct bt_stream_class *stream_class)
69dc4535 143{
d975f66c
PP
144 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
145 return stream_class->name->len > 0 ? stream_class->name->str : NULL;
69dc4535
JG
146}
147
50842bdc 148int bt_stream_class_set_name(struct bt_stream_class *stream_class,
3ea33115
JG
149 const char *name)
150{
151 int ret = 0;
152
d2f71f12
PP
153 if (!stream_class) {
154 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
155 ret = -1;
156 goto end;
157 }
158
159 if (stream_class->frozen) {
160 BT_LOGW("Invalid parameter: stream class is frozen: "
161 "addr=%p, name=\"%s\", id=%" PRId64,
50842bdc
PP
162 stream_class, bt_stream_class_get_name(stream_class),
163 bt_stream_class_get_id(stream_class));
3ea33115
JG
164 ret = -1;
165 goto end;
166 }
167
03be3bcd
PP
168 if (!name) {
169 g_string_assign(stream_class->name, "");
170 } else {
171 if (strlen(name) == 0) {
172 BT_LOGW("Invalid parameter: name is empty.");
173 ret = -1;
174 goto end;
175 }
176
177 g_string_assign(stream_class->name, name);
178 }
179
d2f71f12
PP
180 BT_LOGV("Set stream class's name: "
181 "addr=%p, name=\"%s\", id=%" PRId64,
50842bdc
PP
182 stream_class, bt_stream_class_get_name(stream_class),
183 bt_stream_class_get_id(stream_class));
3ea33115
JG
184end:
185 return ret;
186}
187
50842bdc
PP
188struct bt_ctf_clock *bt_stream_class_get_clock(
189 struct bt_stream_class *stream_class)
2f100782
JG
190{
191 struct bt_ctf_clock *clock = NULL;
192
d2f71f12
PP
193 if (!stream_class) {
194 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
195 goto end;
196 }
197
198 if (!stream_class->clock) {
199 BT_LOGV("Stream class has no clock: "
200 "addr=%p, name=\"%s\", id=%" PRId64,
50842bdc
PP
201 stream_class, bt_stream_class_get_name(stream_class),
202 bt_stream_class_get_id(stream_class));
2f100782
JG
203 goto end;
204 }
205
ac0c6bdd 206 clock = bt_get(stream_class->clock);
2f100782
JG
207end:
208 return clock;
209}
210
50842bdc 211int bt_stream_class_set_clock(struct bt_stream_class *stream_class,
11b0cdc8
JG
212 struct bt_ctf_clock *clock)
213{
214 int ret = 0;
50842bdc 215 struct bt_field_type *timestamp_field = NULL;
11b0cdc8 216
d2f71f12
PP
217 if (!stream_class || !clock) {
218 BT_LOGW("Invalid parameter: stream class or clock is NULL: "
219 "stream-class-addr=%p, clock-addr=%p",
220 stream_class, clock);
221 ret = -1;
222 goto end;
223 }
224
225 if (stream_class->frozen) {
226 BT_LOGW("Invalid parameter: stream class is frozen: "
227 "addr=%p, name=\"%s\", id=%" PRId64,
50842bdc
PP
228 stream_class, bt_stream_class_get_name(stream_class),
229 bt_stream_class_get_id(stream_class));
11b0cdc8
JG
230 ret = -1;
231 goto end;
232 }
233
ac0c6bdd
PP
234 /* Replace the current clock of this stream class. */
235 bt_put(stream_class->clock);
236 stream_class->clock = bt_get(clock);
d2f71f12
PP
237 BT_LOGV("Set stream class's clock: "
238 "addr=%p, name=\"%s\", id=%" PRId64 ", "
239 "clock-addr=%p, clock-name=\"%s\"",
50842bdc
PP
240 stream_class, bt_stream_class_get_name(stream_class),
241 bt_stream_class_get_id(stream_class),
d2f71f12
PP
242 stream_class->clock,
243 bt_ctf_clock_get_name(stream_class->clock));
11b0cdc8 244
11b0cdc8 245end:
ac0c6bdd 246 bt_put(timestamp_field);
11b0cdc8
JG
247 return ret;
248}
249
50842bdc 250int64_t bt_stream_class_get_id(struct bt_stream_class *stream_class)
2f100782
JG
251{
252 int64_t ret;
253
d975f66c 254 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
d2f71f12
PP
255
256 if (!stream_class->id_set) {
257 BT_LOGV("Stream class's ID is not set: addr=%p, name=\"%s\"",
258 stream_class,
50842bdc 259 bt_stream_class_get_name(stream_class));
9ac68eb1 260 ret = (int64_t) -1;
2f100782
JG
261 goto end;
262 }
263
9ac68eb1 264 ret = stream_class->id;
d975f66c 265
2f100782
JG
266end:
267 return ret;
268}
269
5ca83563 270BT_HIDDEN
50842bdc
PP
271void _bt_stream_class_set_id(
272 struct bt_stream_class *stream_class, int64_t id)
5ca83563 273{
f6ccaed9 274 BT_ASSERT(stream_class);
5ca83563
JG
275 stream_class->id = id;
276 stream_class->id_set = 1;
d2f71f12
PP
277 BT_LOGV("Set stream class's ID (internal): "
278 "addr=%p, name=\"%s\", id=%" PRId64,
50842bdc
PP
279 stream_class, bt_stream_class_get_name(stream_class),
280 bt_stream_class_get_id(stream_class));
5ca83563
JG
281}
282
9ac68eb1
PP
283struct event_class_set_stream_class_id_data {
284 int64_t stream_class_id;
29664b2a
PP
285 int ret;
286};
287
29664b2a 288BT_HIDDEN
50842bdc
PP
289int bt_stream_class_set_id_no_check(
290 struct bt_stream_class *stream_class, int64_t id)
2f100782 291{
50842bdc 292 _bt_stream_class_set_id(stream_class, id);
cf76ce92 293 return 0;
2f100782
JG
294}
295
50842bdc 296int bt_stream_class_set_id(struct bt_stream_class *stream_class,
9ac68eb1 297 uint64_t id_param)
29664b2a
PP
298{
299 int ret = 0;
9ac68eb1 300 int64_t id = (int64_t) id_param;
29664b2a 301
d2f71f12
PP
302 if (!stream_class) {
303 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
304 ret = -1;
305 goto end;
306 }
307
308 if (stream_class->frozen) {
309 BT_LOGW("Invalid parameter: stream class is frozen: "
310 "addr=%p, name=\"%s\", id=%" PRId64,
50842bdc
PP
311 stream_class, bt_stream_class_get_name(stream_class),
312 bt_stream_class_get_id(stream_class));
d2f71f12
PP
313 ret = -1;
314 goto end;
315 }
316
317 if (id < 0) {
318 BT_LOGW("Invalid parameter: invalid stream class's ID: "
319 "stream-class-addr=%p, stream-class-name=\"%s\", "
320 "stream-class-id=%" PRId64 ", id=%" PRIu64,
50842bdc
PP
321 stream_class, bt_stream_class_get_name(stream_class),
322 bt_stream_class_get_id(stream_class),
d2f71f12 323 id_param);
29664b2a
PP
324 ret = -1;
325 goto end;
326 }
327
50842bdc 328 ret = bt_stream_class_set_id_no_check(stream_class, id);
d2f71f12
PP
329 if (ret == 0) {
330 BT_LOGV("Set stream class's ID: "
331 "addr=%p, name=\"%s\", id=%" PRId64,
50842bdc
PP
332 stream_class, bt_stream_class_get_name(stream_class),
333 bt_stream_class_get_id(stream_class));
d2f71f12 334 }
29664b2a
PP
335end:
336 return ret;
337}
338
0d23acbe
PP
339static
340void event_class_exists(gpointer element, gpointer query)
341{
50842bdc 342 struct bt_event_class *event_class_a = element;
0d23acbe 343 struct search_query *search_query = query;
50842bdc 344 struct bt_event_class *event_class_b = search_query->value;
0d23acbe
PP
345 int64_t id_a, id_b;
346
347 if (search_query->value == element) {
348 search_query->found = 1;
349 goto end;
350 }
351
0d23acbe
PP
352 /*
353 * Two event classes cannot share the same ID in a given
354 * stream class.
355 */
50842bdc
PP
356 id_a = bt_event_class_get_id(event_class_a);
357 id_b = bt_event_class_get_id(event_class_b);
0d23acbe
PP
358
359 if (id_a < 0 || id_b < 0) {
360 /* at least one ID is not set: will be automatically set later */
361 goto end;
362 }
363
364 if (id_a == id_b) {
66871d36 365 BT_LOGW("Event class with this ID already exists in the stream class: "
d2f71f12 366 "id=%" PRId64 ", name=\"%s\"",
50842bdc 367 id_a, bt_event_class_get_name(event_class_a));
0d23acbe
PP
368 search_query->found = 1;
369 goto end;
370 }
371
372end:
373 return;
374}
375
50842bdc
PP
376int bt_stream_class_add_event_class(
377 struct bt_stream_class *stream_class,
378 struct bt_event_class *event_class)
11b0cdc8
JG
379{
380 int ret = 0;
0b9ce69f 381 int64_t *event_id = NULL;
50842bdc
PP
382 struct bt_trace *trace = NULL;
383 struct bt_stream_class *old_stream_class = NULL;
384 struct bt_validation_output validation_output = { 0 };
385 struct bt_field_type *packet_header_type = NULL;
386 struct bt_field_type *packet_context_type = NULL;
387 struct bt_field_type *event_header_type = NULL;
388 struct bt_field_type *stream_event_ctx_type = NULL;
389 struct bt_field_type *event_context_type = NULL;
390 struct bt_field_type *event_payload_type = NULL;
391 const enum bt_validation_flag validation_flags =
392 BT_VALIDATION_FLAG_EVENT;
2a3ced3c 393 struct bt_clock_class *expected_clock_class = NULL;
11b0cdc8 394
e011d2c1
PP
395 if (!stream_class || !event_class) {
396 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
397 "stream-class-addr=%p, event-class-addr=%p",
398 stream_class, event_class);
399 ret = -1;
400 goto end;
401 }
402
d2f71f12
PP
403 BT_LOGD("Adding event class to stream class: "
404 "stream-class-addr=%p, stream-class-name=\"%s\", "
405 "stream-class-id=%" PRId64 ", event-class-addr=%p, "
406 "event-class-name=\"%s\", event-class-id=%" PRId64,
50842bdc
PP
407 stream_class, bt_stream_class_get_name(stream_class),
408 bt_stream_class_get_id(stream_class),
d2f71f12 409 event_class,
50842bdc
PP
410 bt_event_class_get_name(event_class),
411 bt_event_class_get_id(event_class));
d2f71f12 412
50842bdc 413 trace = bt_stream_class_get_trace(stream_class);
5acf2ae6 414 if (trace && trace->is_static) {
2a3ced3c
PP
415 BT_LOGW("Invalid parameter: stream class's trace is static: "
416 "trace-addr=%p, trace-name=\"%s\"",
417 trace, bt_trace_get_name(trace));
5acf2ae6
PP
418 ret = -1;
419 goto end;
420 }
421
2a3ced3c
PP
422 if (stream_class->frozen) {
423 /*
424 * We only check that the event class to be added has a
425 * single class which matches the stream class's
426 * expected clock class if the stream class is frozen.
427 * If it's not, then this event class is added "as is"
428 * and the validation will be performed when calling
429 * either bt_trace_add_stream_class() or
430 * bt_event_create(). This is because the stream class's
431 * field types (packet context, event header, event
432 * context) could change before the next call to one of
433 * those two functions.
434 */
435 expected_clock_class = bt_get(stream_class->clock_class);
436
437 /*
438 * At this point, `expected_clock_class` can be NULL,
439 * and bt_event_class_validate_single_clock_class()
440 * below can set it.
441 */
442 ret = bt_event_class_validate_single_clock_class(
443 event_class, &expected_clock_class);
444 if (ret) {
445 BT_LOGW("Event class contains a field type which is not "
446 "recursively mapped to its stream class's "
447 "expected clock class: "
448 "stream-class-addr=%p, "
449 "stream-class-id=%" PRId64 ", "
450 "stream-class-name=\"%s\", "
451 "expected-clock-class-addr=%p, "
452 "expected-clock-class-name=\"%s\"",
453 stream_class,
454 bt_stream_class_get_id(stream_class),
455 bt_stream_class_get_name(stream_class),
456 expected_clock_class,
457 expected_clock_class ?
458 bt_clock_class_get_name(expected_clock_class) :
459 NULL);
460 goto end;
461 }
462 }
463
0b9ce69f
JG
464 event_id = g_new(int64_t, 1);
465 if (!event_id) {
d2f71f12 466 BT_LOGE_STR("Failed to allocate one int64_t.");
0b9ce69f
JG
467 ret = -1;
468 goto end;
469 }
470
11b0cdc8
JG
471 /* Check for duplicate event classes */
472 struct search_query query = { .value = event_class, .found = 0 };
0d23acbe
PP
473 g_ptr_array_foreach(stream_class->event_classes, event_class_exists,
474 &query);
11b0cdc8 475 if (query.found) {
d2f71f12 476 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
11b0cdc8
JG
477 ret = -1;
478 goto end;
479 }
480
50842bdc 481 old_stream_class = bt_event_class_get_stream_class(event_class);
e6a8e8e4
JG
482 if (old_stream_class) {
483 /* Event class is already associated to a stream class. */
d2f71f12
PP
484 BT_LOGW("Event class is already part of another stream class: "
485 "event-class-stream-class-addr=%p, "
486 "event-class-stream-class-name=\"%s\", "
487 "event-class-stream-class-id=%" PRId64,
488 old_stream_class,
50842bdc
PP
489 bt_stream_class_get_name(old_stream_class),
490 bt_stream_class_get_id(old_stream_class));
e6a8e8e4
JG
491 ret = -1;
492 goto end;
493 }
494
e6a8e8e4 495 if (trace) {
09840de5
PP
496 /*
497 * If the stream class is associated with a trace, then
498 * both those objects are frozen. Also, this event class
499 * is about to be frozen.
500 *
501 * Therefore the event class must be validated here.
502 * The trace and stream class should be valid at this
503 * point.
504 */
f6ccaed9
PP
505 BT_ASSERT(trace->valid);
506 BT_ASSERT(stream_class->valid);
09840de5 507 packet_header_type =
50842bdc 508 bt_trace_get_packet_header_type(trace);
09840de5 509 packet_context_type =
50842bdc 510 bt_stream_class_get_packet_context_type(
09840de5
PP
511 stream_class);
512 event_header_type =
50842bdc 513 bt_stream_class_get_event_header_type(stream_class);
09840de5 514 stream_event_ctx_type =
50842bdc 515 bt_stream_class_get_event_context_type(
09840de5
PP
516 stream_class);
517 event_context_type =
50842bdc 518 bt_event_class_get_context_type(event_class);
09840de5 519 event_payload_type =
50842bdc
PP
520 bt_event_class_get_payload_type(event_class);
521 ret = bt_validate_class_types(
09840de5
PP
522 trace->environment, packet_header_type,
523 packet_context_type, event_header_type,
524 stream_event_ctx_type, event_context_type,
525 event_payload_type, trace->valid,
526 stream_class->valid, event_class->valid,
527 &validation_output, validation_flags);
528 BT_PUT(packet_header_type);
529 BT_PUT(packet_context_type);
530 BT_PUT(event_header_type);
531 BT_PUT(stream_event_ctx_type);
532 BT_PUT(event_context_type);
533 BT_PUT(event_payload_type);
534
26079216 535 if (ret) {
09840de5
PP
536 /*
537 * This means something went wrong during the
538 * validation process, not that the objects are
539 * invalid.
540 */
d2f71f12 541 BT_LOGE("Failed to validate event class: ret=%d", ret);
09840de5
PP
542 goto end;
543 }
544
545 if ((validation_output.valid_flags & validation_flags) !=
546 validation_flags) {
547 /* Invalid event class */
66871d36 548 BT_LOGW("Invalid trace, stream class, or event class: "
d2f71f12
PP
549 "valid-flags=0x%x",
550 validation_output.valid_flags);
09840de5 551 ret = -1;
26079216
JG
552 goto end;
553 }
554 }
555
09840de5 556 /* Only set an event ID if none was explicitly set before */
50842bdc 557 *event_id = bt_event_class_get_id(event_class);
24626e8b 558 if (*event_id < 0) {
d2f71f12
PP
559 BT_LOGV("Event class has no ID: automatically setting it: "
560 "id=%" PRId64, stream_class->next_event_id);
561
50842bdc 562 if (bt_event_class_set_id(event_class,
d2f71f12
PP
563 stream_class->next_event_id)) {
564 BT_LOGE("Cannot set event class's ID: id=%" PRId64,
565 stream_class->next_event_id);
2f100782
JG
566 ret = -1;
567 goto end;
568 }
d2f71f12 569 stream_class->next_event_id++;
0b9ce69f 570 *event_id = stream_class->next_event_id;
2f100782
JG
571 }
572
e6a8e8e4 573 bt_object_set_parent(event_class, stream_class);
09840de5
PP
574
575 if (trace) {
576 /*
577 * At this point we know that the function will be
578 * successful. Therefore we can replace the event
579 * class's field types with what's in the validation
580 * output structure and mark this event class as valid.
581 */
50842bdc 582 bt_validation_replace_types(NULL, NULL, event_class,
09840de5
PP
583 &validation_output, validation_flags);
584 event_class->valid = 1;
585
586 /*
587 * Put what was not moved in
50842bdc 588 * bt_validation_replace_types().
09840de5 589 */
50842bdc 590 bt_validation_output_put_types(&validation_output);
09840de5
PP
591 }
592
593 /* Add to the event classes of the stream class */
11b0cdc8 594 g_ptr_array_add(stream_class->event_classes, event_class);
0b9ce69f
JG
595 g_hash_table_insert(stream_class->event_classes_ht, event_id,
596 event_class);
597 event_id = NULL;
09840de5
PP
598
599 /* Freeze the event class */
50842bdc 600 bt_event_class_freeze(event_class);
5ca83563 601
2a3ced3c
PP
602 /*
603 * It is safe to set the stream class's unique clock class
604 * now if the stream class is frozen.
605 */
606 if (stream_class->frozen && expected_clock_class) {
f6ccaed9 607 BT_ASSERT(!stream_class->clock_class ||
2a3ced3c
PP
608 stream_class->clock_class == expected_clock_class);
609 BT_MOVE(stream_class->clock_class, expected_clock_class);
610 }
611
9b888ff3
JG
612 /* Notifiy listeners of the trace's schema modification. */
613 if (trace) {
50842bdc
PP
614 struct bt_visitor_object obj = { .object = event_class,
615 .type = BT_VISITOR_OBJECT_TYPE_EVENT_CLASS };
9b888ff3 616
50842bdc 617 (void) bt_trace_object_modification(&obj, trace);
9b888ff3 618 }
d2f71f12
PP
619
620 BT_LOGD("Added event class to stream class: "
621 "stream-class-addr=%p, stream-class-name=\"%s\", "
622 "stream-class-id=%" PRId64 ", event-class-addr=%p, "
623 "event-class-name=\"%s\", event-class-id=%" PRId64,
50842bdc
PP
624 stream_class, bt_stream_class_get_name(stream_class),
625 bt_stream_class_get_id(stream_class),
d2f71f12 626 event_class,
50842bdc
PP
627 bt_event_class_get_name(event_class),
628 bt_event_class_get_id(event_class));
d2f71f12 629
11b0cdc8 630end:
e6a8e8e4
JG
631 BT_PUT(trace);
632 BT_PUT(old_stream_class);
50842bdc 633 bt_validation_output_put_types(&validation_output);
2a3ced3c 634 bt_put(expected_clock_class);
f6ccaed9
PP
635 BT_ASSERT(!packet_header_type);
636 BT_ASSERT(!packet_context_type);
637 BT_ASSERT(!event_header_type);
638 BT_ASSERT(!stream_event_ctx_type);
639 BT_ASSERT(!event_context_type);
640 BT_ASSERT(!event_payload_type);
0b9ce69f 641 g_free(event_id);
09840de5 642
11b0cdc8
JG
643 return ret;
644}
645
50842bdc
PP
646int64_t bt_stream_class_get_event_class_count(
647 struct bt_stream_class *stream_class)
69dc4535 648{
544d0515 649 int64_t ret;
69dc4535
JG
650
651 if (!stream_class) {
d2f71f12 652 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
9ac68eb1 653 ret = (int64_t) -1;
69dc4535
JG
654 goto end;
655 }
656
9ac68eb1 657 ret = (int64_t) stream_class->event_classes->len;
69dc4535
JG
658end:
659 return ret;
660}
661
50842bdc
PP
662struct bt_event_class *bt_stream_class_get_event_class_by_index(
663 struct bt_stream_class *stream_class, uint64_t index)
69dc4535 664{
d975f66c
PP
665 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
666 BT_ASSERT_PRE(index < stream_class->event_classes->len,
667 "Index is out of bounds: index=%" PRIu64 ", "
668 "count=%u",
669 index, stream_class->event_classes->len);
670 return bt_get(g_ptr_array_index(stream_class->event_classes, index));
69dc4535
JG
671}
672
50842bdc
PP
673struct bt_event_class *bt_stream_class_get_event_class_by_id(
674 struct bt_stream_class *stream_class, uint64_t id)
0863f950 675{
9ac68eb1 676 int64_t id_key = (int64_t) id;
0863f950 677
d975f66c
PP
678 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
679 BT_ASSERT_PRE(id_key >= 0,
680 "Invalid event class ID: %" PRIu64, id);
681 return bt_get(g_hash_table_lookup(stream_class->event_classes_ht,
682 &id_key));
0863f950
PP
683}
684
50842bdc
PP
685struct bt_field_type *bt_stream_class_get_packet_context_type(
686 struct bt_stream_class *stream_class)
12c8a1a3 687{
d975f66c
PP
688 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
689 return bt_get(stream_class->packet_context_type);
12c8a1a3
JG
690}
691
50842bdc
PP
692int bt_stream_class_set_packet_context_type(
693 struct bt_stream_class *stream_class,
694 struct bt_field_type *packet_context_type)
12c8a1a3
JG
695{
696 int ret = 0;
697
d2f71f12
PP
698 if (!stream_class) {
699 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
700 ret = -1;
701 goto end;
702 }
703
704 if (stream_class->frozen) {
705 BT_LOGW("Invalid parameter: stream class is frozen: "
706 "addr=%p, name=\"%s\", id=%" PRId64,
50842bdc
PP
707 stream_class, bt_stream_class_get_name(stream_class),
708 bt_stream_class_get_id(stream_class));
12c8a1a3
JG
709 ret = -1;
710 goto end;
711 }
712
835b2d10 713 if (packet_context_type &&
50842bdc
PP
714 bt_field_type_get_type_id(packet_context_type) !=
715 BT_FIELD_TYPE_ID_STRUCT) {
835b2d10 716 /* A packet context must be a structure. */
d2f71f12
PP
717 BT_LOGW("Invalid parameter: stream class's packet context field type must be a structure: "
718 "addr=%p, name=\"%s\", id=%" PRId64 ", "
719 "packet-context-ft-addr=%p, packet-context-ft-id=%s",
50842bdc
PP
720 stream_class, bt_stream_class_get_name(stream_class),
721 bt_stream_class_get_id(stream_class),
d2f71f12 722 packet_context_type,
50842bdc
PP
723 bt_field_type_id_string(
724 bt_field_type_get_type_id(packet_context_type)));
12c8a1a3
JG
725 ret = -1;
726 goto end;
727 }
728
83509119
JG
729 bt_put(stream_class->packet_context_type);
730 bt_get(packet_context_type);
12c8a1a3 731 stream_class->packet_context_type = packet_context_type;
d2f71f12
PP
732 BT_LOGV("Set stream class's packet context field type: "
733 "addr=%p, name=\"%s\", id=%" PRId64 ", "
734 "packet-context-ft-addr=%p",
50842bdc
PP
735 stream_class, bt_stream_class_get_name(stream_class),
736 bt_stream_class_get_id(stream_class),
d2f71f12
PP
737 packet_context_type);
738
12c8a1a3
JG
739end:
740 return ret;
741}
742
50842bdc
PP
743struct bt_field_type *bt_stream_class_get_event_header_type(
744 struct bt_stream_class *stream_class)
662e778c 745{
50842bdc 746 struct bt_field_type *ret = NULL;
662e778c 747
d975f66c 748 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
d2f71f12
PP
749
750 if (!stream_class->event_header_type) {
751 BT_LOGV("Stream class has no event header field type: "
752 "addr=%p, name=\"%s\", id=%" PRId64,
50842bdc
PP
753 stream_class, bt_stream_class_get_name(stream_class),
754 bt_stream_class_get_id(stream_class));
662e778c
JG
755 goto end;
756 }
757
d975f66c
PP
758 ret = bt_get(stream_class->event_header_type);
759
662e778c
JG
760end:
761 return ret;
762}
763
50842bdc
PP
764int bt_stream_class_set_event_header_type(
765 struct bt_stream_class *stream_class,
766 struct bt_field_type *event_header_type)
662e778c
JG
767{
768 int ret = 0;
769
d2f71f12
PP
770 if (!stream_class) {
771 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
772 ret = -1;
773 goto end;
774 }
775
776 if (stream_class->frozen) {
777 BT_LOGW("Invalid parameter: stream class is frozen: "
778 "addr=%p, name=\"%s\", id=%" PRId64,
50842bdc
PP
779 stream_class, bt_stream_class_get_name(stream_class),
780 bt_stream_class_get_id(stream_class));
662e778c
JG
781 ret = -1;
782 goto end;
783 }
784
835b2d10 785 if (event_header_type &&
50842bdc
PP
786 bt_field_type_get_type_id(event_header_type) !=
787 BT_FIELD_TYPE_ID_STRUCT) {
835b2d10 788 /* An event header must be a structure. */
d2f71f12
PP
789 BT_LOGW("Invalid parameter: stream class's event header field type must be a structure: "
790 "addr=%p, name=\"%s\", id=%" PRId64 ", "
791 "event-header-ft-addr=%p, event-header-ft-id=%s",
50842bdc
PP
792 stream_class, bt_stream_class_get_name(stream_class),
793 bt_stream_class_get_id(stream_class),
d2f71f12 794 event_header_type,
50842bdc
PP
795 bt_field_type_id_string(
796 bt_field_type_get_type_id(event_header_type)));
662e778c
JG
797 ret = -1;
798 goto end;
799 }
800
83509119 801 bt_put(stream_class->event_header_type);
835b2d10 802 stream_class->event_header_type = bt_get(event_header_type);
d2f71f12
PP
803 BT_LOGV("Set stream class's event header field type: "
804 "addr=%p, name=\"%s\", id=%" PRId64 ", "
805 "event-header-ft-addr=%p",
50842bdc
PP
806 stream_class, bt_stream_class_get_name(stream_class),
807 bt_stream_class_get_id(stream_class),
d2f71f12 808 event_header_type);
662e778c
JG
809end:
810 return ret;
811}
812
50842bdc
PP
813struct bt_field_type *bt_stream_class_get_event_context_type(
814 struct bt_stream_class *stream_class)
af181248 815{
50842bdc 816 struct bt_field_type *ret = NULL;
af181248 817
d975f66c 818 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
d2f71f12
PP
819
820 if (!stream_class->event_context_type) {
af181248
JG
821 goto end;
822 }
823
d975f66c
PP
824 ret = bt_get(stream_class->event_context_type);
825
af181248
JG
826end:
827 return ret;
828}
829
50842bdc
PP
830int bt_stream_class_set_event_context_type(
831 struct bt_stream_class *stream_class,
832 struct bt_field_type *event_context_type)
af181248
JG
833{
834 int ret = 0;
835
d2f71f12
PP
836 if (!stream_class) {
837 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
838 ret = -1;
839 goto end;
840 }
841
842 if (stream_class->frozen) {
843 BT_LOGW("Invalid parameter: stream class is frozen: "
844 "addr=%p, name=\"%s\", id=%" PRId64,
50842bdc
PP
845 stream_class, bt_stream_class_get_name(stream_class),
846 bt_stream_class_get_id(stream_class));
af181248
JG
847 ret = -1;
848 goto end;
849 }
850
835b2d10 851 if (event_context_type &&
50842bdc
PP
852 bt_field_type_get_type_id(event_context_type) !=
853 BT_FIELD_TYPE_ID_STRUCT) {
835b2d10 854 /* A packet context must be a structure. */
d2f71f12
PP
855 BT_LOGW("Invalid parameter: stream class's event context field type must be a structure: "
856 "addr=%p, name=\"%s\", id=%" PRId64 ", "
857 "event-context-ft-addr=%p, event-context-ft-id=%s",
50842bdc
PP
858 stream_class, bt_stream_class_get_name(stream_class),
859 bt_stream_class_get_id(stream_class),
d2f71f12 860 event_context_type,
50842bdc
PP
861 bt_field_type_id_string(
862 bt_field_type_get_type_id(event_context_type)));
af181248
JG
863 ret = -1;
864 goto end;
865 }
866
83509119 867 bt_put(stream_class->event_context_type);
835b2d10 868 stream_class->event_context_type = bt_get(event_context_type);
d2f71f12
PP
869 BT_LOGV("Set stream class's event context field type: "
870 "addr=%p, name=\"%s\", id=%" PRId64 ", "
871 "event-context-ft-addr=%p",
50842bdc
PP
872 stream_class, bt_stream_class_get_name(stream_class),
873 bt_stream_class_get_id(stream_class),
d2f71f12 874 event_context_type);
af181248
JG
875end:
876 return ret;
877}
878
d2f71f12 879/* Pre-2.0 CTF writer backward compatibility */
50842bdc 880void bt_ctf_stream_class_get(struct bt_stream_class *stream_class)
11b0cdc8 881{
83509119 882 bt_get(stream_class);
11b0cdc8
JG
883}
884
d2f71f12 885/* Pre-2.0 CTF writer backward compatibility */
50842bdc 886void bt_ctf_stream_class_put(struct bt_stream_class *stream_class)
11b0cdc8 887{
83509119 888 bt_put(stream_class);
11b0cdc8
JG
889}
890
8bf65fbd 891static
544d0515 892int64_t get_event_class_count(void *element)
8bf65fbd 893{
50842bdc
PP
894 return bt_stream_class_get_event_class_count(
895 (struct bt_stream_class *) element);
8bf65fbd
JG
896}
897
898static
899void *get_event_class(void *element, int i)
900{
50842bdc
PP
901 return bt_stream_class_get_event_class_by_index(
902 (struct bt_stream_class *) element, i);
8bf65fbd
JG
903}
904
905static
50842bdc 906int visit_event_class(void *object, bt_visitor visitor,void *data)
8bf65fbd 907{
50842bdc 908 struct bt_visitor_object obj =
d9a13d86 909 { .object = object,
50842bdc 910 .type = BT_VISITOR_OBJECT_TYPE_EVENT_CLASS };
8bf65fbd 911
d9a13d86 912 return visitor(&obj, data);
8bf65fbd
JG
913}
914
50842bdc
PP
915int bt_stream_class_visit(struct bt_stream_class *stream_class,
916 bt_visitor visitor, void *data)
8bf65fbd
JG
917{
918 int ret;
50842bdc 919 struct bt_visitor_object obj =
d9a13d86 920 { .object = stream_class,
50842bdc 921 .type = BT_VISITOR_OBJECT_TYPE_STREAM_CLASS };
8bf65fbd
JG
922
923 if (!stream_class || !visitor) {
d2f71f12
PP
924 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
925 "stream-class-addr=%p, visitor=%p",
926 stream_class, visitor);
8bf65fbd
JG
927 ret = -1;
928 goto end;
929 }
930
d9a13d86 931 ret = visitor_helper(&obj, get_event_class_count,
8bf65fbd
JG
932 get_event_class,
933 visit_event_class, visitor, data);
d2f71f12 934 BT_LOGV("visitor_helper() returned: ret=%d", ret);
8bf65fbd
JG
935end:
936 return ret;
937}
938
11b0cdc8 939BT_HIDDEN
50842bdc 940void bt_stream_class_freeze(struct bt_stream_class *stream_class)
11b0cdc8 941{
d2f71f12 942 if (!stream_class || stream_class->frozen) {
11b0cdc8
JG
943 return;
944 }
945
d2f71f12 946 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64,
50842bdc
PP
947 stream_class, bt_stream_class_get_name(stream_class),
948 bt_stream_class_get_id(stream_class));
11b0cdc8 949 stream_class->frozen = 1;
50842bdc
PP
950 bt_field_type_freeze(stream_class->event_header_type);
951 bt_field_type_freeze(stream_class->packet_context_type);
952 bt_field_type_freeze(stream_class->event_context_type);
ac0c6bdd
PP
953
954 if (stream_class->clock) {
50842bdc 955 bt_clock_class_freeze(stream_class->clock->clock_class);
ac0c6bdd 956 }
11b0cdc8
JG
957}
958
11b0cdc8 959BT_HIDDEN
50842bdc 960int bt_stream_class_serialize(struct bt_stream_class *stream_class,
11b0cdc8
JG
961 struct metadata_context *context)
962{
9ac68eb1 963 int ret = 0;
11b0cdc8 964 size_t i;
50842bdc
PP
965 struct bt_trace *trace;
966 struct bt_field_type *packet_header_type = NULL;
11b0cdc8 967
d2f71f12
PP
968 BT_LOGD("Serializing stream class's metadata: "
969 "stream-class-addr=%p, stream-class-name=\"%s\", "
970 "stream-class-id=%" PRId64 ", metadata-context-addr=%p",
50842bdc
PP
971 stream_class, bt_stream_class_get_name(stream_class),
972 bt_stream_class_get_id(stream_class), context);
11b0cdc8
JG
973 g_string_assign(context->field_name, "");
974 context->current_indentation_level = 1;
975 if (!stream_class->id_set) {
d2f71f12 976 BT_LOGW_STR("Stream class's ID is not set.");
11b0cdc8
JG
977 ret = -1;
978 goto end;
979 }
980
6a5c98a5
JG
981 g_string_append(context->string, "stream {\n");
982
983 /*
984 * The reference to the trace is only borrowed since the
985 * serialization of the stream class might have been triggered
986 * by the trace's destruction. In such a case, the trace's
987 * reference count would, unexepectedly, go through the sequence
988 * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
989 * and serialization.
990 */
50842bdc 991 trace = bt_stream_class_borrow_trace(stream_class);
f6ccaed9 992 BT_ASSERT(trace);
50842bdc 993 packet_header_type = bt_trace_get_packet_header_type(trace);
6a5c98a5
JG
994 trace = NULL;
995 if (packet_header_type) {
50842bdc 996 struct bt_field_type *stream_id_type;
6a5c98a5
JG
997
998 stream_id_type =
50842bdc 999 bt_field_type_structure_get_field_type_by_name(
6a5c98a5
JG
1000 packet_header_type, "stream_id");
1001 if (stream_id_type) {
1002 /*
1003 * Only set the stream's id if the trace's packet header
1004 * contains a stream_id field. This field is only
1005 * needed if the trace contains only one stream
1006 * class.
1007 */
1008 g_string_append_printf(context->string,
1009 "\tid = %" PRId64 ";\n", stream_class->id);
1010 }
1011 bt_put(stream_id_type);
1012 }
e011d2c1
PP
1013 if (stream_class->event_header_type) {
1014 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
1015 g_string_append(context->string, "\tevent.header := ");
50842bdc 1016 ret = bt_field_type_serialize(stream_class->event_header_type,
e011d2c1
PP
1017 context);
1018 if (ret) {
1019 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
1020 "ret=%d", ret);
1021 goto end;
1022 }
1023 g_string_append(context->string, ";");
11b0cdc8
JG
1024 }
1025
e011d2c1 1026
98edd02c 1027 if (stream_class->packet_context_type) {
e011d2c1
PP
1028 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
1029 g_string_append(context->string, "\n\n\tpacket.context := ");
50842bdc 1030 ret = bt_field_type_serialize(stream_class->packet_context_type,
98edd02c
JG
1031 context);
1032 if (ret) {
66871d36 1033 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
d2f71f12 1034 "ret=%d", ret);
98edd02c
JG
1035 goto end;
1036 }
e011d2c1 1037 g_string_append(context->string, ";");
11b0cdc8
JG
1038 }
1039
1040 if (stream_class->event_context_type) {
e011d2c1
PP
1041 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
1042 g_string_append(context->string, "\n\n\tevent.context := ");
50842bdc 1043 ret = bt_field_type_serialize(
11b0cdc8
JG
1044 stream_class->event_context_type, context);
1045 if (ret) {
66871d36 1046 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
d2f71f12 1047 "ret=%d", ret);
11b0cdc8
JG
1048 goto end;
1049 }
e011d2c1 1050 g_string_append(context->string, ";");
11b0cdc8
JG
1051 }
1052
e011d2c1
PP
1053 g_string_append(context->string, "\n};\n\n");
1054
11b0cdc8 1055 for (i = 0; i < stream_class->event_classes->len; i++) {
50842bdc 1056 struct bt_event_class *event_class =
11b0cdc8
JG
1057 stream_class->event_classes->pdata[i];
1058
50842bdc 1059 ret = bt_event_class_serialize(event_class, context);
11b0cdc8 1060 if (ret) {
66871d36 1061 BT_LOGW("Cannot serialize event class's metadata: "
d2f71f12
PP
1062 "event-class-addr=%p, event-class-name=\"%s\", "
1063 "event-class-id=%" PRId64,
1064 event_class,
50842bdc
PP
1065 bt_event_class_get_name(event_class),
1066 bt_event_class_get_id(event_class));
11b0cdc8
JG
1067 goto end;
1068 }
1069 }
1070end:
6a5c98a5 1071 bt_put(packet_header_type);
11b0cdc8
JG
1072 context->current_indentation_level = 0;
1073 return ret;
1074}
1075
1076static
50842bdc 1077void bt_stream_class_destroy(struct bt_object *obj)
11b0cdc8 1078{
50842bdc 1079 struct bt_stream_class *stream_class;
11b0cdc8 1080
50842bdc 1081 stream_class = container_of(obj, struct bt_stream_class, base);
d2f71f12 1082 BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64,
50842bdc
PP
1083 stream_class, bt_stream_class_get_name(stream_class),
1084 bt_stream_class_get_id(stream_class));
83509119 1085 bt_put(stream_class->clock);
2a3ced3c 1086 bt_put(stream_class->clock_class);
11b0cdc8 1087
0b9ce69f
JG
1088 if (stream_class->event_classes_ht) {
1089 g_hash_table_destroy(stream_class->event_classes_ht);
1090 }
11b0cdc8 1091 if (stream_class->event_classes) {
8c8cb0f2 1092 BT_LOGD_STR("Destroying event classes.");
11b0cdc8
JG
1093 g_ptr_array_free(stream_class->event_classes, TRUE);
1094 }
1095
1096 if (stream_class->name) {
1097 g_string_free(stream_class->name, TRUE);
1098 }
1099
8c8cb0f2 1100 BT_LOGD_STR("Putting event header field type.");
83509119 1101 bt_put(stream_class->event_header_type);
8c8cb0f2 1102 BT_LOGD_STR("Putting packet context field type.");
83509119 1103 bt_put(stream_class->packet_context_type);
8c8cb0f2 1104 BT_LOGD_STR("Putting event context field type.");
83509119 1105 bt_put(stream_class->event_context_type);
11b0cdc8
JG
1106 g_free(stream_class);
1107}
1108
1109static
50842bdc 1110int init_event_header(struct bt_stream_class *stream_class)
11b0cdc8
JG
1111{
1112 int ret = 0;
50842bdc
PP
1113 struct bt_field_type *event_header_type =
1114 bt_field_type_structure_create();
1115 struct bt_field_type *_uint32_t =
11b0cdc8 1116 get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
50842bdc 1117 struct bt_field_type *_uint64_t =
11b0cdc8
JG
1118 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
1119
1120 if (!event_header_type) {
d2f71f12 1121 BT_LOGE_STR("Cannot create empty structure field type.");
11b0cdc8
JG
1122 ret = -1;
1123 goto end;
1124 }
1125
50842bdc 1126 ret = bt_field_type_structure_add_field(event_header_type,
11b0cdc8
JG
1127 _uint32_t, "id");
1128 if (ret) {
d2f71f12 1129 BT_LOGE_STR("Cannot add `id` field to event header field type.");
11b0cdc8
JG
1130 goto end;
1131 }
1132
50842bdc 1133 ret = bt_field_type_structure_add_field(event_header_type,
11b0cdc8
JG
1134 _uint64_t, "timestamp");
1135 if (ret) {
d2f71f12 1136 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
11b0cdc8
JG
1137 goto end;
1138 }
1139
e0e2946b 1140 BT_MOVE(stream_class->event_header_type, event_header_type);
11b0cdc8
JG
1141end:
1142 if (ret) {
83509119 1143 bt_put(event_header_type);
11b0cdc8
JG
1144 }
1145
83509119
JG
1146 bt_put(_uint32_t);
1147 bt_put(_uint64_t);
11b0cdc8
JG
1148 return ret;
1149}
1150
1151static
50842bdc 1152int init_packet_context(struct bt_stream_class *stream_class)
11b0cdc8
JG
1153{
1154 int ret = 0;
50842bdc
PP
1155 struct bt_field_type *packet_context_type =
1156 bt_field_type_structure_create();
1157 struct bt_field_type *_uint64_t =
11b0cdc8 1158 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
50842bdc 1159 struct bt_field_type *ts_begin_end_uint64_t;
11b0cdc8
JG
1160
1161 if (!packet_context_type) {
d2f71f12 1162 BT_LOGE_STR("Cannot create empty structure field type.");
11b0cdc8
JG
1163 ret = -1;
1164 goto end;
1165 }
1166
50842bdc 1167 ts_begin_end_uint64_t = bt_field_type_copy(_uint64_t);
e011d2c1
PP
1168 if (!ts_begin_end_uint64_t) {
1169 BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
1170 ret = -1;
1171 goto end;
1172 }
1173
11b0cdc8
JG
1174 /*
1175 * We create a stream packet context as proposed in the CTF
1176 * specification.
1177 */
50842bdc 1178 ret = bt_field_type_structure_add_field(packet_context_type,
e011d2c1 1179 ts_begin_end_uint64_t, "timestamp_begin");
11b0cdc8 1180 if (ret) {
d2f71f12 1181 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
11b0cdc8
JG
1182 goto end;
1183 }
1184
50842bdc 1185 ret = bt_field_type_structure_add_field(packet_context_type,
e011d2c1 1186 ts_begin_end_uint64_t, "timestamp_end");
11b0cdc8 1187 if (ret) {
d2f71f12 1188 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
11b0cdc8
JG
1189 goto end;
1190 }
1191
50842bdc 1192 ret = bt_field_type_structure_add_field(packet_context_type,
11b0cdc8
JG
1193 _uint64_t, "content_size");
1194 if (ret) {
d2f71f12 1195 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
11b0cdc8
JG
1196 goto end;
1197 }
1198
50842bdc 1199 ret = bt_field_type_structure_add_field(packet_context_type,
11b0cdc8
JG
1200 _uint64_t, "packet_size");
1201 if (ret) {
d2f71f12 1202 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
11b0cdc8
JG
1203 goto end;
1204 }
1205
50842bdc 1206 ret = bt_field_type_structure_add_field(packet_context_type,
11b0cdc8
JG
1207 _uint64_t, "events_discarded");
1208 if (ret) {
d2f71f12 1209 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
11b0cdc8
JG
1210 goto end;
1211 }
1212
e0e2946b 1213 BT_MOVE(stream_class->packet_context_type, packet_context_type);
11b0cdc8
JG
1214end:
1215 if (ret) {
83509119 1216 bt_put(packet_context_type);
11b0cdc8
JG
1217 goto end;
1218 }
1219
83509119 1220 bt_put(_uint64_t);
e011d2c1
PP
1221 bt_put(ts_begin_end_uint64_t);
1222 return ret;
1223}
1224
1225static
50842bdc 1226int try_map_clock_class(struct bt_stream_class *stream_class,
8cd07f2c 1227 struct bt_field_type *parent_ft, const char *field_name)
e011d2c1 1228{
50842bdc 1229 struct bt_clock_class *mapped_clock_class = NULL;
e011d2c1 1230 int ret = 0;
8cd07f2c
PP
1231 struct bt_field_type *ft =
1232 bt_field_type_structure_get_field_type_by_name(parent_ft,
1233 field_name);
1234
f6ccaed9 1235 BT_ASSERT(stream_class->clock);
e011d2c1
PP
1236
1237 if (!ft) {
1238 /* Field does not exist: not an error */
1239 goto end;
1240 }
1241
f6ccaed9 1242 BT_ASSERT(bt_field_type_is_integer(ft));
e011d2c1 1243 mapped_clock_class =
50842bdc 1244 bt_field_type_integer_get_mapped_clock_class(ft);
e011d2c1 1245 if (!mapped_clock_class) {
8cd07f2c
PP
1246 struct bt_field_type *ft_copy;
1247
e011d2c1
PP
1248 if (!stream_class->clock) {
1249 BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
1250 "stream-class-addr=%p, stream-class-name=\"%s\", "
1251 "stream-class-id=%" PRId64 ", ft-addr=%p",
50842bdc
PP
1252 stream_class, bt_stream_class_get_name(stream_class),
1253 bt_stream_class_get_id(stream_class), ft);
e011d2c1
PP
1254 ret = -1;
1255 goto end;
1256 }
1257
8cd07f2c
PP
1258 ft_copy = bt_field_type_copy(ft);
1259 if (!ft_copy) {
1260 BT_LOGE("Failed to copy integer field type: ft-addr=%p",
1261 ft);
e011d2c1
PP
1262 }
1263
8cd07f2c
PP
1264 ret = bt_field_type_integer_set_mapped_clock_class_no_check(
1265 ft_copy, stream_class->clock->clock_class);
f6ccaed9 1266 BT_ASSERT(ret == 0);
8cd07f2c
PP
1267 ret = bt_field_type_structure_replace_field(parent_ft,
1268 field_name, ft_copy);
1269 bt_put(ft_copy);
e011d2c1
PP
1270 BT_LOGV("Automatically mapped field type to stream class's clock class: "
1271 "stream-class-addr=%p, stream-class-name=\"%s\", "
8cd07f2c
PP
1272 "stream-class-id=%" PRId64 ", ft-addr=%p, "
1273 "ft-copy-addr=%p",
50842bdc 1274 stream_class, bt_stream_class_get_name(stream_class),
8cd07f2c 1275 bt_stream_class_get_id(stream_class), ft, ft_copy);
e011d2c1
PP
1276 }
1277
1278end:
8cd07f2c 1279 bt_put(ft);
e011d2c1
PP
1280 bt_put(mapped_clock_class);
1281 return ret;
1282}
1283
1284BT_HIDDEN
50842bdc
PP
1285int bt_stream_class_map_clock_class(
1286 struct bt_stream_class *stream_class,
1287 struct bt_field_type *packet_context_type,
1288 struct bt_field_type *event_header_type)
e011d2c1 1289{
e011d2c1
PP
1290 int ret = 0;
1291
f6ccaed9 1292 BT_ASSERT(stream_class);
e011d2c1 1293
8cd07f2c
PP
1294 if (!stream_class->clock) {
1295 /* No clock class to map to */
1296 goto end;
1297 }
1298
e011d2c1 1299 if (packet_context_type) {
8cd07f2c
PP
1300 if (try_map_clock_class(stream_class, packet_context_type,
1301 "timestamp_begin")) {
e011d2c1
PP
1302 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
1303 ret = -1;
1304 goto end;
1305 }
1306
8cd07f2c
PP
1307 if (try_map_clock_class(stream_class, packet_context_type,
1308 "timestamp_end")) {
e011d2c1
PP
1309 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
1310 ret = -1;
1311 goto end;
1312 }
e011d2c1
PP
1313 }
1314
1315 if (event_header_type) {
8cd07f2c
PP
1316 if (try_map_clock_class(stream_class, event_header_type,
1317 "timestamp")) {
e011d2c1
PP
1318 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
1319 ret = -1;
1320 goto end;
1321 }
e011d2c1
PP
1322 }
1323
1324end:
11b0cdc8
JG
1325 return ret;
1326}
2a3ced3c
PP
1327
1328BT_HIDDEN
1329int bt_stream_class_validate_single_clock_class(
1330 struct bt_stream_class *stream_class,
1331 struct bt_clock_class **expected_clock_class)
1332{
1333 int ret;
1334 uint64_t i;
1335
f6ccaed9
PP
1336 BT_ASSERT(stream_class);
1337 BT_ASSERT(expected_clock_class);
2a3ced3c
PP
1338 ret = bt_validate_single_clock_class(stream_class->packet_context_type,
1339 expected_clock_class);
1340 if (ret) {
1341 BT_LOGW("Stream class's packet context field type "
1342 "is not recursively mapped to the "
1343 "expected clock class: "
1344 "stream-class-addr=%p, "
1345 "stream-class-name=\"%s\", "
1346 "stream-class-id=%" PRId64 ", "
1347 "ft-addr=%p",
1348 stream_class,
1349 bt_stream_class_get_name(stream_class),
1350 stream_class->id,
1351 stream_class->packet_context_type);
1352 goto end;
1353 }
1354
1355 ret = bt_validate_single_clock_class(stream_class->event_header_type,
1356 expected_clock_class);
1357 if (ret) {
1358 BT_LOGW("Stream class's event header field type "
1359 "is not recursively mapped to the "
1360 "expected clock class: "
1361 "stream-class-addr=%p, "
1362 "stream-class-name=\"%s\", "
1363 "stream-class-id=%" PRId64 ", "
1364 "ft-addr=%p",
1365 stream_class,
1366 bt_stream_class_get_name(stream_class),
1367 stream_class->id,
1368 stream_class->event_header_type);
1369 goto end;
1370 }
1371
1372 ret = bt_validate_single_clock_class(stream_class->event_context_type,
1373 expected_clock_class);
1374 if (ret) {
1375 BT_LOGW("Stream class's event context field type "
1376 "is not recursively mapped to the "
1377 "expected clock class: "
1378 "stream-class-addr=%p, "
1379 "stream-class-name=\"%s\", "
1380 "stream-class-id=%" PRId64 ", "
1381 "ft-addr=%p",
1382 stream_class,
1383 bt_stream_class_get_name(stream_class),
1384 stream_class->id,
1385 stream_class->event_context_type);
1386 goto end;
1387 }
1388
1389 for (i = 0; i < stream_class->event_classes->len; i++) {
1390 struct bt_event_class *event_class =
1391 g_ptr_array_index(stream_class->event_classes, i);
1392
f6ccaed9 1393 BT_ASSERT(event_class);
2a3ced3c
PP
1394 ret = bt_event_class_validate_single_clock_class(event_class,
1395 expected_clock_class);
1396 if (ret) {
1397 BT_LOGW("Stream class's event class contains a "
1398 "field type which is not recursively mapped to "
1399 "the expected clock class: "
1400 "stream-class-addr=%p, "
1401 "stream-class-name=\"%s\", "
1402 "stream-class-id=%" PRId64,
1403 stream_class,
1404 bt_stream_class_get_name(stream_class),
1405 stream_class->id);
1406 goto end;
1407 }
1408 }
1409
1410end:
1411 return ret;
1412}
This page took 0.11558 seconds and 4 git commands to generate.