Always evaluate BT_ASSERT(); add BT_ASSERT_DBG() for debug mode only
[babeltrace.git] / src / ctf-writer / stream-class.c
1 /*
2 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #define BT_LOG_TAG "CTF-WRITER/STREAM-CLASS"
25 #include "logging.h"
26
27 #include <inttypes.h>
28 #include <stdbool.h>
29 #include <stdint.h>
30
31 #include <babeltrace2-ctf-writer/event.h>
32 #include <babeltrace2-ctf-writer/object.h>
33 #include <babeltrace2-ctf-writer/trace.h>
34 #include <babeltrace2-ctf-writer/utils.h>
35
36 #include "common/align.h"
37 #include "common/assert.h"
38 #include "compat/compiler.h"
39 #include "compat/endian.h"
40
41 #include "assert-pre.h"
42 #include "clock-class.h"
43 #include "event-class.h"
44 #include "event.h"
45 #include "fields.h"
46 #include "field-types.h"
47 #include "field-wrapper.h"
48 #include "stream-class.h"
49 #include "utils.h"
50 #include "validation.h"
51 #include "visitor.h"
52 #include "writer.h"
53
54 BT_HIDDEN
55 int bt_ctf_stream_class_common_initialize(struct bt_ctf_stream_class_common *stream_class,
56 const char *name, bt_ctf_object_release_func release_func)
57 {
58 BT_LOGD("Initializing common stream class object: name=\"%s\"", name);
59
60 bt_ctf_object_init_shared_with_parent(&stream_class->base, release_func);
61 stream_class->name = g_string_new(name);
62 stream_class->event_classes = g_ptr_array_new_with_free_func(
63 (GDestroyNotify) bt_ctf_object_try_spec_release);
64 if (!stream_class->event_classes) {
65 BT_LOGE_STR("Failed to allocate a GPtrArray.");
66 goto error;
67 }
68
69 stream_class->event_classes_ht = g_hash_table_new_full(g_int64_hash,
70 g_int64_equal, g_free, NULL);
71 if (!stream_class->event_classes_ht) {
72 BT_LOGE_STR("Failed to allocate a GHashTable.");
73 goto error;
74 }
75
76 BT_LOGD("Initialized common stream class object: addr=%p, name=\"%s\"",
77 stream_class, name);
78 return 0;
79
80 error:
81 return -1;
82 }
83
84 BT_HIDDEN
85 void bt_ctf_stream_class_common_finalize(struct bt_ctf_stream_class_common *stream_class)
86 {
87 BT_LOGD("Finalizing common stream class: addr=%p, name=\"%s\", id=%" PRId64,
88 stream_class, bt_ctf_stream_class_common_get_name(stream_class),
89 bt_ctf_stream_class_common_get_id(stream_class));
90 bt_ctf_object_put_ref(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_ctf_object_put_ref(stream_class->event_header_field_type);
106 BT_LOGD_STR("Putting packet context field type.");
107 bt_ctf_object_put_ref(stream_class->packet_context_field_type);
108 BT_LOGD_STR("Putting event context field type.");
109 bt_ctf_object_put_ref(stream_class->event_context_field_type);
110 }
111
112 static
113 void event_class_exists(gpointer element, gpointer query)
114 {
115 struct bt_ctf_event_class_common *event_class_a = element;
116 struct bt_ctf_search_query *search_query = query;
117 struct bt_ctf_event_class_common *event_class_b = search_query->value;
118 int64_t id_a, id_b;
119
120 if (search_query->value == element) {
121 search_query->found = 1;
122 goto end;
123 }
124
125 /*
126 * Two event classes cannot share the same ID in a given
127 * stream class.
128 */
129 id_a = bt_ctf_event_class_common_get_id(event_class_a);
130 id_b = bt_ctf_event_class_common_get_id(event_class_b);
131
132 if (id_a < 0 || id_b < 0) {
133 /* at least one ID is not set: will be automatically set later */
134 goto end;
135 }
136
137 if (id_a == id_b) {
138 BT_LOGW("Event class with this ID already exists in the stream class: "
139 "id=%" PRId64 ", name=\"%s\"",
140 id_a, bt_ctf_event_class_common_get_name(event_class_a));
141 search_query->found = 1;
142 goto end;
143 }
144
145 end:
146 return;
147 }
148
149 BT_HIDDEN
150 int bt_ctf_stream_class_common_add_event_class(
151 struct bt_ctf_stream_class_common *stream_class,
152 struct bt_ctf_event_class_common *event_class,
153 bt_ctf_validation_flag_copy_field_type_func copy_field_type_func)
154 {
155 int ret = 0;
156 int64_t *event_id = NULL;
157 struct bt_ctf_trace_common *trace = NULL;
158 struct bt_ctf_stream_class_common *old_stream_class = NULL;
159 struct bt_ctf_validation_output validation_output = { 0 };
160 struct bt_ctf_field_type_common *packet_header_type = NULL;
161 struct bt_ctf_field_type_common *packet_context_type = NULL;
162 struct bt_ctf_field_type_common *event_header_type = NULL;
163 struct bt_ctf_field_type_common *stream_event_ctx_type = NULL;
164 struct bt_ctf_field_type_common *event_context_type = NULL;
165 struct bt_ctf_field_type_common *event_payload_type = NULL;
166 const enum bt_ctf_validation_flag validation_flags =
167 BT_CTF_VALIDATION_FLAG_EVENT;
168 struct bt_ctf_clock_class *expected_clock_class = NULL;
169
170 BT_ASSERT_DBG(copy_field_type_func);
171
172 if (!stream_class || !event_class) {
173 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
174 "stream-class-addr=%p, event-class-addr=%p",
175 stream_class, event_class);
176 ret = -1;
177 goto end;
178 }
179
180 BT_LOGD("Adding event class to stream class: "
181 "stream-class-addr=%p, stream-class-name=\"%s\", "
182 "stream-class-id=%" PRId64 ", event-class-addr=%p, "
183 "event-class-name=\"%s\", event-class-id=%" PRId64,
184 stream_class, bt_ctf_stream_class_common_get_name(stream_class),
185 bt_ctf_stream_class_common_get_id(stream_class),
186 event_class,
187 bt_ctf_event_class_common_get_name(event_class),
188 bt_ctf_event_class_common_get_id(event_class));
189 trace = bt_ctf_stream_class_common_borrow_trace(stream_class);
190
191 if (stream_class->frozen) {
192 /*
193 * We only check that the event class to be added has a
194 * single class which matches the stream class's
195 * expected clock class if the stream class is frozen.
196 * If it's not, then this event class is added "as is"
197 * and the validation will be performed when calling
198 * either bt_ctf_trace_add_stream_class() or
199 * bt_ctf_event_create(). This is because the stream class's
200 * field types (packet context, event header, event
201 * context) could change before the next call to one of
202 * those two functions.
203 */
204 expected_clock_class = bt_ctf_object_get_ref(stream_class->clock_class);
205
206 /*
207 * At this point, `expected_clock_class` can be NULL,
208 * and bt_ctf_event_class_validate_single_clock_class()
209 * below can set it.
210 */
211 ret = bt_ctf_event_class_common_validate_single_clock_class(
212 event_class, &expected_clock_class);
213 if (ret) {
214 BT_LOGW("Event class contains a field type which is not "
215 "recursively mapped to its stream class's "
216 "expected clock class: "
217 "stream-class-addr=%p, "
218 "stream-class-id=%" PRId64 ", "
219 "stream-class-name=\"%s\", "
220 "expected-clock-class-addr=%p, "
221 "expected-clock-class-name=\"%s\"",
222 stream_class,
223 bt_ctf_stream_class_common_get_id(stream_class),
224 bt_ctf_stream_class_common_get_name(stream_class),
225 expected_clock_class,
226 expected_clock_class ?
227 bt_ctf_clock_class_get_name(expected_clock_class) :
228 NULL);
229 goto end;
230 }
231 }
232
233 event_id = g_new(int64_t, 1);
234 if (!event_id) {
235 BT_LOGE_STR("Failed to allocate one int64_t.");
236 ret = -1;
237 goto end;
238 }
239
240 /* Check for duplicate event classes */
241 struct bt_ctf_search_query query = { .value = event_class, .found = 0 };
242 g_ptr_array_foreach(stream_class->event_classes, event_class_exists,
243 &query);
244 if (query.found) {
245 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
246 ret = -1;
247 goto end;
248 }
249
250 old_stream_class = bt_ctf_event_class_common_borrow_stream_class(event_class);
251 if (old_stream_class) {
252 /* Event class is already associated to a stream class. */
253 BT_LOGW("Event class is already part of another stream class: "
254 "event-class-stream-class-addr=%p, "
255 "event-class-stream-class-name=\"%s\", "
256 "event-class-stream-class-id=%" PRId64,
257 old_stream_class,
258 bt_ctf_stream_class_common_get_name(old_stream_class),
259 bt_ctf_stream_class_common_get_id(old_stream_class));
260 ret = -1;
261 goto end;
262 }
263
264 if (trace) {
265 /*
266 * If the stream class is associated with a trace, then
267 * both those objects are frozen. Also, this event class
268 * is about to be frozen.
269 *
270 * Therefore the event class must be validated here.
271 * The trace and stream class should be valid at this
272 * point.
273 */
274 BT_ASSERT_DBG(trace->valid);
275 BT_ASSERT_DBG(stream_class->valid);
276 packet_header_type =
277 bt_ctf_trace_common_borrow_packet_header_field_type(trace);
278 packet_context_type =
279 bt_ctf_stream_class_common_borrow_packet_context_field_type(
280 stream_class);
281 event_header_type =
282 bt_ctf_stream_class_common_borrow_event_header_field_type(
283 stream_class);
284 stream_event_ctx_type =
285 bt_ctf_stream_class_common_borrow_event_context_field_type(
286 stream_class);
287 event_context_type =
288 bt_ctf_event_class_common_borrow_context_field_type(
289 event_class);
290 event_payload_type =
291 bt_ctf_event_class_common_borrow_payload_field_type(
292 event_class);
293 ret = bt_ctf_validate_class_types(
294 trace->environment, packet_header_type,
295 packet_context_type, event_header_type,
296 stream_event_ctx_type, event_context_type,
297 event_payload_type, trace->valid,
298 stream_class->valid, event_class->valid,
299 &validation_output, validation_flags,
300 copy_field_type_func);
301
302 if (ret) {
303 /*
304 * This means something went wrong during the
305 * validation process, not that the objects are
306 * invalid.
307 */
308 BT_LOGE("Failed to validate event class: ret=%d", ret);
309 goto end;
310 }
311
312 if ((validation_output.valid_flags & validation_flags) !=
313 validation_flags) {
314 /* Invalid event class */
315 BT_LOGW("Invalid trace, stream class, or event class: "
316 "valid-flags=0x%x",
317 validation_output.valid_flags);
318 ret = -1;
319 goto end;
320 }
321 }
322
323 /* Only set an event ID if none was explicitly set before */
324 *event_id = bt_ctf_event_class_common_get_id(event_class);
325 if (*event_id < 0) {
326 BT_LOGT("Event class has no ID: automatically setting it: "
327 "id=%" PRId64, stream_class->next_event_id);
328
329 if (bt_ctf_event_class_common_set_id(event_class,
330 stream_class->next_event_id)) {
331 BT_LOGE("Cannot set event class's ID: id=%" PRId64,
332 stream_class->next_event_id);
333 ret = -1;
334 goto end;
335 }
336 stream_class->next_event_id++;
337 *event_id = stream_class->next_event_id;
338 }
339
340 bt_ctf_object_set_parent(&event_class->base, &stream_class->base);
341
342 if (trace) {
343 /*
344 * At this point we know that the function will be
345 * successful. Therefore we can replace the event
346 * class's field types with what's in the validation
347 * output structure and mark this event class as valid.
348 */
349 bt_ctf_validation_replace_types(NULL, NULL, event_class,
350 &validation_output, validation_flags);
351 event_class->valid = 1;
352
353 /*
354 * Put what was not moved in
355 * bt_ctf_validation_replace_types().
356 */
357 bt_ctf_validation_output_put_types(&validation_output);
358 }
359
360 /* Add to the event classes of the stream class */
361 g_ptr_array_add(stream_class->event_classes, event_class);
362 g_hash_table_insert(stream_class->event_classes_ht, event_id,
363 event_class);
364 event_id = NULL;
365
366 /* Freeze the event class */
367 bt_ctf_event_class_common_freeze(event_class);
368
369 /*
370 * It is safe to set the stream class's unique clock class
371 * now if the stream class is frozen.
372 */
373 if (stream_class->frozen && expected_clock_class) {
374 BT_ASSERT_DBG(!stream_class->clock_class ||
375 stream_class->clock_class == expected_clock_class);
376 BT_CTF_OBJECT_MOVE_REF(stream_class->clock_class, expected_clock_class);
377 }
378
379 BT_LOGD("Added event class to stream class: "
380 "stream-class-addr=%p, stream-class-name=\"%s\", "
381 "stream-class-id=%" PRId64 ", event-class-addr=%p, "
382 "event-class-name=\"%s\", event-class-id=%" PRId64,
383 stream_class, bt_ctf_stream_class_common_get_name(stream_class),
384 bt_ctf_stream_class_common_get_id(stream_class),
385 event_class,
386 bt_ctf_event_class_common_get_name(event_class),
387 bt_ctf_event_class_common_get_id(event_class));
388
389 end:
390 bt_ctf_validation_output_put_types(&validation_output);
391 bt_ctf_object_put_ref(expected_clock_class);
392 g_free(event_id);
393 return ret;
394 }
395
396 static
397 int64_t get_event_class_count(void *element)
398 {
399 return bt_ctf_stream_class_get_event_class_count(
400 (struct bt_ctf_stream_class *) element);
401 }
402
403 static
404 void *get_event_class(void *element, int i)
405 {
406 return bt_ctf_stream_class_get_event_class_by_index(
407 (struct bt_ctf_stream_class *) element, i);
408 }
409
410 static
411 int visit_event_class(void *object, bt_ctf_visitor visitor,void *data)
412 {
413 struct bt_ctf_visitor_object obj = {
414 .object = object,
415 .type = BT_CTF_VISITOR_OBJECT_TYPE_EVENT_CLASS
416 };
417
418 return visitor(&obj, data);
419 }
420
421 BT_HIDDEN
422 int bt_ctf_stream_class_common_visit(struct bt_ctf_stream_class_common *stream_class,
423 bt_ctf_visitor visitor, void *data)
424 {
425 int ret;
426 struct bt_ctf_visitor_object obj = {
427 .object = stream_class,
428 .type = BT_CTF_VISITOR_OBJECT_TYPE_STREAM_CLASS
429 };
430
431 if (!stream_class || !visitor) {
432 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
433 "stream-class-addr=%p, visitor=%p",
434 stream_class, visitor);
435 ret = -1;
436 goto end;
437 }
438
439 ret = bt_ctf_visitor_helper(&obj, get_event_class_count,
440 get_event_class,
441 visit_event_class, visitor, data);
442 BT_LOGT("bt_ctf_visitor_helper() returned: ret=%d", ret);
443
444 end:
445 return ret;
446 }
447
448 BT_HIDDEN
449 int bt_ctf_stream_class_visit(struct bt_ctf_stream_class *stream_class,
450 bt_ctf_visitor visitor, void *data)
451 {
452 return bt_ctf_stream_class_common_visit(BT_CTF_FROM_COMMON(stream_class),
453 visitor, data);
454 }
455
456 BT_HIDDEN
457 void bt_ctf_stream_class_common_freeze(struct bt_ctf_stream_class_common *stream_class)
458 {
459 if (!stream_class || stream_class->frozen) {
460 return;
461 }
462
463 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64,
464 stream_class, bt_ctf_stream_class_common_get_name(stream_class),
465 bt_ctf_stream_class_common_get_id(stream_class));
466 stream_class->frozen = 1;
467 bt_ctf_field_type_common_freeze(stream_class->event_header_field_type);
468 bt_ctf_field_type_common_freeze(stream_class->packet_context_field_type);
469 bt_ctf_field_type_common_freeze(stream_class->event_context_field_type);
470 bt_ctf_clock_class_freeze(stream_class->clock_class);
471 }
472
473 BT_HIDDEN
474 int bt_ctf_stream_class_common_validate_single_clock_class(
475 struct bt_ctf_stream_class_common *stream_class,
476 struct bt_ctf_clock_class **expected_clock_class)
477 {
478 int ret;
479 uint64_t i;
480
481 BT_ASSERT_DBG(stream_class);
482 BT_ASSERT_DBG(expected_clock_class);
483 ret = bt_ctf_field_type_common_validate_single_clock_class(
484 stream_class->packet_context_field_type,
485 expected_clock_class);
486 if (ret) {
487 BT_LOGW("Stream class's packet context field type "
488 "is not recursively mapped to the "
489 "expected clock class: "
490 "stream-class-addr=%p, "
491 "stream-class-name=\"%s\", "
492 "stream-class-id=%" PRId64 ", "
493 "ft-addr=%p",
494 stream_class,
495 bt_ctf_stream_class_common_get_name(stream_class),
496 stream_class->id,
497 stream_class->packet_context_field_type);
498 goto end;
499 }
500
501 ret = bt_ctf_field_type_common_validate_single_clock_class(
502 stream_class->event_header_field_type,
503 expected_clock_class);
504 if (ret) {
505 BT_LOGW("Stream class's event header field type "
506 "is not recursively mapped to the "
507 "expected clock class: "
508 "stream-class-addr=%p, "
509 "stream-class-name=\"%s\", "
510 "stream-class-id=%" PRId64 ", "
511 "ft-addr=%p",
512 stream_class,
513 bt_ctf_stream_class_common_get_name(stream_class),
514 stream_class->id,
515 stream_class->event_header_field_type);
516 goto end;
517 }
518
519 ret = bt_ctf_field_type_common_validate_single_clock_class(
520 stream_class->event_context_field_type,
521 expected_clock_class);
522 if (ret) {
523 BT_LOGW("Stream class's event context field type "
524 "is not recursively mapped to the "
525 "expected clock class: "
526 "stream-class-addr=%p, "
527 "stream-class-name=\"%s\", "
528 "stream-class-id=%" PRId64 ", "
529 "ft-addr=%p",
530 stream_class,
531 bt_ctf_stream_class_common_get_name(stream_class),
532 stream_class->id,
533 stream_class->event_context_field_type);
534 goto end;
535 }
536
537 for (i = 0; i < stream_class->event_classes->len; i++) {
538 struct bt_ctf_event_class_common *event_class =
539 g_ptr_array_index(stream_class->event_classes, i);
540
541 BT_ASSERT_DBG(event_class);
542 ret = bt_ctf_event_class_common_validate_single_clock_class(
543 event_class, expected_clock_class);
544 if (ret) {
545 BT_LOGW("Stream class's event class contains a "
546 "field type which is not recursively mapped to "
547 "the expected clock class: "
548 "stream-class-addr=%p, "
549 "stream-class-name=\"%s\", "
550 "stream-class-id=%" PRId64,
551 stream_class,
552 bt_ctf_stream_class_common_get_name(stream_class),
553 stream_class->id);
554 goto end;
555 }
556 }
557
558 end:
559 return ret;
560 }
561
562 static
563 int init_event_header(struct bt_ctf_stream_class *stream_class)
564 {
565 int ret = 0;
566 struct bt_ctf_field_type *event_header_type =
567 bt_ctf_field_type_structure_create();
568 struct bt_ctf_field_type *_uint32_t =
569 get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
570 struct bt_ctf_field_type *_uint64_t =
571 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
572
573 if (!event_header_type) {
574 BT_LOGE_STR("Cannot create empty structure field type.");
575 ret = -1;
576 goto end;
577 }
578
579 ret = bt_ctf_field_type_structure_add_field(event_header_type,
580 _uint32_t, "id");
581 if (ret) {
582 BT_LOGE_STR("Cannot add `id` field to event header field type.");
583 goto end;
584 }
585
586 ret = bt_ctf_field_type_structure_add_field(event_header_type,
587 _uint64_t, "timestamp");
588 if (ret) {
589 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
590 goto end;
591 }
592
593 bt_ctf_object_put_ref(stream_class->common.event_header_field_type);
594 stream_class->common.event_header_field_type =
595 (void *) event_header_type;
596 event_header_type = NULL;
597
598 end:
599 if (ret) {
600 bt_ctf_object_put_ref(event_header_type);
601 }
602
603 bt_ctf_object_put_ref(_uint32_t);
604 bt_ctf_object_put_ref(_uint64_t);
605 return ret;
606 }
607
608 static
609 int init_packet_context(struct bt_ctf_stream_class *stream_class)
610 {
611 int ret = 0;
612 struct bt_ctf_field_type *packet_context_type =
613 bt_ctf_field_type_structure_create();
614 struct bt_ctf_field_type *_uint64_t =
615 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
616 struct bt_ctf_field_type *ts_begin_end_uint64_t = NULL;
617
618 if (!packet_context_type) {
619 BT_LOGE_STR("Cannot create empty structure field type.");
620 ret = -1;
621 goto end;
622 }
623
624 ts_begin_end_uint64_t = bt_ctf_field_type_copy(_uint64_t);
625 if (!ts_begin_end_uint64_t) {
626 BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
627 ret = -1;
628 goto end;
629 }
630
631 /*
632 * We create a stream packet context as proposed in the CTF
633 * specification.
634 */
635 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
636 ts_begin_end_uint64_t, "timestamp_begin");
637 if (ret) {
638 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
639 goto end;
640 }
641
642 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
643 ts_begin_end_uint64_t, "timestamp_end");
644 if (ret) {
645 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
646 goto end;
647 }
648
649 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
650 _uint64_t, "content_size");
651 if (ret) {
652 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
653 goto end;
654 }
655
656 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
657 _uint64_t, "packet_size");
658 if (ret) {
659 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
660 goto end;
661 }
662
663 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
664 _uint64_t, "events_discarded");
665 if (ret) {
666 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
667 goto end;
668 }
669
670 bt_ctf_object_put_ref(stream_class->common.packet_context_field_type);
671 stream_class->common.packet_context_field_type =
672 (void *) packet_context_type;
673 packet_context_type = NULL;
674
675 end:
676 if (ret) {
677 bt_ctf_object_put_ref(packet_context_type);
678 goto end;
679 }
680
681 bt_ctf_object_put_ref(_uint64_t);
682 bt_ctf_object_put_ref(ts_begin_end_uint64_t);
683 return ret;
684 }
685
686 static
687 void bt_ctf_stream_class_destroy(struct bt_ctf_object *obj)
688 {
689 struct bt_ctf_stream_class *stream_class;
690
691 stream_class = (void *) obj;
692 BT_LOGD("Destroying CTF writer stream class: addr=%p, name=\"%s\", id=%" PRId64,
693 stream_class, bt_ctf_stream_class_get_name(stream_class),
694 bt_ctf_stream_class_get_id(stream_class));
695 bt_ctf_stream_class_common_finalize(BT_CTF_TO_COMMON(stream_class));
696 bt_ctf_object_put_ref(stream_class->clock);
697 g_free(stream_class);
698 }
699
700 struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *name)
701 {
702 struct bt_ctf_stream_class *stream_class;
703 int ret;
704
705 BT_LOGD("Creating CTF writer stream class object: name=\"%s\"", name);
706 stream_class = g_new0(struct bt_ctf_stream_class, 1);
707 if (!stream_class) {
708 BT_LOGE_STR("Failed to allocate one CTF writer stream class.");
709 goto error;
710 }
711
712 ret = bt_ctf_stream_class_common_initialize(BT_CTF_TO_COMMON(stream_class),
713 name, bt_ctf_stream_class_destroy);
714 if (ret) {
715 /* bt_ctf_stream_class_common_initialize() logs errors */
716 goto error;
717 }
718
719 ret = init_event_header(stream_class);
720 if (ret) {
721 BT_LOGE_STR("Cannot initialize stream class's event header field type.");
722 goto error;
723 }
724
725 ret = init_packet_context(stream_class);
726 if (ret) {
727 BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
728 goto error;
729 }
730
731 BT_LOGD("Created CTF writer stream class object: addr=%p, name=\"%s\"",
732 stream_class, name);
733 return stream_class;
734
735 error:
736 BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_class);
737 return stream_class;
738 }
739
740 static
741 int try_map_clock_class(struct bt_ctf_stream_class *stream_class,
742 struct bt_ctf_field_type *parent_ft, const char *field_name)
743 {
744 struct bt_ctf_clock_class *mapped_clock_class = NULL;
745 int ret = 0;
746 struct bt_ctf_field_type *ft =
747 bt_ctf_field_type_structure_get_field_type_by_name(parent_ft,
748 field_name);
749
750 BT_ASSERT_DBG(stream_class->clock);
751
752 if (!ft) {
753 /* Field does not exist: not an error */
754 goto end;
755 }
756
757 BT_ASSERT_DBG(((struct bt_ctf_field_type_common *) ft)->id ==
758 BT_CTF_FIELD_TYPE_ID_INTEGER);
759 mapped_clock_class =
760 bt_ctf_field_type_integer_get_mapped_clock_class(ft);
761 if (!mapped_clock_class) {
762 struct bt_ctf_field_type *ft_copy;
763
764 if (!stream_class->clock) {
765 BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
766 "stream-class-addr=%p, stream-class-name=\"%s\", "
767 "stream-class-id=%" PRId64 ", ft-addr=%p",
768 stream_class,
769 bt_ctf_stream_class_get_name(stream_class),
770 bt_ctf_stream_class_get_id(stream_class), ft);
771 ret = -1;
772 goto end;
773 }
774
775 ft_copy = bt_ctf_field_type_copy(ft);
776 if (!ft_copy) {
777 BT_LOGE("Failed to copy integer field type: ft-addr=%p",
778 ft);
779 ret = -1;
780 goto end;
781 }
782
783 ret = bt_ctf_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
784 (void *) ft_copy, stream_class->clock->clock_class);
785 BT_ASSERT_DBG(ret == 0);
786
787 ret = bt_ctf_field_type_common_structure_replace_field(
788 (void *) parent_ft, field_name, (void *) ft_copy);
789 bt_ctf_object_put_ref(ft_copy);
790 BT_LOGT("Automatically mapped field type to stream class's clock class: "
791 "stream-class-addr=%p, stream-class-name=\"%s\", "
792 "stream-class-id=%" PRId64 ", ft-addr=%p, "
793 "ft-copy-addr=%p",
794 stream_class,
795 bt_ctf_stream_class_get_name(stream_class),
796 bt_ctf_stream_class_get_id(stream_class), ft, ft_copy);
797 }
798
799 end:
800 bt_ctf_object_put_ref(ft);
801 bt_ctf_object_put_ref(mapped_clock_class);
802 return ret;
803 }
804
805 BT_HIDDEN
806 int bt_ctf_stream_class_map_clock_class(
807 struct bt_ctf_stream_class *stream_class,
808 struct bt_ctf_field_type *packet_context_type,
809 struct bt_ctf_field_type *event_header_type)
810 {
811 int ret = 0;
812
813 BT_ASSERT_DBG(stream_class);
814
815 if (!stream_class->clock) {
816 /* No clock class to map to */
817 goto end;
818 }
819
820 if (packet_context_type) {
821 if (try_map_clock_class(stream_class, packet_context_type,
822 "timestamp_begin")) {
823 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
824 ret = -1;
825 goto end;
826 }
827
828 if (try_map_clock_class(stream_class, packet_context_type,
829 "timestamp_end")) {
830 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
831 ret = -1;
832 goto end;
833 }
834 }
835
836 if (event_header_type) {
837 if (try_map_clock_class(stream_class, event_header_type,
838 "timestamp")) {
839 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
840 ret = -1;
841 goto end;
842 }
843 }
844
845 end:
846 return ret;
847 }
848
849 struct bt_ctf_clock *bt_ctf_stream_class_get_clock(
850 struct bt_ctf_stream_class *stream_class)
851 {
852 struct bt_ctf_clock *clock = NULL;
853
854 if (!stream_class) {
855 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
856 goto end;
857 }
858
859 if (!stream_class->clock) {
860 BT_LOGT("Stream class has no clock: "
861 "addr=%p, name=\"%s\", id=%" PRId64,
862 stream_class,
863 bt_ctf_stream_class_get_name(stream_class),
864 bt_ctf_stream_class_get_id(stream_class));
865 goto end;
866 }
867
868 clock = bt_ctf_object_get_ref(stream_class->clock);
869
870 end:
871 return clock;
872 }
873
874 int bt_ctf_stream_class_set_clock(
875 struct bt_ctf_stream_class *stream_class,
876 struct bt_ctf_clock *clock)
877 {
878 int ret = 0;
879
880 if (!stream_class || !clock) {
881 BT_LOGW("Invalid parameter: stream class or clock is NULL: "
882 "stream-class-addr=%p, clock-addr=%p",
883 stream_class, clock);
884 ret = -1;
885 goto end;
886 }
887
888 if (stream_class->common.frozen) {
889 BT_LOGW("Invalid parameter: stream class is frozen: "
890 "addr=%p, name=\"%s\", id=%" PRId64,
891 stream_class,
892 bt_ctf_stream_class_get_name(stream_class),
893 bt_ctf_stream_class_get_id(stream_class));
894 ret = -1;
895 goto end;
896 }
897
898 /* Replace the current clock of this stream class. */
899 bt_ctf_object_put_ref(stream_class->clock);
900 stream_class->clock = bt_ctf_object_get_ref(clock);
901 BT_LOGT("Set stream class's clock: "
902 "addr=%p, name=\"%s\", id=%" PRId64 ", "
903 "clock-addr=%p, clock-name=\"%s\"",
904 stream_class,
905 bt_ctf_stream_class_get_name(stream_class),
906 bt_ctf_stream_class_get_id(stream_class),
907 stream_class->clock,
908 bt_ctf_clock_get_name(stream_class->clock));
909
910 end:
911 return ret;
912 }
913
914 BT_HIDDEN
915 int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
916 struct metadata_context *context)
917 {
918 int ret = 0;
919 size_t i;
920 struct bt_ctf_trace *trace;
921 struct bt_ctf_field_type *packet_header_type = NULL;
922
923 BT_LOGD("Serializing stream class's metadata: "
924 "stream-class-addr=%p, stream-class-name=\"%s\", "
925 "stream-class-id=%" PRId64 ", metadata-context-addr=%p",
926 stream_class,
927 bt_ctf_stream_class_get_name(stream_class),
928 bt_ctf_stream_class_get_id(stream_class), context);
929 g_string_assign(context->field_name, "");
930 context->current_indentation_level = 1;
931 if (!stream_class->common.id_set) {
932 BT_LOGW_STR("Stream class's ID is not set.");
933 ret = -1;
934 goto end;
935 }
936
937 g_string_append(context->string, "stream {\n");
938
939 /*
940 * The reference to the trace is only borrowed since the
941 * serialization of the stream class might have been triggered
942 * by the trace's destruction. In such a case, the trace's
943 * reference count would, unexepectedly, go through the sequence
944 * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
945 * and serialization.
946 */
947 trace = BT_CTF_FROM_COMMON(bt_ctf_stream_class_common_borrow_trace(
948 BT_CTF_TO_COMMON(stream_class)));
949 BT_ASSERT_DBG(trace);
950 packet_header_type = bt_ctf_trace_get_packet_header_field_type(trace);
951 trace = NULL;
952 if (packet_header_type) {
953 struct bt_ctf_field_type *stream_id_type;
954
955 stream_id_type =
956 bt_ctf_field_type_structure_get_field_type_by_name(
957 packet_header_type, "stream_id");
958 if (stream_id_type) {
959 /*
960 * Only set the stream's id if the trace's packet header
961 * contains a stream_id field. This field is only
962 * needed if the trace contains only one stream
963 * class.
964 */
965 g_string_append_printf(context->string,
966 "\tid = %" PRId64 ";\n",
967 stream_class->common.id);
968 }
969 bt_ctf_object_put_ref(stream_id_type);
970 }
971 if (stream_class->common.event_header_field_type) {
972 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
973 g_string_append(context->string, "\tevent.header := ");
974 ret = bt_ctf_field_type_serialize_recursive(
975 (void *) stream_class->common.event_header_field_type,
976 context);
977 if (ret) {
978 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
979 "ret=%d", ret);
980 goto end;
981 }
982 g_string_append(context->string, ";");
983 }
984
985
986 if (stream_class->common.packet_context_field_type) {
987 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
988 g_string_append(context->string, "\n\n\tpacket.context := ");
989 ret = bt_ctf_field_type_serialize_recursive(
990 (void *) stream_class->common.packet_context_field_type,
991 context);
992 if (ret) {
993 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
994 "ret=%d", ret);
995 goto end;
996 }
997 g_string_append(context->string, ";");
998 }
999
1000 if (stream_class->common.event_context_field_type) {
1001 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
1002 g_string_append(context->string, "\n\n\tevent.context := ");
1003 ret = bt_ctf_field_type_serialize_recursive(
1004 (void *) stream_class->common.event_context_field_type,
1005 context);
1006 if (ret) {
1007 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
1008 "ret=%d", ret);
1009 goto end;
1010 }
1011 g_string_append(context->string, ";");
1012 }
1013
1014 g_string_append(context->string, "\n};\n\n");
1015
1016 for (i = 0; i < stream_class->common.event_classes->len; i++) {
1017 struct bt_ctf_event_class *event_class =
1018 stream_class->common.event_classes->pdata[i];
1019
1020 ret = bt_ctf_event_class_serialize(event_class, context);
1021 if (ret) {
1022 BT_LOGW("Cannot serialize event class's metadata: "
1023 "event-class-addr=%p, event-class-name=\"%s\", "
1024 "event-class-id=%" PRId64,
1025 event_class,
1026 bt_ctf_event_class_get_name(event_class),
1027 bt_ctf_event_class_get_id(event_class));
1028 goto end;
1029 }
1030 }
1031
1032 end:
1033 bt_ctf_object_put_ref(packet_header_type);
1034 context->current_indentation_level = 0;
1035 return ret;
1036 }
1037
1038 struct bt_ctf_trace *bt_ctf_stream_class_get_trace(
1039 struct bt_ctf_stream_class *stream_class)
1040 {
1041 return bt_ctf_object_get_ref(bt_ctf_stream_class_common_borrow_trace(
1042 BT_CTF_TO_COMMON(stream_class)));
1043 }
1044
1045 const char *bt_ctf_stream_class_get_name(
1046 struct bt_ctf_stream_class *stream_class)
1047 {
1048 return bt_ctf_stream_class_common_get_name(BT_CTF_TO_COMMON(stream_class));
1049 }
1050
1051 int bt_ctf_stream_class_set_name(
1052 struct bt_ctf_stream_class *stream_class, const char *name)
1053 {
1054 return bt_ctf_stream_class_common_set_name(BT_CTF_TO_COMMON(stream_class),
1055 name);
1056 }
1057
1058 int64_t bt_ctf_stream_class_get_id(
1059 struct bt_ctf_stream_class *stream_class)
1060 {
1061 return bt_ctf_stream_class_common_get_id(BT_CTF_TO_COMMON(stream_class));
1062 }
1063
1064 int bt_ctf_stream_class_set_id(
1065 struct bt_ctf_stream_class *stream_class, uint64_t id)
1066 {
1067 return bt_ctf_stream_class_common_set_id(BT_CTF_TO_COMMON(stream_class), id);
1068 }
1069
1070 struct bt_ctf_field_type *bt_ctf_stream_class_get_packet_context_type(
1071 struct bt_ctf_stream_class *stream_class)
1072 {
1073 return bt_ctf_object_get_ref(
1074 bt_ctf_stream_class_common_borrow_packet_context_field_type(
1075 BT_CTF_TO_COMMON(stream_class)));
1076 }
1077
1078 int bt_ctf_stream_class_set_packet_context_type(
1079 struct bt_ctf_stream_class *stream_class,
1080 struct bt_ctf_field_type *packet_context_type)
1081 {
1082 return bt_ctf_stream_class_common_set_packet_context_field_type(
1083 BT_CTF_TO_COMMON(stream_class), (void *) packet_context_type);
1084 }
1085
1086 struct bt_ctf_field_type *
1087 bt_ctf_stream_class_get_event_header_type(
1088 struct bt_ctf_stream_class *stream_class)
1089 {
1090 return bt_ctf_object_get_ref(
1091 bt_ctf_stream_class_common_borrow_event_header_field_type(
1092 BT_CTF_TO_COMMON(stream_class)));
1093 }
1094
1095 int bt_ctf_stream_class_set_event_header_type(
1096 struct bt_ctf_stream_class *stream_class,
1097 struct bt_ctf_field_type *event_header_type)
1098 {
1099 return bt_ctf_stream_class_common_set_event_header_field_type(
1100 BT_CTF_TO_COMMON(stream_class), (void *) event_header_type);
1101 }
1102
1103 struct bt_ctf_field_type *
1104 bt_ctf_stream_class_get_event_context_type(
1105 struct bt_ctf_stream_class *stream_class)
1106 {
1107 return bt_ctf_object_get_ref(
1108 bt_ctf_stream_class_common_borrow_event_context_field_type(
1109 BT_CTF_TO_COMMON(stream_class)));
1110 }
1111
1112 int bt_ctf_stream_class_set_event_context_type(
1113 struct bt_ctf_stream_class *stream_class,
1114 struct bt_ctf_field_type *event_context_type)
1115 {
1116 return bt_ctf_stream_class_common_set_event_context_field_type(
1117 BT_CTF_TO_COMMON(stream_class), (void *) event_context_type);
1118 }
1119
1120 int64_t bt_ctf_stream_class_get_event_class_count(
1121 struct bt_ctf_stream_class *stream_class)
1122 {
1123 return bt_ctf_stream_class_common_get_event_class_count(
1124 BT_CTF_TO_COMMON(stream_class));
1125 }
1126
1127 struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_index(
1128 struct bt_ctf_stream_class *stream_class, uint64_t index)
1129 {
1130 return bt_ctf_object_get_ref(
1131 bt_ctf_stream_class_common_borrow_event_class_by_index(
1132 BT_CTF_TO_COMMON(stream_class), index));
1133 }
1134
1135 struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_id(
1136 struct bt_ctf_stream_class *stream_class, uint64_t id)
1137 {
1138 return bt_ctf_object_get_ref(
1139 bt_ctf_stream_class_common_borrow_event_class_by_id(
1140 BT_CTF_TO_COMMON(stream_class), id));
1141 }
1142
1143 int bt_ctf_stream_class_add_event_class(
1144 struct bt_ctf_stream_class *stream_class,
1145 struct bt_ctf_event_class *event_class)
1146 {
1147 return bt_ctf_stream_class_common_add_event_class(
1148 BT_CTF_TO_COMMON(stream_class), BT_CTF_TO_COMMON(event_class),
1149 (bt_ctf_validation_flag_copy_field_type_func) bt_ctf_field_type_copy);
1150 }
This page took 0.088897 seconds and 4 git commands to generate.