assert-pre-internal.h: add BT_ASSERT_PRE_VALID_INDEX()
[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
3dca2276 32#include <babeltrace/assert-pre-internal.h>
ac0c6bdd 33#include <babeltrace/ctf-ir/clock-class-internal.h>
272df73e 34#include <babeltrace/ctf-ir/event-class-internal.h>
2e33ac5a
PP
35#include <babeltrace/ctf-ir/field-types-internal.h>
36#include <babeltrace/ctf-ir/fields-internal.h>
11b0cdc8 37#include <babeltrace/ctf-ir/stream-class-internal.h>
09840de5 38#include <babeltrace/ctf-ir/validation-internal.h>
8bf65fbd 39#include <babeltrace/ctf-ir/visitor-internal.h>
654c1444 40#include <babeltrace/ctf-ir/utils.h>
2a3ced3c 41#include <babeltrace/ctf-ir/utils-internal.h>
312c056a 42#include <babeltrace/ctf-ir/field-wrapper-internal.h>
83509119 43#include <babeltrace/ref.h>
3d9990ac
PP
44#include <babeltrace/compiler-internal.h>
45#include <babeltrace/align-internal.h>
46#include <babeltrace/endian-internal.h>
f6ccaed9 47#include <babeltrace/assert-internal.h>
dc3fffef 48#include <inttypes.h>
544d0515 49#include <stdint.h>
e011d2c1 50#include <stdbool.h>
11b0cdc8 51
cb6f1f7d
PP
52static inline
53int bt_stream_class_initialize(struct bt_stream_class *stream_class,
3dca2276 54 const char *name, bt_object_release_func release_func)
e0e2946b 55{
cb6f1f7d 56 BT_LOGD("Initializing stream class object: name=\"%s\"", name);
11b0cdc8 57
3fea54f6 58 bt_object_init_shared_with_parent(&stream_class->base, release_func);
11b0cdc8
JG
59 stream_class->name = g_string_new(name);
60 stream_class->event_classes = g_ptr_array_new_with_free_func(
3fea54f6 61 (GDestroyNotify) bt_object_try_spec_release);
11b0cdc8 62 if (!stream_class->event_classes) {
d2f71f12 63 BT_LOGE_STR("Failed to allocate a GPtrArray.");
83509119 64 goto error;
11b0cdc8
JG
65 }
66
0b9ce69f
JG
67 stream_class->event_classes_ht = g_hash_table_new_full(g_int64_hash,
68 g_int64_equal, g_free, NULL);
d2f71f12
PP
69 if (!stream_class->event_classes_ht) {
70 BT_LOGE_STR("Failed to allocate a GHashTable.");
71 goto error;
72 }
0b9ce69f 73
cb6f1f7d 74 BT_LOGD("Initialized stream class object: addr=%p, name=\"%s\"",
d2f71f12 75 stream_class, name);
3dca2276 76 return 0;
11b0cdc8 77
11b0cdc8 78error:
3dca2276 79 return -1;
142c5610
JG
80}
81
cb6f1f7d
PP
82static
83void bt_stream_class_destroy(struct bt_object *obj)
3ea33115 84{
cb6f1f7d
PP
85 struct bt_stream_class *stream_class = (void *) obj;
86
87 BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64,
88 stream_class, bt_stream_class_get_name(stream_class),
89 bt_stream_class_get_id(stream_class));
3dca2276 90 bt_put(stream_class->clock_class);
3ea33115 91
3dca2276
PP
92 if (stream_class->event_classes_ht) {
93 g_hash_table_destroy(stream_class->event_classes_ht);
94 }
95 if (stream_class->event_classes) {
96 BT_LOGD_STR("Destroying event classes.");
97 g_ptr_array_free(stream_class->event_classes, TRUE);
d2f71f12
PP
98 }
99
3dca2276
PP
100 if (stream_class->name) {
101 g_string_free(stream_class->name, TRUE);
3ea33115
JG
102 }
103
3dca2276
PP
104 BT_LOGD_STR("Putting event header field type.");
105 bt_put(stream_class->event_header_field_type);
106 BT_LOGD_STR("Putting packet context field type.");
107 bt_put(stream_class->packet_context_field_type);
108 BT_LOGD_STR("Putting event context field type.");
109 bt_put(stream_class->event_context_field_type);
312c056a
PP
110 bt_object_pool_finalize(&stream_class->event_header_field_pool);
111 bt_object_pool_finalize(&stream_class->packet_context_field_pool);
3dca2276 112 g_free(stream_class);
3ea33115
JG
113}
114
312c056a
PP
115static
116void free_field_wrapper(struct bt_field_wrapper *field_wrapper,
117 struct bt_stream_class *stream_class)
118{
119 bt_field_wrapper_destroy((void *) field_wrapper);
120}
121
3dca2276 122struct bt_stream_class *bt_stream_class_create(const char *name)
2f100782 123{
3dca2276
PP
124 struct bt_stream_class *stream_class = NULL;
125 int ret;
2f100782 126
3dca2276
PP
127 BT_LOGD("Creating stream class object: name=\"%s\"", name);
128 stream_class = g_new0(struct bt_stream_class, 1);
d2f71f12 129 if (!stream_class) {
3dca2276
PP
130 BT_LOGE_STR("Failed to allocate one stream class.");
131 goto error;
d2f71f12
PP
132 }
133
cb6f1f7d
PP
134 ret = bt_stream_class_initialize(stream_class, name,
135 bt_stream_class_destroy);
3dca2276 136 if (ret) {
cb6f1f7d 137 /* bt_stream_class_initialize() logs errors */
3dca2276 138 goto error;
2f100782
JG
139 }
140
312c056a
PP
141 ret = bt_object_pool_initialize(&stream_class->event_header_field_pool,
142 (bt_object_pool_new_object_func) bt_field_wrapper_new,
143 (bt_object_pool_destroy_object_func) free_field_wrapper,
144 stream_class);
145 if (ret) {
146 BT_LOGE("Failed to initialize event header field pool: ret=%d",
147 ret);
148 goto error;
149 }
150
151 ret = bt_object_pool_initialize(&stream_class->packet_context_field_pool,
152 (bt_object_pool_new_object_func) bt_field_wrapper_new,
153 (bt_object_pool_destroy_object_func) free_field_wrapper,
154 stream_class);
155 if (ret) {
156 BT_LOGE("Failed to initialize packet context field pool: ret=%d",
157 ret);
158 goto error;
159 }
160
3dca2276
PP
161 BT_LOGD("Created stream class object: addr=%p, name=\"%s\"",
162 stream_class, name);
163 return stream_class;
164
165error:
166 bt_put(stream_class);
167 return NULL;
2f100782
JG
168}
169
312c056a
PP
170struct bt_event_header_field *bt_stream_class_create_event_header_field(
171 struct bt_stream_class *stream_class)
172{
173 struct bt_field_wrapper *field_wrapper;
174
175 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
cb6f1f7d 176 BT_ASSERT_PRE(stream_class->frozen,
312c056a 177 "Stream class is not part of a trace: %!+S", stream_class);
cb6f1f7d 178 BT_ASSERT_PRE(stream_class->event_header_field_type,
312c056a
PP
179 "Stream class has no event header field type: %!+S",
180 stream_class);
181 field_wrapper = bt_field_wrapper_create(
182 &stream_class->event_header_field_pool,
cb6f1f7d 183 (void *) stream_class->event_header_field_type);
312c056a
PP
184 if (!field_wrapper) {
185 BT_LIB_LOGE("Cannot allocate one event header field from stream class: "
186 "%![sc-]+S", stream_class);
187 goto error;
188 }
189
190 BT_ASSERT(field_wrapper->field);
191 goto end;
192
193error:
194 if (field_wrapper) {
195 bt_field_wrapper_destroy(field_wrapper);
196 field_wrapper = NULL;
197 }
198
199end:
200 return (void *) field_wrapper;
201}
202
203struct bt_packet_context_field *bt_stream_class_create_packet_context_field(
204 struct bt_stream_class *stream_class)
205{
206 struct bt_field_wrapper *field_wrapper;
207
208 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
cb6f1f7d 209 BT_ASSERT_PRE(stream_class->frozen,
312c056a 210 "Stream class is not part of a trace: %!+S", stream_class);
cb6f1f7d 211 BT_ASSERT_PRE(stream_class->packet_context_field_type,
312c056a
PP
212 "Stream class has no packet context field type: %!+S",
213 stream_class);
214 field_wrapper = bt_field_wrapper_create(
215 &stream_class->packet_context_field_pool,
cb6f1f7d 216 (void *) stream_class->packet_context_field_type);
312c056a
PP
217 if (!field_wrapper) {
218 BT_LIB_LOGE("Cannot allocate one packet context field from stream class: "
219 "%![sc-]+S", stream_class);
220 goto error;
221 }
222
223 BT_ASSERT(field_wrapper->field);
224 goto end;
225
226error:
227 if (field_wrapper) {
228 bt_field_wrapper_destroy(field_wrapper);
229 field_wrapper = NULL;
230 }
231
232end:
233 return (void *) field_wrapper;
234}
235
094ff7c0 236struct bt_trace *bt_stream_class_borrow_trace(struct bt_stream_class *stream_class)
11b0cdc8 237{
cb6f1f7d
PP
238 BT_ASSERT(stream_class);
239 return (void *) bt_object_borrow_parent(&stream_class->base);
11b0cdc8
JG
240}
241
3dca2276 242const char *bt_stream_class_get_name(struct bt_stream_class *stream_class)
2f100782 243{
cb6f1f7d
PP
244 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
245 return stream_class->name->len > 0 ? stream_class->name->str : NULL;
2f100782
JG
246}
247
3dca2276
PP
248int bt_stream_class_set_name(struct bt_stream_class *stream_class,
249 const char *name)
5ca83563 250{
cb6f1f7d
PP
251 int ret = 0;
252
253 if (!stream_class) {
254 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
255 ret = -1;
256 goto end;
257 }
258
259 if (stream_class->frozen) {
260 BT_LOGW("Invalid parameter: stream class is frozen: "
261 "addr=%p, name=\"%s\", id=%" PRId64,
262 stream_class,
263 bt_stream_class_get_name(stream_class),
264 bt_stream_class_get_id(stream_class));
265 ret = -1;
266 goto end;
267 }
268
269 if (!name) {
270 g_string_assign(stream_class->name, "");
271 } else {
272 if (strlen(name) == 0) {
273 BT_LOGW("Invalid parameter: name is empty.");
274 ret = -1;
275 goto end;
276 }
277
278 g_string_assign(stream_class->name, name);
279 }
280
281 BT_LOGV("Set stream class's name: "
282 "addr=%p, name=\"%s\", id=%" PRId64,
283 stream_class, bt_stream_class_get_name(stream_class),
284 bt_stream_class_get_id(stream_class));
285end:
286 return ret;
5ca83563
JG
287}
288
3dca2276 289int64_t bt_stream_class_get_id(struct bt_stream_class *stream_class)
2f100782 290{
cb6f1f7d
PP
291 int64_t ret;
292
293 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
294
295 if (!stream_class->id_set) {
296 BT_LOGV("Stream class's ID is not set: addr=%p, name=\"%s\"",
297 stream_class,
298 bt_stream_class_get_name(stream_class));
299 ret = (int64_t) -1;
300 goto end;
301 }
302
303 ret = stream_class->id;
304
305end:
306 return ret;
2f100782
JG
307}
308
cb6f1f7d
PP
309int bt_stream_class_set_id(struct bt_stream_class *stream_class,
310 uint64_t id_param)
29664b2a 311{
cb6f1f7d
PP
312 int ret = 0;
313 int64_t id = (int64_t) id_param;
314
315 if (!stream_class) {
316 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
317 ret = -1;
318 goto end;
319 }
320
321 if (stream_class->frozen) {
322 BT_LOGW("Invalid parameter: stream class is frozen: "
323 "addr=%p, name=\"%s\", id=%" PRId64,
324 stream_class,
325 bt_stream_class_get_name(stream_class),
326 bt_stream_class_get_id(stream_class));
327 ret = -1;
328 goto end;
329 }
330
331 if (id < 0) {
332 BT_LOGW("Invalid parameter: invalid stream class's ID: "
333 "stream-class-addr=%p, stream-class-name=\"%s\", "
334 "stream-class-id=%" PRId64 ", id=%" PRIu64,
335 stream_class,
336 bt_stream_class_get_name(stream_class),
337 bt_stream_class_get_id(stream_class),
338 id_param);
339 ret = -1;
340 goto end;
341 }
342
343 ret = bt_stream_class_set_id_no_check(stream_class, id);
344 if (ret == 0) {
345 BT_LOGV("Set stream class's ID: "
346 "addr=%p, name=\"%s\", id=%" PRId64,
347 stream_class,
348 bt_stream_class_get_name(stream_class),
349 bt_stream_class_get_id(stream_class));
350 }
351end:
352 return ret;
29664b2a
PP
353}
354
0d23acbe
PP
355static
356void event_class_exists(gpointer element, gpointer query)
357{
cb6f1f7d 358 struct bt_event_class *event_class_a = element;
0d23acbe 359 struct search_query *search_query = query;
cb6f1f7d 360 struct bt_event_class *event_class_b = search_query->value;
0d23acbe
PP
361 int64_t id_a, id_b;
362
363 if (search_query->value == element) {
364 search_query->found = 1;
365 goto end;
366 }
367
0d23acbe
PP
368 /*
369 * Two event classes cannot share the same ID in a given
370 * stream class.
371 */
cb6f1f7d
PP
372 id_a = bt_event_class_get_id(event_class_a);
373 id_b = bt_event_class_get_id(event_class_b);
0d23acbe
PP
374
375 if (id_a < 0 || id_b < 0) {
376 /* at least one ID is not set: will be automatically set later */
377 goto end;
378 }
379
380 if (id_a == id_b) {
66871d36 381 BT_LOGW("Event class with this ID already exists in the stream class: "
d2f71f12 382 "id=%" PRId64 ", name=\"%s\"",
cb6f1f7d 383 id_a, bt_event_class_get_name(event_class_a));
0d23acbe
PP
384 search_query->found = 1;
385 goto end;
386 }
387
388end:
389 return;
390}
391
cb6f1f7d
PP
392int bt_stream_class_add_event_class(struct bt_stream_class *stream_class,
393 struct bt_event_class *event_class)
11b0cdc8
JG
394{
395 int ret = 0;
0b9ce69f 396 int64_t *event_id = NULL;
cb6f1f7d
PP
397 struct bt_trace *trace = NULL;
398 struct bt_stream_class *old_stream_class = NULL;
50842bdc 399 struct bt_validation_output validation_output = { 0 };
cb6f1f7d
PP
400 struct bt_field_type *packet_header_type = NULL;
401 struct bt_field_type *packet_context_type = NULL;
402 struct bt_field_type *event_header_type = NULL;
403 struct bt_field_type *stream_event_ctx_type = NULL;
404 struct bt_field_type *event_context_type = NULL;
405 struct bt_field_type *event_payload_type = NULL;
50842bdc
PP
406 const enum bt_validation_flag validation_flags =
407 BT_VALIDATION_FLAG_EVENT;
2a3ced3c 408 struct bt_clock_class *expected_clock_class = NULL;
11b0cdc8 409
cb6f1f7d
PP
410 if (!stream_class) {
411 BT_LOGW("Invalid parameter: stream class is NULL: "
412 "stream-class-addr=%p", stream_class);
413 ret = -1;
414 goto end;
415 }
416
417 trace = bt_stream_class_borrow_trace(stream_class);
418 if (trace && trace->is_static) {
419 BT_LOGW("Invalid parameter: stream class's trace is static: "
420 "trace-addr=%p, trace-name=\"%s\"",
421 trace, bt_trace_get_name(trace));
422 ret = -1;
423 goto end;
424 }
3dca2276 425
e011d2c1
PP
426 if (!stream_class || !event_class) {
427 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
428 "stream-class-addr=%p, event-class-addr=%p",
429 stream_class, event_class);
430 ret = -1;
431 goto end;
432 }
433
d2f71f12
PP
434 BT_LOGD("Adding event class to stream class: "
435 "stream-class-addr=%p, stream-class-name=\"%s\", "
436 "stream-class-id=%" PRId64 ", event-class-addr=%p, "
437 "event-class-name=\"%s\", event-class-id=%" PRId64,
cb6f1f7d
PP
438 stream_class, bt_stream_class_get_name(stream_class),
439 bt_stream_class_get_id(stream_class),
d2f71f12 440 event_class,
cb6f1f7d
PP
441 bt_event_class_get_name(event_class),
442 bt_event_class_get_id(event_class));
443 trace = bt_stream_class_borrow_trace(stream_class);
5acf2ae6 444
2a3ced3c
PP
445 if (stream_class->frozen) {
446 /*
447 * We only check that the event class to be added has a
448 * single class which matches the stream class's
449 * expected clock class if the stream class is frozen.
450 * If it's not, then this event class is added "as is"
451 * and the validation will be performed when calling
452 * either bt_trace_add_stream_class() or
453 * bt_event_create(). This is because the stream class's
454 * field types (packet context, event header, event
455 * context) could change before the next call to one of
456 * those two functions.
457 */
458 expected_clock_class = bt_get(stream_class->clock_class);
459
460 /*
461 * At this point, `expected_clock_class` can be NULL,
462 * and bt_event_class_validate_single_clock_class()
463 * below can set it.
464 */
cb6f1f7d 465 ret = bt_event_class_validate_single_clock_class(
2a3ced3c
PP
466 event_class, &expected_clock_class);
467 if (ret) {
468 BT_LOGW("Event class contains a field type which is not "
469 "recursively mapped to its stream class's "
470 "expected clock class: "
471 "stream-class-addr=%p, "
472 "stream-class-id=%" PRId64 ", "
473 "stream-class-name=\"%s\", "
474 "expected-clock-class-addr=%p, "
475 "expected-clock-class-name=\"%s\"",
476 stream_class,
cb6f1f7d
PP
477 bt_stream_class_get_id(stream_class),
478 bt_stream_class_get_name(stream_class),
2a3ced3c
PP
479 expected_clock_class,
480 expected_clock_class ?
481 bt_clock_class_get_name(expected_clock_class) :
482 NULL);
483 goto end;
484 }
485 }
486
0b9ce69f
JG
487 event_id = g_new(int64_t, 1);
488 if (!event_id) {
d2f71f12 489 BT_LOGE_STR("Failed to allocate one int64_t.");
0b9ce69f
JG
490 ret = -1;
491 goto end;
492 }
493
11b0cdc8
JG
494 /* Check for duplicate event classes */
495 struct search_query query = { .value = event_class, .found = 0 };
0d23acbe
PP
496 g_ptr_array_foreach(stream_class->event_classes, event_class_exists,
497 &query);
11b0cdc8 498 if (query.found) {
d2f71f12 499 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
11b0cdc8
JG
500 ret = -1;
501 goto end;
502 }
503
cb6f1f7d 504 old_stream_class = bt_event_class_borrow_stream_class(event_class);
e6a8e8e4
JG
505 if (old_stream_class) {
506 /* Event class is already associated to a stream class. */
d2f71f12
PP
507 BT_LOGW("Event class is already part of another stream class: "
508 "event-class-stream-class-addr=%p, "
509 "event-class-stream-class-name=\"%s\", "
510 "event-class-stream-class-id=%" PRId64,
511 old_stream_class,
cb6f1f7d
PP
512 bt_stream_class_get_name(old_stream_class),
513 bt_stream_class_get_id(old_stream_class));
e6a8e8e4
JG
514 ret = -1;
515 goto end;
516 }
517
e6a8e8e4 518 if (trace) {
09840de5
PP
519 /*
520 * If the stream class is associated with a trace, then
521 * both those objects are frozen. Also, this event class
522 * is about to be frozen.
523 *
524 * Therefore the event class must be validated here.
525 * The trace and stream class should be valid at this
526 * point.
527 */
f6ccaed9
PP
528 BT_ASSERT(trace->valid);
529 BT_ASSERT(stream_class->valid);
09840de5 530 packet_header_type =
cb6f1f7d 531 bt_trace_borrow_packet_header_field_type(trace);
09840de5 532 packet_context_type =
cb6f1f7d 533 bt_stream_class_borrow_packet_context_field_type(
09840de5
PP
534 stream_class);
535 event_header_type =
cb6f1f7d 536 bt_stream_class_borrow_event_header_field_type(
3dca2276 537 stream_class);
09840de5 538 stream_event_ctx_type =
cb6f1f7d 539 bt_stream_class_borrow_event_context_field_type(
09840de5
PP
540 stream_class);
541 event_context_type =
cb6f1f7d 542 bt_event_class_borrow_context_field_type(
094ff7c0 543 event_class);
09840de5 544 event_payload_type =
cb6f1f7d 545 bt_event_class_borrow_payload_field_type(
094ff7c0 546 event_class);
50842bdc 547 ret = bt_validate_class_types(
09840de5
PP
548 trace->environment, packet_header_type,
549 packet_context_type, event_header_type,
550 stream_event_ctx_type, event_context_type,
551 event_payload_type, trace->valid,
552 stream_class->valid, event_class->valid,
3dca2276 553 &validation_output, validation_flags,
cb6f1f7d 554 bt_field_type_copy);
09840de5 555
26079216 556 if (ret) {
09840de5
PP
557 /*
558 * This means something went wrong during the
559 * validation process, not that the objects are
560 * invalid.
561 */
d2f71f12 562 BT_LOGE("Failed to validate event class: ret=%d", ret);
09840de5
PP
563 goto end;
564 }
565
566 if ((validation_output.valid_flags & validation_flags) !=
567 validation_flags) {
568 /* Invalid event class */
66871d36 569 BT_LOGW("Invalid trace, stream class, or event class: "
d2f71f12
PP
570 "valid-flags=0x%x",
571 validation_output.valid_flags);
09840de5 572 ret = -1;
26079216
JG
573 goto end;
574 }
575 }
576
09840de5 577 /* Only set an event ID if none was explicitly set before */
cb6f1f7d 578 *event_id = bt_event_class_get_id(event_class);
24626e8b 579 if (*event_id < 0) {
d2f71f12
PP
580 BT_LOGV("Event class has no ID: automatically setting it: "
581 "id=%" PRId64, stream_class->next_event_id);
582
cb6f1f7d 583 if (bt_event_class_set_id(event_class,
d2f71f12
PP
584 stream_class->next_event_id)) {
585 BT_LOGE("Cannot set event class's ID: id=%" PRId64,
586 stream_class->next_event_id);
2f100782
JG
587 ret = -1;
588 goto end;
589 }
d2f71f12 590 stream_class->next_event_id++;
0b9ce69f 591 *event_id = stream_class->next_event_id;
2f100782
JG
592 }
593
3fea54f6 594 bt_object_set_parent(&event_class->base, &stream_class->base);
09840de5
PP
595
596 if (trace) {
597 /*
598 * At this point we know that the function will be
599 * successful. Therefore we can replace the event
600 * class's field types with what's in the validation
601 * output structure and mark this event class as valid.
602 */
50842bdc 603 bt_validation_replace_types(NULL, NULL, event_class,
09840de5
PP
604 &validation_output, validation_flags);
605 event_class->valid = 1;
606
607 /*
608 * Put what was not moved in
50842bdc 609 * bt_validation_replace_types().
09840de5 610 */
50842bdc 611 bt_validation_output_put_types(&validation_output);
09840de5
PP
612 }
613
614 /* Add to the event classes of the stream class */
11b0cdc8 615 g_ptr_array_add(stream_class->event_classes, event_class);
0b9ce69f
JG
616 g_hash_table_insert(stream_class->event_classes_ht, event_id,
617 event_class);
618 event_id = NULL;
09840de5
PP
619
620 /* Freeze the event class */
cb6f1f7d 621 bt_event_class_freeze(event_class);
5ca83563 622
2a3ced3c
PP
623 /*
624 * It is safe to set the stream class's unique clock class
625 * now if the stream class is frozen.
626 */
627 if (stream_class->frozen && expected_clock_class) {
f6ccaed9 628 BT_ASSERT(!stream_class->clock_class ||
2a3ced3c
PP
629 stream_class->clock_class == expected_clock_class);
630 BT_MOVE(stream_class->clock_class, expected_clock_class);
631 }
632
cb6f1f7d
PP
633 /* Notifiy listeners of the trace's schema modification. */
634 if (trace) {
635 struct bt_visitor_object obj = { .object = event_class,
636 .type = BT_VISITOR_OBJECT_TYPE_EVENT_CLASS };
637
638 (void) bt_trace_object_modification(&obj, trace);
639 }
640
d2f71f12
PP
641 BT_LOGD("Added event class to stream class: "
642 "stream-class-addr=%p, stream-class-name=\"%s\", "
643 "stream-class-id=%" PRId64 ", event-class-addr=%p, "
644 "event-class-name=\"%s\", event-class-id=%" PRId64,
cb6f1f7d
PP
645 stream_class, bt_stream_class_get_name(stream_class),
646 bt_stream_class_get_id(stream_class),
d2f71f12 647 event_class,
cb6f1f7d
PP
648 bt_event_class_get_name(event_class),
649 bt_event_class_get_id(event_class));
d2f71f12 650
11b0cdc8 651end:
50842bdc 652 bt_validation_output_put_types(&validation_output);
2a3ced3c 653 bt_put(expected_clock_class);
0b9ce69f 654 g_free(event_id);
11b0cdc8
JG
655 return ret;
656}
657
cb6f1f7d
PP
658int64_t bt_stream_class_get_event_class_count(
659 struct bt_stream_class *stream_class)
69dc4535 660{
cb6f1f7d 661 int64_t ret;
69dc4535
JG
662
663 if (!stream_class) {
cb6f1f7d
PP
664 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
665 ret = (int64_t) -1;
69dc4535
JG
666 goto end;
667 }
668
cb6f1f7d 669 ret = (int64_t) stream_class->event_classes->len;
69dc4535
JG
670end:
671 return ret;
672}
673
094ff7c0 674struct bt_event_class *bt_stream_class_borrow_event_class_by_index(
50842bdc 675 struct bt_stream_class *stream_class, uint64_t index)
69dc4535 676{
cb6f1f7d
PP
677 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
678 BT_ASSERT_PRE(index < stream_class->event_classes->len,
679 "Index is out of bounds: index=%" PRIu64 ", "
680 "count=%u",
681 index, stream_class->event_classes->len);
682 return g_ptr_array_index(stream_class->event_classes, index);
69dc4535
JG
683}
684
094ff7c0 685struct bt_event_class *bt_stream_class_borrow_event_class_by_id(
50842bdc 686 struct bt_stream_class *stream_class, uint64_t id)
0863f950 687{
cb6f1f7d
PP
688 int64_t id_key = (int64_t) id;
689
690 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
691 BT_ASSERT_PRE(id_key >= 0,
692 "Invalid event class ID: %" PRIu64, id);
693 return g_hash_table_lookup(stream_class->event_classes_ht,
694 &id_key);
0863f950
PP
695}
696
094ff7c0 697struct bt_field_type *bt_stream_class_borrow_packet_context_field_type(
50842bdc 698 struct bt_stream_class *stream_class)
12c8a1a3 699{
cb6f1f7d
PP
700 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
701 return stream_class->packet_context_field_type;
12c8a1a3
JG
702}
703
3dca2276 704int bt_stream_class_set_packet_context_field_type(
50842bdc
PP
705 struct bt_stream_class *stream_class,
706 struct bt_field_type *packet_context_type)
12c8a1a3 707{
cb6f1f7d
PP
708 int ret = 0;
709
710 if (!stream_class) {
711 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
712 ret = -1;
713 goto end;
714 }
715
716 if (stream_class->frozen) {
717 BT_LOGW("Invalid parameter: stream class is frozen: "
718 "addr=%p, name=\"%s\", id=%" PRId64,
719 stream_class, bt_stream_class_get_name(stream_class),
720 bt_stream_class_get_id(stream_class));
721 ret = -1;
722 goto end;
723 }
724
725 if (packet_context_type &&
726 bt_field_type_get_type_id(packet_context_type) !=
727 BT_FIELD_TYPE_ID_STRUCT) {
728 /* A packet context must be a structure. */
729 BT_LOGW("Invalid parameter: stream class's packet context field type must be a structure: "
730 "addr=%p, name=\"%s\", id=%" PRId64 ", "
731 "packet-context-ft-addr=%p, packet-context-ft-id=%s",
732 stream_class, bt_stream_class_get_name(stream_class),
733 bt_stream_class_get_id(stream_class),
734 packet_context_type,
735 bt_common_field_type_id_string(
736 bt_field_type_get_type_id(packet_context_type)));
737 ret = -1;
738 goto end;
739 }
740
741 bt_put(stream_class->packet_context_field_type);
742 bt_get(packet_context_type);
743 stream_class->packet_context_field_type = packet_context_type;
744 BT_LOGV("Set stream class's packet context field type: "
745 "addr=%p, name=\"%s\", id=%" PRId64 ", "
746 "packet-context-ft-addr=%p",
747 stream_class, bt_stream_class_get_name(stream_class),
748 bt_stream_class_get_id(stream_class),
749 packet_context_type);
750
751end:
752 return ret;
12c8a1a3
JG
753}
754
094ff7c0 755struct bt_field_type *bt_stream_class_borrow_event_header_field_type(
50842bdc 756 struct bt_stream_class *stream_class)
662e778c 757{
cb6f1f7d
PP
758 struct bt_field_type *ret = NULL;
759
760 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
761
762 if (!stream_class->event_header_field_type) {
763 BT_LOGV("Stream class has no event header field type: "
764 "addr=%p, name=\"%s\", id=%" PRId64,
765 stream_class,
766 bt_stream_class_get_name(stream_class),
767 bt_stream_class_get_id(stream_class));
768 goto end;
769 }
770
771 ret = stream_class->event_header_field_type;
772
773end:
774 return ret;
662e778c
JG
775}
776
3dca2276 777int bt_stream_class_set_event_header_field_type(
50842bdc
PP
778 struct bt_stream_class *stream_class,
779 struct bt_field_type *event_header_type)
662e778c 780{
cb6f1f7d
PP
781 int ret = 0;
782
783 if (!stream_class) {
784 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
785 ret = -1;
786 goto end;
787 }
788
789 if (stream_class->frozen) {
790 BT_LOGW("Invalid parameter: stream class is frozen: "
791 "addr=%p, name=\"%s\", id=%" PRId64,
792 stream_class,
793 bt_stream_class_get_name(stream_class),
794 bt_stream_class_get_id(stream_class));
795 ret = -1;
796 goto end;
797 }
798
799 if (event_header_type &&
800 bt_field_type_get_type_id(event_header_type) !=
801 BT_FIELD_TYPE_ID_STRUCT) {
802 /* An event header must be a structure. */
803 BT_LOGW("Invalid parameter: stream class's event header field type must be a structure: "
804 "addr=%p, name=\"%s\", id=%" PRId64 ", "
805 "event-header-ft-addr=%p, event-header-ft-id=%s",
806 stream_class, bt_stream_class_get_name(stream_class),
807 bt_stream_class_get_id(stream_class),
808 event_header_type,
809 bt_common_field_type_id_string(
810 bt_field_type_get_type_id(event_header_type)));
811 ret = -1;
812 goto end;
813 }
814
815 bt_put(stream_class->event_header_field_type);
816 stream_class->event_header_field_type = bt_get(event_header_type);
817 BT_LOGV("Set stream class's event header field type: "
818 "addr=%p, name=\"%s\", id=%" PRId64 ", "
819 "event-header-ft-addr=%p",
820 stream_class, bt_stream_class_get_name(stream_class),
821 bt_stream_class_get_id(stream_class),
822 event_header_type);
823end:
824 return ret;
662e778c
JG
825}
826
094ff7c0 827struct bt_field_type *bt_stream_class_borrow_event_context_field_type(
50842bdc 828 struct bt_stream_class *stream_class)
af181248 829{
cb6f1f7d
PP
830 struct bt_field_type *ret = NULL;
831
832 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
833
834 if (!stream_class->event_context_field_type) {
835 goto end;
836 }
837
838 ret = stream_class->event_context_field_type;
839
840end:
841 return ret;
af181248
JG
842}
843
3dca2276 844int bt_stream_class_set_event_context_field_type(
50842bdc
PP
845 struct bt_stream_class *stream_class,
846 struct bt_field_type *event_context_type)
af181248 847{
cb6f1f7d
PP
848 int ret = 0;
849
850 if (!stream_class) {
851 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
852 ret = -1;
853 goto end;
854 }
855
856 if (stream_class->frozen) {
857 BT_LOGW("Invalid parameter: stream class is frozen: "
858 "addr=%p, name=\"%s\", id=%" PRId64,
859 stream_class, bt_stream_class_get_name(stream_class),
860 bt_stream_class_get_id(stream_class));
861 ret = -1;
862 goto end;
863 }
864
865 if (event_context_type &&
866 bt_field_type_get_type_id(event_context_type) !=
867 BT_FIELD_TYPE_ID_STRUCT) {
868 /* A packet context must be a structure. */
869 BT_LOGW("Invalid parameter: stream class's event context field type must be a structure: "
870 "addr=%p, name=\"%s\", id=%" PRId64 ", "
871 "event-context-ft-addr=%p, event-context-ft-id=%s",
872 stream_class, bt_stream_class_get_name(stream_class),
873 bt_stream_class_get_id(stream_class),
874 event_context_type,
875 bt_common_field_type_id_string(
876 bt_field_type_get_type_id(event_context_type)));
877 ret = -1;
878 goto end;
879 }
880
881 bt_put(stream_class->event_context_field_type);
882 stream_class->event_context_field_type = bt_get(event_context_type);
883 BT_LOGV("Set stream class's event context field type: "
884 "addr=%p, name=\"%s\", id=%" PRId64 ", "
885 "event-context-ft-addr=%p",
886 stream_class, bt_stream_class_get_name(stream_class),
887 bt_stream_class_get_id(stream_class),
888 event_context_type);
889end:
890 return ret;
11b0cdc8
JG
891}
892
8bf65fbd 893static
544d0515 894int64_t get_event_class_count(void *element)
8bf65fbd 895{
50842bdc
PP
896 return bt_stream_class_get_event_class_count(
897 (struct bt_stream_class *) element);
8bf65fbd
JG
898}
899
900static
901void *get_event_class(void *element, int i)
902{
50842bdc
PP
903 return bt_stream_class_get_event_class_by_index(
904 (struct bt_stream_class *) element, i);
8bf65fbd
JG
905}
906
907static
50842bdc 908int visit_event_class(void *object, bt_visitor visitor,void *data)
8bf65fbd 909{
3dca2276
PP
910 struct bt_visitor_object obj = {
911 .object = object,
912 .type = BT_VISITOR_OBJECT_TYPE_EVENT_CLASS
913 };
8bf65fbd 914
d9a13d86 915 return visitor(&obj, data);
8bf65fbd
JG
916}
917
3dca2276 918BT_HIDDEN
cb6f1f7d 919int bt_stream_class_visit(struct bt_stream_class *stream_class,
50842bdc 920 bt_visitor visitor, void *data)
8bf65fbd
JG
921{
922 int ret;
3dca2276
PP
923 struct bt_visitor_object obj = {
924 .object = stream_class,
925 .type = BT_VISITOR_OBJECT_TYPE_STREAM_CLASS
926 };
8bf65fbd
JG
927
928 if (!stream_class || !visitor) {
d2f71f12
PP
929 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
930 "stream-class-addr=%p, visitor=%p",
931 stream_class, visitor);
8bf65fbd
JG
932 ret = -1;
933 goto end;
934 }
935
d9a13d86 936 ret = visitor_helper(&obj, get_event_class_count,
8bf65fbd
JG
937 get_event_class,
938 visit_event_class, visitor, data);
d2f71f12 939 BT_LOGV("visitor_helper() returned: ret=%d", ret);
3dca2276 940
8bf65fbd
JG
941end:
942 return ret;
943}
944
11b0cdc8 945BT_HIDDEN
cb6f1f7d 946void bt_stream_class_freeze(struct bt_stream_class *stream_class)
11b0cdc8 947{
d2f71f12 948 if (!stream_class || stream_class->frozen) {
11b0cdc8
JG
949 return;
950 }
951
d2f71f12 952 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64,
cb6f1f7d
PP
953 stream_class, bt_stream_class_get_name(stream_class),
954 bt_stream_class_get_id(stream_class));
11b0cdc8 955 stream_class->frozen = 1;
cb6f1f7d
PP
956 bt_field_type_freeze(stream_class->event_header_field_type);
957 bt_field_type_freeze(stream_class->packet_context_field_type);
958 bt_field_type_freeze(stream_class->event_context_field_type);
3dca2276 959 bt_clock_class_freeze(stream_class->clock_class);
11b0cdc8
JG
960}
961
2a3ced3c 962BT_HIDDEN
cb6f1f7d
PP
963int bt_stream_class_validate_single_clock_class(
964 struct bt_stream_class *stream_class,
2a3ced3c
PP
965 struct bt_clock_class **expected_clock_class)
966{
967 int ret;
968 uint64_t i;
969
f6ccaed9
PP
970 BT_ASSERT(stream_class);
971 BT_ASSERT(expected_clock_class);
cb6f1f7d 972 ret = bt_field_type_validate_single_clock_class(
3dca2276 973 stream_class->packet_context_field_type,
2a3ced3c
PP
974 expected_clock_class);
975 if (ret) {
976 BT_LOGW("Stream class's packet context field type "
977 "is not recursively mapped to the "
978 "expected clock class: "
979 "stream-class-addr=%p, "
980 "stream-class-name=\"%s\", "
981 "stream-class-id=%" PRId64 ", "
982 "ft-addr=%p",
983 stream_class,
cb6f1f7d 984 bt_stream_class_get_name(stream_class),
2a3ced3c 985 stream_class->id,
3dca2276 986 stream_class->packet_context_field_type);
2a3ced3c
PP
987 goto end;
988 }
989
cb6f1f7d 990 ret = bt_field_type_validate_single_clock_class(
3dca2276 991 stream_class->event_header_field_type,
2a3ced3c
PP
992 expected_clock_class);
993 if (ret) {
994 BT_LOGW("Stream class's event header field type "
995 "is not recursively mapped to the "
996 "expected clock class: "
997 "stream-class-addr=%p, "
998 "stream-class-name=\"%s\", "
999 "stream-class-id=%" PRId64 ", "
1000 "ft-addr=%p",
1001 stream_class,
cb6f1f7d 1002 bt_stream_class_get_name(stream_class),
2a3ced3c 1003 stream_class->id,
3dca2276 1004 stream_class->event_header_field_type);
2a3ced3c
PP
1005 goto end;
1006 }
1007
cb6f1f7d 1008 ret = bt_field_type_validate_single_clock_class(
3dca2276 1009 stream_class->event_context_field_type,
2a3ced3c
PP
1010 expected_clock_class);
1011 if (ret) {
1012 BT_LOGW("Stream class's event context field type "
1013 "is not recursively mapped to the "
1014 "expected clock class: "
1015 "stream-class-addr=%p, "
1016 "stream-class-name=\"%s\", "
1017 "stream-class-id=%" PRId64 ", "
1018 "ft-addr=%p",
1019 stream_class,
cb6f1f7d 1020 bt_stream_class_get_name(stream_class),
2a3ced3c 1021 stream_class->id,
3dca2276 1022 stream_class->event_context_field_type);
2a3ced3c
PP
1023 goto end;
1024 }
1025
1026 for (i = 0; i < stream_class->event_classes->len; i++) {
cb6f1f7d 1027 struct bt_event_class *event_class =
2a3ced3c
PP
1028 g_ptr_array_index(stream_class->event_classes, i);
1029
f6ccaed9 1030 BT_ASSERT(event_class);
cb6f1f7d 1031 ret = bt_event_class_validate_single_clock_class(
3dca2276 1032 event_class, expected_clock_class);
2a3ced3c
PP
1033 if (ret) {
1034 BT_LOGW("Stream class's event class contains a "
1035 "field type which is not recursively mapped to "
1036 "the expected clock class: "
1037 "stream-class-addr=%p, "
1038 "stream-class-name=\"%s\", "
1039 "stream-class-id=%" PRId64,
1040 stream_class,
cb6f1f7d 1041 bt_stream_class_get_name(stream_class),
2a3ced3c
PP
1042 stream_class->id);
1043 goto end;
1044 }
1045 }
1046
1047end:
1048 return ret;
1049}
This page took 0.095186 seconds and 4 git commands to generate.