lib: merge common CTF IR part with the remaining implementation
[babeltrace.git] / lib / ctf-ir / stream-class.c
1 /*
2 * stream-class.c
3 *
4 * Babeltrace CTF IR - Stream Class
5 *
6 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 *
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
29 #define BT_LOG_TAG "STREAM-CLASS"
30 #include <babeltrace/lib-logging-internal.h>
31
32 #include <babeltrace/assert-pre-internal.h>
33 #include <babeltrace/ctf-ir/clock-class-internal.h>
34 #include <babeltrace/ctf-ir/event-class-internal.h>
35 #include <babeltrace/ctf-ir/field-types-internal.h>
36 #include <babeltrace/ctf-ir/fields-internal.h>
37 #include <babeltrace/ctf-ir/stream-class-internal.h>
38 #include <babeltrace/ctf-ir/validation-internal.h>
39 #include <babeltrace/ctf-ir/visitor-internal.h>
40 #include <babeltrace/ctf-ir/utils.h>
41 #include <babeltrace/ctf-ir/utils-internal.h>
42 #include <babeltrace/ctf-ir/field-wrapper-internal.h>
43 #include <babeltrace/ref.h>
44 #include <babeltrace/compiler-internal.h>
45 #include <babeltrace/align-internal.h>
46 #include <babeltrace/endian-internal.h>
47 #include <babeltrace/assert-internal.h>
48 #include <inttypes.h>
49 #include <stdint.h>
50 #include <stdbool.h>
51
52 static inline
53 int bt_stream_class_initialize(struct bt_stream_class *stream_class,
54 const char *name, bt_object_release_func release_func)
55 {
56 BT_LOGD("Initializing stream class object: name=\"%s\"", name);
57
58 bt_object_init_shared_with_parent(&stream_class->base, release_func);
59 stream_class->name = g_string_new(name);
60 stream_class->event_classes = g_ptr_array_new_with_free_func(
61 (GDestroyNotify) bt_object_try_spec_release);
62 if (!stream_class->event_classes) {
63 BT_LOGE_STR("Failed to allocate a GPtrArray.");
64 goto error;
65 }
66
67 stream_class->event_classes_ht = g_hash_table_new_full(g_int64_hash,
68 g_int64_equal, g_free, NULL);
69 if (!stream_class->event_classes_ht) {
70 BT_LOGE_STR("Failed to allocate a GHashTable.");
71 goto error;
72 }
73
74 BT_LOGD("Initialized stream class object: addr=%p, name=\"%s\"",
75 stream_class, name);
76 return 0;
77
78 error:
79 return -1;
80 }
81
82 static
83 void bt_stream_class_destroy(struct bt_object *obj)
84 {
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));
90 bt_put(stream_class->clock_class);
91
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);
98 }
99
100 if (stream_class->name) {
101 g_string_free(stream_class->name, TRUE);
102 }
103
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);
110 bt_object_pool_finalize(&stream_class->event_header_field_pool);
111 bt_object_pool_finalize(&stream_class->packet_context_field_pool);
112 g_free(stream_class);
113 }
114
115 static
116 void 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
122 struct bt_stream_class *bt_stream_class_create(const char *name)
123 {
124 struct bt_stream_class *stream_class = NULL;
125 int ret;
126
127 BT_LOGD("Creating stream class object: name=\"%s\"", name);
128 stream_class = g_new0(struct bt_stream_class, 1);
129 if (!stream_class) {
130 BT_LOGE_STR("Failed to allocate one stream class.");
131 goto error;
132 }
133
134 ret = bt_stream_class_initialize(stream_class, name,
135 bt_stream_class_destroy);
136 if (ret) {
137 /* bt_stream_class_initialize() logs errors */
138 goto error;
139 }
140
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
161 BT_LOGD("Created stream class object: addr=%p, name=\"%s\"",
162 stream_class, name);
163 return stream_class;
164
165 error:
166 bt_put(stream_class);
167 return NULL;
168 }
169
170 struct 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");
176 BT_ASSERT_PRE(stream_class->frozen,
177 "Stream class is not part of a trace: %!+S", stream_class);
178 BT_ASSERT_PRE(stream_class->event_header_field_type,
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,
183 (void *) stream_class->event_header_field_type);
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
193 error:
194 if (field_wrapper) {
195 bt_field_wrapper_destroy(field_wrapper);
196 field_wrapper = NULL;
197 }
198
199 end:
200 return (void *) field_wrapper;
201 }
202
203 struct 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");
209 BT_ASSERT_PRE(stream_class->frozen,
210 "Stream class is not part of a trace: %!+S", stream_class);
211 BT_ASSERT_PRE(stream_class->packet_context_field_type,
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,
216 (void *) stream_class->packet_context_field_type);
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
226 error:
227 if (field_wrapper) {
228 bt_field_wrapper_destroy(field_wrapper);
229 field_wrapper = NULL;
230 }
231
232 end:
233 return (void *) field_wrapper;
234 }
235
236 struct bt_trace *bt_stream_class_borrow_trace(struct bt_stream_class *stream_class)
237 {
238 BT_ASSERT(stream_class);
239 return (void *) bt_object_borrow_parent(&stream_class->base);
240 }
241
242 const char *bt_stream_class_get_name(struct bt_stream_class *stream_class)
243 {
244 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
245 return stream_class->name->len > 0 ? stream_class->name->str : NULL;
246 }
247
248 int bt_stream_class_set_name(struct bt_stream_class *stream_class,
249 const char *name)
250 {
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));
285 end:
286 return ret;
287 }
288
289 int64_t bt_stream_class_get_id(struct bt_stream_class *stream_class)
290 {
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
305 end:
306 return ret;
307 }
308
309 int bt_stream_class_set_id(struct bt_stream_class *stream_class,
310 uint64_t id_param)
311 {
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 }
351 end:
352 return ret;
353 }
354
355 static
356 void event_class_exists(gpointer element, gpointer query)
357 {
358 struct bt_event_class *event_class_a = element;
359 struct search_query *search_query = query;
360 struct bt_event_class *event_class_b = search_query->value;
361 int64_t id_a, id_b;
362
363 if (search_query->value == element) {
364 search_query->found = 1;
365 goto end;
366 }
367
368 /*
369 * Two event classes cannot share the same ID in a given
370 * stream class.
371 */
372 id_a = bt_event_class_get_id(event_class_a);
373 id_b = bt_event_class_get_id(event_class_b);
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) {
381 BT_LOGW("Event class with this ID already exists in the stream class: "
382 "id=%" PRId64 ", name=\"%s\"",
383 id_a, bt_event_class_get_name(event_class_a));
384 search_query->found = 1;
385 goto end;
386 }
387
388 end:
389 return;
390 }
391
392 int bt_stream_class_add_event_class(struct bt_stream_class *stream_class,
393 struct bt_event_class *event_class)
394 {
395 int ret = 0;
396 int64_t *event_id = NULL;
397 struct bt_trace *trace = NULL;
398 struct bt_stream_class *old_stream_class = NULL;
399 struct bt_validation_output validation_output = { 0 };
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;
406 const enum bt_validation_flag validation_flags =
407 BT_VALIDATION_FLAG_EVENT;
408 struct bt_clock_class *expected_clock_class = NULL;
409
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 }
425
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
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,
438 stream_class, bt_stream_class_get_name(stream_class),
439 bt_stream_class_get_id(stream_class),
440 event_class,
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);
444
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 */
465 ret = bt_event_class_validate_single_clock_class(
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,
477 bt_stream_class_get_id(stream_class),
478 bt_stream_class_get_name(stream_class),
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
487 event_id = g_new(int64_t, 1);
488 if (!event_id) {
489 BT_LOGE_STR("Failed to allocate one int64_t.");
490 ret = -1;
491 goto end;
492 }
493
494 /* Check for duplicate event classes */
495 struct search_query query = { .value = event_class, .found = 0 };
496 g_ptr_array_foreach(stream_class->event_classes, event_class_exists,
497 &query);
498 if (query.found) {
499 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
500 ret = -1;
501 goto end;
502 }
503
504 old_stream_class = bt_event_class_borrow_stream_class(event_class);
505 if (old_stream_class) {
506 /* Event class is already associated to a stream class. */
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,
512 bt_stream_class_get_name(old_stream_class),
513 bt_stream_class_get_id(old_stream_class));
514 ret = -1;
515 goto end;
516 }
517
518 if (trace) {
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 */
528 BT_ASSERT(trace->valid);
529 BT_ASSERT(stream_class->valid);
530 packet_header_type =
531 bt_trace_borrow_packet_header_field_type(trace);
532 packet_context_type =
533 bt_stream_class_borrow_packet_context_field_type(
534 stream_class);
535 event_header_type =
536 bt_stream_class_borrow_event_header_field_type(
537 stream_class);
538 stream_event_ctx_type =
539 bt_stream_class_borrow_event_context_field_type(
540 stream_class);
541 event_context_type =
542 bt_event_class_borrow_context_field_type(
543 event_class);
544 event_payload_type =
545 bt_event_class_borrow_payload_field_type(
546 event_class);
547 ret = bt_validate_class_types(
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,
553 &validation_output, validation_flags,
554 bt_field_type_copy);
555
556 if (ret) {
557 /*
558 * This means something went wrong during the
559 * validation process, not that the objects are
560 * invalid.
561 */
562 BT_LOGE("Failed to validate event class: ret=%d", ret);
563 goto end;
564 }
565
566 if ((validation_output.valid_flags & validation_flags) !=
567 validation_flags) {
568 /* Invalid event class */
569 BT_LOGW("Invalid trace, stream class, or event class: "
570 "valid-flags=0x%x",
571 validation_output.valid_flags);
572 ret = -1;
573 goto end;
574 }
575 }
576
577 /* Only set an event ID if none was explicitly set before */
578 *event_id = bt_event_class_get_id(event_class);
579 if (*event_id < 0) {
580 BT_LOGV("Event class has no ID: automatically setting it: "
581 "id=%" PRId64, stream_class->next_event_id);
582
583 if (bt_event_class_set_id(event_class,
584 stream_class->next_event_id)) {
585 BT_LOGE("Cannot set event class's ID: id=%" PRId64,
586 stream_class->next_event_id);
587 ret = -1;
588 goto end;
589 }
590 stream_class->next_event_id++;
591 *event_id = stream_class->next_event_id;
592 }
593
594 bt_object_set_parent(&event_class->base, &stream_class->base);
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 */
603 bt_validation_replace_types(NULL, NULL, event_class,
604 &validation_output, validation_flags);
605 event_class->valid = 1;
606
607 /*
608 * Put what was not moved in
609 * bt_validation_replace_types().
610 */
611 bt_validation_output_put_types(&validation_output);
612 }
613
614 /* Add to the event classes of the stream class */
615 g_ptr_array_add(stream_class->event_classes, event_class);
616 g_hash_table_insert(stream_class->event_classes_ht, event_id,
617 event_class);
618 event_id = NULL;
619
620 /* Freeze the event class */
621 bt_event_class_freeze(event_class);
622
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) {
628 BT_ASSERT(!stream_class->clock_class ||
629 stream_class->clock_class == expected_clock_class);
630 BT_MOVE(stream_class->clock_class, expected_clock_class);
631 }
632
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
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,
645 stream_class, bt_stream_class_get_name(stream_class),
646 bt_stream_class_get_id(stream_class),
647 event_class,
648 bt_event_class_get_name(event_class),
649 bt_event_class_get_id(event_class));
650
651 end:
652 bt_validation_output_put_types(&validation_output);
653 bt_put(expected_clock_class);
654 g_free(event_id);
655 return ret;
656 }
657
658 int64_t bt_stream_class_get_event_class_count(
659 struct bt_stream_class *stream_class)
660 {
661 int64_t ret;
662
663 if (!stream_class) {
664 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
665 ret = (int64_t) -1;
666 goto end;
667 }
668
669 ret = (int64_t) stream_class->event_classes->len;
670 end:
671 return ret;
672 }
673
674 struct bt_event_class *bt_stream_class_borrow_event_class_by_index(
675 struct bt_stream_class *stream_class, uint64_t index)
676 {
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);
683 }
684
685 struct bt_event_class *bt_stream_class_borrow_event_class_by_id(
686 struct bt_stream_class *stream_class, uint64_t id)
687 {
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);
695 }
696
697 struct bt_field_type *bt_stream_class_borrow_packet_context_field_type(
698 struct bt_stream_class *stream_class)
699 {
700 BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
701 return stream_class->packet_context_field_type;
702 }
703
704 int bt_stream_class_set_packet_context_field_type(
705 struct bt_stream_class *stream_class,
706 struct bt_field_type *packet_context_type)
707 {
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
751 end:
752 return ret;
753 }
754
755 struct bt_field_type *bt_stream_class_borrow_event_header_field_type(
756 struct bt_stream_class *stream_class)
757 {
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
773 end:
774 return ret;
775 }
776
777 int bt_stream_class_set_event_header_field_type(
778 struct bt_stream_class *stream_class,
779 struct bt_field_type *event_header_type)
780 {
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);
823 end:
824 return ret;
825 }
826
827 struct bt_field_type *bt_stream_class_borrow_event_context_field_type(
828 struct bt_stream_class *stream_class)
829 {
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
840 end:
841 return ret;
842 }
843
844 int bt_stream_class_set_event_context_field_type(
845 struct bt_stream_class *stream_class,
846 struct bt_field_type *event_context_type)
847 {
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);
889 end:
890 return ret;
891 }
892
893 static
894 int64_t get_event_class_count(void *element)
895 {
896 return bt_stream_class_get_event_class_count(
897 (struct bt_stream_class *) element);
898 }
899
900 static
901 void *get_event_class(void *element, int i)
902 {
903 return bt_stream_class_get_event_class_by_index(
904 (struct bt_stream_class *) element, i);
905 }
906
907 static
908 int visit_event_class(void *object, bt_visitor visitor,void *data)
909 {
910 struct bt_visitor_object obj = {
911 .object = object,
912 .type = BT_VISITOR_OBJECT_TYPE_EVENT_CLASS
913 };
914
915 return visitor(&obj, data);
916 }
917
918 BT_HIDDEN
919 int bt_stream_class_visit(struct bt_stream_class *stream_class,
920 bt_visitor visitor, void *data)
921 {
922 int ret;
923 struct bt_visitor_object obj = {
924 .object = stream_class,
925 .type = BT_VISITOR_OBJECT_TYPE_STREAM_CLASS
926 };
927
928 if (!stream_class || !visitor) {
929 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
930 "stream-class-addr=%p, visitor=%p",
931 stream_class, visitor);
932 ret = -1;
933 goto end;
934 }
935
936 ret = visitor_helper(&obj, get_event_class_count,
937 get_event_class,
938 visit_event_class, visitor, data);
939 BT_LOGV("visitor_helper() returned: ret=%d", ret);
940
941 end:
942 return ret;
943 }
944
945 BT_HIDDEN
946 void bt_stream_class_freeze(struct bt_stream_class *stream_class)
947 {
948 if (!stream_class || stream_class->frozen) {
949 return;
950 }
951
952 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64,
953 stream_class, bt_stream_class_get_name(stream_class),
954 bt_stream_class_get_id(stream_class));
955 stream_class->frozen = 1;
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);
959 bt_clock_class_freeze(stream_class->clock_class);
960 }
961
962 BT_HIDDEN
963 int bt_stream_class_validate_single_clock_class(
964 struct bt_stream_class *stream_class,
965 struct bt_clock_class **expected_clock_class)
966 {
967 int ret;
968 uint64_t i;
969
970 BT_ASSERT(stream_class);
971 BT_ASSERT(expected_clock_class);
972 ret = bt_field_type_validate_single_clock_class(
973 stream_class->packet_context_field_type,
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,
984 bt_stream_class_get_name(stream_class),
985 stream_class->id,
986 stream_class->packet_context_field_type);
987 goto end;
988 }
989
990 ret = bt_field_type_validate_single_clock_class(
991 stream_class->event_header_field_type,
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,
1002 bt_stream_class_get_name(stream_class),
1003 stream_class->id,
1004 stream_class->event_header_field_type);
1005 goto end;
1006 }
1007
1008 ret = bt_field_type_validate_single_clock_class(
1009 stream_class->event_context_field_type,
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,
1020 bt_stream_class_get_name(stream_class),
1021 stream_class->id,
1022 stream_class->event_context_field_type);
1023 goto end;
1024 }
1025
1026 for (i = 0; i < stream_class->event_classes->len; i++) {
1027 struct bt_event_class *event_class =
1028 g_ptr_array_index(stream_class->event_classes, i);
1029
1030 BT_ASSERT(event_class);
1031 ret = bt_event_class_validate_single_clock_class(
1032 event_class, expected_clock_class);
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,
1041 bt_stream_class_get_name(stream_class),
1042 stream_class->id);
1043 goto end;
1044 }
1045 }
1046
1047 end:
1048 return ret;
1049 }
This page took 0.06198 seconds and 4 git commands to generate.