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