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