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