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