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