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