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