lib: add internal object pool API and use it; adapt plugins/tests
[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
3dca2276
PP
52BT_HIDDEN
53int bt_stream_class_common_initialize(struct bt_stream_class_common *stream_class,
54 const char *name, bt_object_release_func release_func)
e0e2946b 55{
3dca2276 56 BT_LOGD("Initializing common stream class object: name=\"%s\"", name);
11b0cdc8 57
3dca2276 58 bt_object_init(stream_class, release_func);
11b0cdc8
JG
59 stream_class->name = g_string_new(name);
60 stream_class->event_classes = g_ptr_array_new_with_free_func(
e6a8e8e4 61 (GDestroyNotify) bt_object_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
3dca2276 74 BT_LOGD("Initialized common 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
3dca2276
PP
82BT_HIDDEN
83void bt_stream_class_common_finalize(struct bt_stream_class_common *stream_class)
3ea33115 84{
3dca2276
PP
85 BT_LOGD("Finalizing common stream class: addr=%p, name=\"%s\", id=%" PRId64,
86 stream_class, bt_stream_class_common_get_name(stream_class),
87 bt_stream_class_common_get_id(stream_class));
88 bt_put(stream_class->clock_class);
3ea33115 89
3dca2276
PP
90 if (stream_class->event_classes_ht) {
91 g_hash_table_destroy(stream_class->event_classes_ht);
92 }
93 if (stream_class->event_classes) {
94 BT_LOGD_STR("Destroying event classes.");
95 g_ptr_array_free(stream_class->event_classes, TRUE);
d2f71f12
PP
96 }
97
3dca2276
PP
98 if (stream_class->name) {
99 g_string_free(stream_class->name, TRUE);
3ea33115
JG
100 }
101
3dca2276
PP
102 BT_LOGD_STR("Putting event header field type.");
103 bt_put(stream_class->event_header_field_type);
104 BT_LOGD_STR("Putting packet context field type.");
105 bt_put(stream_class->packet_context_field_type);
106 BT_LOGD_STR("Putting event context field type.");
107 bt_put(stream_class->event_context_field_type);
108}
03be3bcd 109
3dca2276
PP
110static
111void bt_stream_class_destroy(struct bt_object *obj)
112{
113 struct bt_stream_class *stream_class;
03be3bcd 114
3dca2276
PP
115 stream_class = (void *) obj;
116 BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64,
50842bdc
PP
117 stream_class, bt_stream_class_get_name(stream_class),
118 bt_stream_class_get_id(stream_class));
312c056a
PP
119
120 /*
121 * IMPORTANT: Finalize the common stream class BEFORE finalizing
122 * the pools because otherwise this scenario is possible:
123 *
124 * 1. Event header field object pool is finalized, thus
125 * destroying its internal array and state.
126 *
127 * 2. Stream class is finalized: each event class is destroyed.
128 *
129 * 3. Destroying an event class finalizes its event pool,
130 * destroying each contained event.
131 *
132 * 4. Destroying an event makes it recycle its event header
133 * field to its stream class's event header field pool. But
134 * said pool is already destroyed.
135 */
3dca2276 136 bt_stream_class_common_finalize(BT_TO_COMMON(stream_class));
312c056a
PP
137 bt_object_pool_finalize(&stream_class->event_header_field_pool);
138 bt_object_pool_finalize(&stream_class->packet_context_field_pool);
3dca2276 139 g_free(stream_class);
3ea33115
JG
140}
141
312c056a
PP
142static
143void free_field_wrapper(struct bt_field_wrapper *field_wrapper,
144 struct bt_stream_class *stream_class)
145{
146 bt_field_wrapper_destroy((void *) field_wrapper);
147}
148
3dca2276 149struct bt_stream_class *bt_stream_class_create(const char *name)
2f100782 150{
3dca2276
PP
151 struct bt_stream_class *stream_class = NULL;
152 int ret;
2f100782 153
3dca2276
PP
154 BT_LOGD("Creating stream class object: name=\"%s\"", name);
155 stream_class = g_new0(struct bt_stream_class, 1);
d2f71f12 156 if (!stream_class) {
3dca2276
PP
157 BT_LOGE_STR("Failed to allocate one stream class.");
158 goto error;
d2f71f12
PP
159 }
160
3dca2276
PP
161 ret = bt_stream_class_common_initialize(BT_TO_COMMON(stream_class),
162 name, bt_stream_class_destroy);
163 if (ret) {
164 /* bt_stream_class_common_initialize() logs errors */
165 goto error;
2f100782
JG
166 }
167
312c056a
PP
168 ret = bt_object_pool_initialize(&stream_class->event_header_field_pool,
169 (bt_object_pool_new_object_func) bt_field_wrapper_new,
170 (bt_object_pool_destroy_object_func) free_field_wrapper,
171 stream_class);
172 if (ret) {
173 BT_LOGE("Failed to initialize event header field pool: ret=%d",
174 ret);
175 goto error;
176 }
177
178 ret = bt_object_pool_initialize(&stream_class->packet_context_field_pool,
179 (bt_object_pool_new_object_func) bt_field_wrapper_new,
180 (bt_object_pool_destroy_object_func) free_field_wrapper,
181 stream_class);
182 if (ret) {
183 BT_LOGE("Failed to initialize packet context field pool: ret=%d",
184 ret);
185 goto error;
186 }
187
3dca2276
PP
188 BT_LOGD("Created stream class object: addr=%p, name=\"%s\"",
189 stream_class, name);
190 return stream_class;
191
192error:
193 bt_put(stream_class);
194 return NULL;
2f100782
JG
195}
196
312c056a
PP
197struct bt_event_header_field *bt_stream_class_create_event_header_field(
198 struct bt_stream_class *stream_class)
199{
200 struct bt_field_wrapper *field_wrapper;
201
202 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
203 BT_ASSERT_PRE(stream_class->common.frozen,
204 "Stream class is not part of a trace: %!+S", stream_class);
205 BT_ASSERT_PRE(stream_class->common.event_header_field_type,
206 "Stream class has no event header field type: %!+S",
207 stream_class);
208 field_wrapper = bt_field_wrapper_create(
209 &stream_class->event_header_field_pool,
210 (void *) stream_class->common.event_header_field_type);
211 if (!field_wrapper) {
212 BT_LIB_LOGE("Cannot allocate one event header field from stream class: "
213 "%![sc-]+S", stream_class);
214 goto error;
215 }
216
217 BT_ASSERT(field_wrapper->field);
218 goto end;
219
220error:
221 if (field_wrapper) {
222 bt_field_wrapper_destroy(field_wrapper);
223 field_wrapper = NULL;
224 }
225
226end:
227 return (void *) field_wrapper;
228}
229
230struct bt_packet_context_field *bt_stream_class_create_packet_context_field(
231 struct bt_stream_class *stream_class)
232{
233 struct bt_field_wrapper *field_wrapper;
234
235 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
236 BT_ASSERT_PRE(stream_class->common.frozen,
237 "Stream class is not part of a trace: %!+S", stream_class);
238 BT_ASSERT_PRE(stream_class->common.packet_context_field_type,
239 "Stream class has no packet context field type: %!+S",
240 stream_class);
241 field_wrapper = bt_field_wrapper_create(
242 &stream_class->packet_context_field_pool,
243 (void *) stream_class->common.packet_context_field_type);
244 if (!field_wrapper) {
245 BT_LIB_LOGE("Cannot allocate one packet context field from stream class: "
246 "%![sc-]+S", stream_class);
247 goto error;
248 }
249
250 BT_ASSERT(field_wrapper->field);
251 goto end;
252
253error:
254 if (field_wrapper) {
255 bt_field_wrapper_destroy(field_wrapper);
256 field_wrapper = NULL;
257 }
258
259end:
260 return (void *) field_wrapper;
261}
262
094ff7c0 263struct bt_trace *bt_stream_class_borrow_trace(struct bt_stream_class *stream_class)
11b0cdc8 264{
094ff7c0 265 return BT_FROM_COMMON(bt_stream_class_common_borrow_trace(
3dca2276 266 BT_TO_COMMON(stream_class)));
11b0cdc8
JG
267}
268
3dca2276 269const char *bt_stream_class_get_name(struct bt_stream_class *stream_class)
2f100782 270{
3dca2276 271 return bt_stream_class_common_get_name(BT_TO_COMMON(stream_class));
2f100782
JG
272}
273
3dca2276
PP
274int bt_stream_class_set_name(struct bt_stream_class *stream_class,
275 const char *name)
5ca83563 276{
3dca2276
PP
277 return bt_stream_class_common_set_name(BT_TO_COMMON(stream_class),
278 name);
5ca83563
JG
279}
280
3dca2276 281int64_t bt_stream_class_get_id(struct bt_stream_class *stream_class)
2f100782 282{
3dca2276 283 return bt_stream_class_common_get_id(BT_TO_COMMON(stream_class));
2f100782
JG
284}
285
3dca2276 286int bt_stream_class_set_id(struct bt_stream_class *stream_class, uint64_t id)
29664b2a 287{
3dca2276 288 return bt_stream_class_common_set_id(BT_TO_COMMON(stream_class), id);
29664b2a
PP
289}
290
0d23acbe
PP
291static
292void event_class_exists(gpointer element, gpointer query)
293{
3dca2276 294 struct bt_event_class_common *event_class_a = element;
0d23acbe 295 struct search_query *search_query = query;
3dca2276 296 struct bt_event_class_common *event_class_b = search_query->value;
0d23acbe
PP
297 int64_t id_a, id_b;
298
299 if (search_query->value == element) {
300 search_query->found = 1;
301 goto end;
302 }
303
0d23acbe
PP
304 /*
305 * Two event classes cannot share the same ID in a given
306 * stream class.
307 */
3dca2276
PP
308 id_a = bt_event_class_common_get_id(event_class_a);
309 id_b = bt_event_class_common_get_id(event_class_b);
0d23acbe
PP
310
311 if (id_a < 0 || id_b < 0) {
312 /* at least one ID is not set: will be automatically set later */
313 goto end;
314 }
315
316 if (id_a == id_b) {
66871d36 317 BT_LOGW("Event class with this ID already exists in the stream class: "
d2f71f12 318 "id=%" PRId64 ", name=\"%s\"",
3dca2276 319 id_a, bt_event_class_common_get_name(event_class_a));
0d23acbe
PP
320 search_query->found = 1;
321 goto end;
322 }
323
324end:
325 return;
326}
327
3dca2276
PP
328BT_HIDDEN
329int bt_stream_class_common_add_event_class(
330 struct bt_stream_class_common *stream_class,
331 struct bt_event_class_common *event_class,
332 bt_validation_flag_copy_field_type_func copy_field_type_func)
11b0cdc8
JG
333{
334 int ret = 0;
0b9ce69f 335 int64_t *event_id = NULL;
3dca2276
PP
336 struct bt_trace_common *trace = NULL;
337 struct bt_stream_class_common *old_stream_class = NULL;
50842bdc 338 struct bt_validation_output validation_output = { 0 };
3dca2276
PP
339 struct bt_field_type_common *packet_header_type = NULL;
340 struct bt_field_type_common *packet_context_type = NULL;
341 struct bt_field_type_common *event_header_type = NULL;
342 struct bt_field_type_common *stream_event_ctx_type = NULL;
343 struct bt_field_type_common *event_context_type = NULL;
344 struct bt_field_type_common *event_payload_type = NULL;
50842bdc
PP
345 const enum bt_validation_flag validation_flags =
346 BT_VALIDATION_FLAG_EVENT;
2a3ced3c 347 struct bt_clock_class *expected_clock_class = NULL;
11b0cdc8 348
3dca2276
PP
349 BT_ASSERT(copy_field_type_func);
350
e011d2c1
PP
351 if (!stream_class || !event_class) {
352 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
353 "stream-class-addr=%p, event-class-addr=%p",
354 stream_class, event_class);
355 ret = -1;
356 goto end;
357 }
358
d2f71f12
PP
359 BT_LOGD("Adding event class to stream class: "
360 "stream-class-addr=%p, stream-class-name=\"%s\", "
361 "stream-class-id=%" PRId64 ", event-class-addr=%p, "
362 "event-class-name=\"%s\", event-class-id=%" PRId64,
3dca2276
PP
363 stream_class, bt_stream_class_common_get_name(stream_class),
364 bt_stream_class_common_get_id(stream_class),
d2f71f12 365 event_class,
3dca2276
PP
366 bt_event_class_common_get_name(event_class),
367 bt_event_class_common_get_id(event_class));
094ff7c0 368 trace = bt_stream_class_common_borrow_trace(stream_class);
5acf2ae6 369
2a3ced3c
PP
370 if (stream_class->frozen) {
371 /*
372 * We only check that the event class to be added has a
373 * single class which matches the stream class's
374 * expected clock class if the stream class is frozen.
375 * If it's not, then this event class is added "as is"
376 * and the validation will be performed when calling
377 * either bt_trace_add_stream_class() or
378 * bt_event_create(). This is because the stream class's
379 * field types (packet context, event header, event
380 * context) could change before the next call to one of
381 * those two functions.
382 */
383 expected_clock_class = bt_get(stream_class->clock_class);
384
385 /*
386 * At this point, `expected_clock_class` can be NULL,
387 * and bt_event_class_validate_single_clock_class()
388 * below can set it.
389 */
3dca2276 390 ret = bt_event_class_common_validate_single_clock_class(
2a3ced3c
PP
391 event_class, &expected_clock_class);
392 if (ret) {
393 BT_LOGW("Event class contains a field type which is not "
394 "recursively mapped to its stream class's "
395 "expected clock class: "
396 "stream-class-addr=%p, "
397 "stream-class-id=%" PRId64 ", "
398 "stream-class-name=\"%s\", "
399 "expected-clock-class-addr=%p, "
400 "expected-clock-class-name=\"%s\"",
401 stream_class,
3dca2276
PP
402 bt_stream_class_common_get_id(stream_class),
403 bt_stream_class_common_get_name(stream_class),
2a3ced3c
PP
404 expected_clock_class,
405 expected_clock_class ?
406 bt_clock_class_get_name(expected_clock_class) :
407 NULL);
408 goto end;
409 }
410 }
411
0b9ce69f
JG
412 event_id = g_new(int64_t, 1);
413 if (!event_id) {
d2f71f12 414 BT_LOGE_STR("Failed to allocate one int64_t.");
0b9ce69f
JG
415 ret = -1;
416 goto end;
417 }
418
11b0cdc8
JG
419 /* Check for duplicate event classes */
420 struct search_query query = { .value = event_class, .found = 0 };
0d23acbe
PP
421 g_ptr_array_foreach(stream_class->event_classes, event_class_exists,
422 &query);
11b0cdc8 423 if (query.found) {
d2f71f12 424 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
11b0cdc8
JG
425 ret = -1;
426 goto end;
427 }
428
3dca2276 429 old_stream_class = bt_event_class_common_borrow_stream_class(event_class);
e6a8e8e4
JG
430 if (old_stream_class) {
431 /* Event class is already associated to a stream class. */
d2f71f12
PP
432 BT_LOGW("Event class is already part of another stream class: "
433 "event-class-stream-class-addr=%p, "
434 "event-class-stream-class-name=\"%s\", "
435 "event-class-stream-class-id=%" PRId64,
436 old_stream_class,
3dca2276
PP
437 bt_stream_class_common_get_name(old_stream_class),
438 bt_stream_class_common_get_id(old_stream_class));
e6a8e8e4
JG
439 ret = -1;
440 goto end;
441 }
442
e6a8e8e4 443 if (trace) {
09840de5
PP
444 /*
445 * If the stream class is associated with a trace, then
446 * both those objects are frozen. Also, this event class
447 * is about to be frozen.
448 *
449 * Therefore the event class must be validated here.
450 * The trace and stream class should be valid at this
451 * point.
452 */
f6ccaed9
PP
453 BT_ASSERT(trace->valid);
454 BT_ASSERT(stream_class->valid);
09840de5 455 packet_header_type =
094ff7c0 456 bt_trace_common_borrow_packet_header_field_type(trace);
09840de5 457 packet_context_type =
094ff7c0 458 bt_stream_class_common_borrow_packet_context_field_type(
09840de5
PP
459 stream_class);
460 event_header_type =
094ff7c0 461 bt_stream_class_common_borrow_event_header_field_type(
3dca2276 462 stream_class);
09840de5 463 stream_event_ctx_type =
094ff7c0 464 bt_stream_class_common_borrow_event_context_field_type(
09840de5
PP
465 stream_class);
466 event_context_type =
094ff7c0
PP
467 bt_event_class_common_borrow_context_field_type(
468 event_class);
09840de5 469 event_payload_type =
094ff7c0
PP
470 bt_event_class_common_borrow_payload_field_type(
471 event_class);
50842bdc 472 ret = bt_validate_class_types(
09840de5
PP
473 trace->environment, packet_header_type,
474 packet_context_type, event_header_type,
475 stream_event_ctx_type, event_context_type,
476 event_payload_type, trace->valid,
477 stream_class->valid, event_class->valid,
3dca2276
PP
478 &validation_output, validation_flags,
479 copy_field_type_func);
09840de5 480
26079216 481 if (ret) {
09840de5
PP
482 /*
483 * This means something went wrong during the
484 * validation process, not that the objects are
485 * invalid.
486 */
d2f71f12 487 BT_LOGE("Failed to validate event class: ret=%d", ret);
09840de5
PP
488 goto end;
489 }
490
491 if ((validation_output.valid_flags & validation_flags) !=
492 validation_flags) {
493 /* Invalid event class */
66871d36 494 BT_LOGW("Invalid trace, stream class, or event class: "
d2f71f12
PP
495 "valid-flags=0x%x",
496 validation_output.valid_flags);
09840de5 497 ret = -1;
26079216
JG
498 goto end;
499 }
500 }
501
09840de5 502 /* Only set an event ID if none was explicitly set before */
3dca2276 503 *event_id = bt_event_class_common_get_id(event_class);
24626e8b 504 if (*event_id < 0) {
d2f71f12
PP
505 BT_LOGV("Event class has no ID: automatically setting it: "
506 "id=%" PRId64, stream_class->next_event_id);
507
3dca2276 508 if (bt_event_class_common_set_id(event_class,
d2f71f12
PP
509 stream_class->next_event_id)) {
510 BT_LOGE("Cannot set event class's ID: id=%" PRId64,
511 stream_class->next_event_id);
2f100782
JG
512 ret = -1;
513 goto end;
514 }
d2f71f12 515 stream_class->next_event_id++;
0b9ce69f 516 *event_id = stream_class->next_event_id;
2f100782
JG
517 }
518
e6a8e8e4 519 bt_object_set_parent(event_class, stream_class);
09840de5
PP
520
521 if (trace) {
522 /*
523 * At this point we know that the function will be
524 * successful. Therefore we can replace the event
525 * class's field types with what's in the validation
526 * output structure and mark this event class as valid.
527 */
50842bdc 528 bt_validation_replace_types(NULL, NULL, event_class,
09840de5
PP
529 &validation_output, validation_flags);
530 event_class->valid = 1;
531
532 /*
533 * Put what was not moved in
50842bdc 534 * bt_validation_replace_types().
09840de5 535 */
50842bdc 536 bt_validation_output_put_types(&validation_output);
09840de5
PP
537 }
538
539 /* Add to the event classes of the stream class */
11b0cdc8 540 g_ptr_array_add(stream_class->event_classes, event_class);
0b9ce69f
JG
541 g_hash_table_insert(stream_class->event_classes_ht, event_id,
542 event_class);
543 event_id = NULL;
09840de5
PP
544
545 /* Freeze the event class */
3dca2276 546 bt_event_class_common_freeze(event_class);
5ca83563 547
2a3ced3c
PP
548 /*
549 * It is safe to set the stream class's unique clock class
550 * now if the stream class is frozen.
551 */
552 if (stream_class->frozen && expected_clock_class) {
f6ccaed9 553 BT_ASSERT(!stream_class->clock_class ||
2a3ced3c
PP
554 stream_class->clock_class == expected_clock_class);
555 BT_MOVE(stream_class->clock_class, expected_clock_class);
556 }
557
d2f71f12
PP
558 BT_LOGD("Added event class to stream class: "
559 "stream-class-addr=%p, stream-class-name=\"%s\", "
560 "stream-class-id=%" PRId64 ", event-class-addr=%p, "
561 "event-class-name=\"%s\", event-class-id=%" PRId64,
3dca2276
PP
562 stream_class, bt_stream_class_common_get_name(stream_class),
563 bt_stream_class_common_get_id(stream_class),
d2f71f12 564 event_class,
3dca2276
PP
565 bt_event_class_common_get_name(event_class),
566 bt_event_class_common_get_id(event_class));
d2f71f12 567
11b0cdc8 568end:
50842bdc 569 bt_validation_output_put_types(&validation_output);
2a3ced3c 570 bt_put(expected_clock_class);
0b9ce69f 571 g_free(event_id);
11b0cdc8
JG
572 return ret;
573}
574
3dca2276
PP
575int bt_stream_class_add_event_class(
576 struct bt_stream_class *stream_class,
577 struct bt_event_class *event_class)
69dc4535 578{
3dca2276
PP
579 struct bt_trace *trace;
580 int ret = 0;
312c056a
PP
581 uint64_t i;
582 struct bt_clock_class *old_clock_class;
69dc4535
JG
583
584 if (!stream_class) {
3dca2276
PP
585 BT_LOGW("Invalid parameter: stream class is NULL: "
586 "stream-class-addr=%p", stream_class);
587 ret = -1;
588 goto end;
589 }
590
312c056a 591 old_clock_class = stream_class->common.clock_class;
3dca2276
PP
592 trace = BT_FROM_COMMON(bt_stream_class_common_borrow_trace(
593 BT_TO_COMMON(stream_class)));
594 if (trace && trace->is_static) {
595 BT_LOGW("Invalid parameter: stream class's trace is static: "
596 "trace-addr=%p, trace-name=\"%s\"",
597 trace, bt_trace_get_name(trace));
598 ret = -1;
599 goto end;
600 }
601
602 ret = bt_stream_class_common_add_event_class(
603 BT_TO_COMMON(stream_class), BT_TO_COMMON(event_class),
604 (bt_validation_flag_copy_field_type_func) bt_field_type_copy);
605 if (ret) {
69dc4535
JG
606 goto end;
607 }
608
3dca2276
PP
609 /* Notifiy listeners of the trace's schema modification. */
610 if (trace) {
611 struct bt_visitor_object obj = { .object = event_class,
612 .type = BT_VISITOR_OBJECT_TYPE_EVENT_CLASS };
613
614 (void) bt_trace_object_modification(&obj, trace);
615 }
616
312c056a
PP
617 if (!old_clock_class && stream_class->common.clock_class) {
618 /*
619 * Adding this event class updated the stream class's
620 * single clock class: make sure all the events which
621 * exist in event pools have an existing clock value for
622 * this clock class so that any created event object in
623 * the future (from a pool or not) has this clock value
624 * available.
625 */
626 for (i = 0; i < stream_class->common.event_classes->len; i++) {
627 struct bt_event_class *event_class =
628 stream_class->common.event_classes->pdata[i];
629
630 BT_ASSERT(event_class);
631 ret = bt_event_class_update_event_pool_clock_values(
632 event_class);
633 if (ret) {
634 goto end;
635 }
636 }
637 }
638
69dc4535
JG
639end:
640 return ret;
641}
642
3dca2276
PP
643int64_t bt_stream_class_get_event_class_count(
644 struct bt_stream_class *stream_class)
645{
646 return bt_stream_class_common_get_event_class_count(
647 BT_TO_COMMON(stream_class));
648}
649
094ff7c0 650struct bt_event_class *bt_stream_class_borrow_event_class_by_index(
50842bdc 651 struct bt_stream_class *stream_class, uint64_t index)
69dc4535 652{
094ff7c0 653 return BT_FROM_COMMON(bt_stream_class_common_borrow_event_class_by_index(
3dca2276 654 BT_TO_COMMON(stream_class), index));
69dc4535
JG
655}
656
094ff7c0 657struct bt_event_class *bt_stream_class_borrow_event_class_by_id(
50842bdc 658 struct bt_stream_class *stream_class, uint64_t id)
0863f950 659{
094ff7c0 660 return BT_FROM_COMMON(bt_stream_class_common_borrow_event_class_by_id(
3dca2276 661 BT_TO_COMMON(stream_class), id));
0863f950
PP
662}
663
094ff7c0 664struct bt_field_type *bt_stream_class_borrow_packet_context_field_type(
50842bdc 665 struct bt_stream_class *stream_class)
12c8a1a3 666{
094ff7c0 667 return BT_FROM_COMMON(bt_stream_class_common_borrow_packet_context_field_type(
3dca2276 668 BT_TO_COMMON(stream_class)));
12c8a1a3
JG
669}
670
3dca2276 671int bt_stream_class_set_packet_context_field_type(
50842bdc
PP
672 struct bt_stream_class *stream_class,
673 struct bt_field_type *packet_context_type)
12c8a1a3 674{
3dca2276
PP
675 return bt_stream_class_common_set_packet_context_field_type(
676 BT_TO_COMMON(stream_class), (void *) packet_context_type);
12c8a1a3
JG
677}
678
094ff7c0 679struct bt_field_type *bt_stream_class_borrow_event_header_field_type(
50842bdc 680 struct bt_stream_class *stream_class)
662e778c 681{
094ff7c0 682 return BT_FROM_COMMON(bt_stream_class_common_borrow_event_header_field_type(
3dca2276 683 BT_TO_COMMON(stream_class)));
662e778c
JG
684}
685
3dca2276 686int bt_stream_class_set_event_header_field_type(
50842bdc
PP
687 struct bt_stream_class *stream_class,
688 struct bt_field_type *event_header_type)
662e778c 689{
3dca2276
PP
690 return bt_stream_class_common_set_event_header_field_type(
691 BT_TO_COMMON(stream_class), (void *) event_header_type);
662e778c
JG
692}
693
094ff7c0 694struct bt_field_type *bt_stream_class_borrow_event_context_field_type(
50842bdc 695 struct bt_stream_class *stream_class)
af181248 696{
094ff7c0 697 return BT_FROM_COMMON(bt_stream_class_common_borrow_event_context_field_type(
3dca2276 698 BT_TO_COMMON(stream_class)));
af181248
JG
699}
700
3dca2276 701int bt_stream_class_set_event_context_field_type(
50842bdc
PP
702 struct bt_stream_class *stream_class,
703 struct bt_field_type *event_context_type)
af181248 704{
3dca2276
PP
705 return bt_stream_class_common_set_event_context_field_type(
706 BT_TO_COMMON(stream_class), (void *) event_context_type);
11b0cdc8
JG
707}
708
8bf65fbd 709static
544d0515 710int64_t get_event_class_count(void *element)
8bf65fbd 711{
50842bdc
PP
712 return bt_stream_class_get_event_class_count(
713 (struct bt_stream_class *) element);
8bf65fbd
JG
714}
715
716static
717void *get_event_class(void *element, int i)
718{
50842bdc
PP
719 return bt_stream_class_get_event_class_by_index(
720 (struct bt_stream_class *) element, i);
8bf65fbd
JG
721}
722
723static
50842bdc 724int visit_event_class(void *object, bt_visitor visitor,void *data)
8bf65fbd 725{
3dca2276
PP
726 struct bt_visitor_object obj = {
727 .object = object,
728 .type = BT_VISITOR_OBJECT_TYPE_EVENT_CLASS
729 };
8bf65fbd 730
d9a13d86 731 return visitor(&obj, data);
8bf65fbd
JG
732}
733
3dca2276
PP
734BT_HIDDEN
735int bt_stream_class_common_visit(struct bt_stream_class_common *stream_class,
50842bdc 736 bt_visitor visitor, void *data)
8bf65fbd
JG
737{
738 int ret;
3dca2276
PP
739 struct bt_visitor_object obj = {
740 .object = stream_class,
741 .type = BT_VISITOR_OBJECT_TYPE_STREAM_CLASS
742 };
8bf65fbd
JG
743
744 if (!stream_class || !visitor) {
d2f71f12
PP
745 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
746 "stream-class-addr=%p, visitor=%p",
747 stream_class, visitor);
8bf65fbd
JG
748 ret = -1;
749 goto end;
750 }
751
d9a13d86 752 ret = visitor_helper(&obj, get_event_class_count,
8bf65fbd
JG
753 get_event_class,
754 visit_event_class, visitor, data);
d2f71f12 755 BT_LOGV("visitor_helper() returned: ret=%d", ret);
3dca2276 756
8bf65fbd
JG
757end:
758 return ret;
759}
760
3dca2276
PP
761int bt_stream_class_visit(struct bt_stream_class *stream_class,
762 bt_visitor visitor, void *data)
763{
764 return bt_stream_class_common_visit(BT_FROM_COMMON(stream_class),
765 visitor, data);
766}
767
11b0cdc8 768BT_HIDDEN
3dca2276 769void bt_stream_class_common_freeze(struct bt_stream_class_common *stream_class)
11b0cdc8 770{
d2f71f12 771 if (!stream_class || stream_class->frozen) {
11b0cdc8
JG
772 return;
773 }
774
d2f71f12 775 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64,
3dca2276
PP
776 stream_class, bt_stream_class_common_get_name(stream_class),
777 bt_stream_class_common_get_id(stream_class));
11b0cdc8 778 stream_class->frozen = 1;
3dca2276
PP
779 bt_field_type_common_freeze(stream_class->event_header_field_type);
780 bt_field_type_common_freeze(stream_class->packet_context_field_type);
781 bt_field_type_common_freeze(stream_class->event_context_field_type);
782 bt_clock_class_freeze(stream_class->clock_class);
11b0cdc8
JG
783}
784
3dca2276 785void bt_stream_class_freeze(struct bt_stream_class *stream_class)
e011d2c1 786{
3dca2276 787 bt_stream_class_common_freeze(BT_TO_COMMON(stream_class));
11b0cdc8 788}
2a3ced3c
PP
789
790BT_HIDDEN
3dca2276
PP
791int bt_stream_class_common_validate_single_clock_class(
792 struct bt_stream_class_common *stream_class,
2a3ced3c
PP
793 struct bt_clock_class **expected_clock_class)
794{
795 int ret;
796 uint64_t i;
797
f6ccaed9
PP
798 BT_ASSERT(stream_class);
799 BT_ASSERT(expected_clock_class);
3dca2276
PP
800 ret = bt_field_type_common_validate_single_clock_class(
801 stream_class->packet_context_field_type,
2a3ced3c
PP
802 expected_clock_class);
803 if (ret) {
804 BT_LOGW("Stream class's packet context field type "
805 "is not recursively mapped to the "
806 "expected clock class: "
807 "stream-class-addr=%p, "
808 "stream-class-name=\"%s\", "
809 "stream-class-id=%" PRId64 ", "
810 "ft-addr=%p",
811 stream_class,
3dca2276 812 bt_stream_class_common_get_name(stream_class),
2a3ced3c 813 stream_class->id,
3dca2276 814 stream_class->packet_context_field_type);
2a3ced3c
PP
815 goto end;
816 }
817
3dca2276
PP
818 ret = bt_field_type_common_validate_single_clock_class(
819 stream_class->event_header_field_type,
2a3ced3c
PP
820 expected_clock_class);
821 if (ret) {
822 BT_LOGW("Stream class's event header field type "
823 "is not recursively mapped to the "
824 "expected clock class: "
825 "stream-class-addr=%p, "
826 "stream-class-name=\"%s\", "
827 "stream-class-id=%" PRId64 ", "
828 "ft-addr=%p",
829 stream_class,
3dca2276 830 bt_stream_class_common_get_name(stream_class),
2a3ced3c 831 stream_class->id,
3dca2276 832 stream_class->event_header_field_type);
2a3ced3c
PP
833 goto end;
834 }
835
3dca2276
PP
836 ret = bt_field_type_common_validate_single_clock_class(
837 stream_class->event_context_field_type,
2a3ced3c
PP
838 expected_clock_class);
839 if (ret) {
840 BT_LOGW("Stream class's event context field type "
841 "is not recursively mapped to the "
842 "expected clock class: "
843 "stream-class-addr=%p, "
844 "stream-class-name=\"%s\", "
845 "stream-class-id=%" PRId64 ", "
846 "ft-addr=%p",
847 stream_class,
3dca2276 848 bt_stream_class_common_get_name(stream_class),
2a3ced3c 849 stream_class->id,
3dca2276 850 stream_class->event_context_field_type);
2a3ced3c
PP
851 goto end;
852 }
853
854 for (i = 0; i < stream_class->event_classes->len; i++) {
3dca2276 855 struct bt_event_class_common *event_class =
2a3ced3c
PP
856 g_ptr_array_index(stream_class->event_classes, i);
857
f6ccaed9 858 BT_ASSERT(event_class);
3dca2276
PP
859 ret = bt_event_class_common_validate_single_clock_class(
860 event_class, expected_clock_class);
2a3ced3c
PP
861 if (ret) {
862 BT_LOGW("Stream class's event class contains a "
863 "field type which is not recursively mapped to "
864 "the expected clock class: "
865 "stream-class-addr=%p, "
866 "stream-class-name=\"%s\", "
867 "stream-class-id=%" PRId64,
868 stream_class,
3dca2276 869 bt_stream_class_common_get_name(stream_class),
2a3ced3c
PP
870 stream_class->id);
871 goto end;
872 }
873 }
874
875end:
876 return ret;
877}
This page took 0.089673 seconds and 4 git commands to generate.