Always evaluate BT_ASSERT(); add BT_ASSERT_DBG() for debug mode only
[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
217cf9d3
PP
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>
578e048b
MJ
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
98b15851 170 BT_ASSERT_DBG(copy_field_type_func);
16ca5ff0
PP
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 */
98b15851
PP
274 BT_ASSERT_DBG(trace->valid);
275 BT_ASSERT_DBG(stream_class->valid);
16ca5ff0
PP
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) {
98b15851 374 BT_ASSERT_DBG(!stream_class->clock_class ||
16ca5ff0 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
98b15851
PP
481 BT_ASSERT_DBG(stream_class);
482 BT_ASSERT_DBG(expected_clock_class);
16ca5ff0
PP
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
98b15851 541 BT_ASSERT_DBG(event_class);
16ca5ff0
PP
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);
4af85094 616 struct bt_ctf_field_type *ts_begin_end_uint64_t = NULL;
3dca2276
PP
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
98b15851 750 BT_ASSERT_DBG(stream_class->clock);
3dca2276
PP
751
752 if (!ft) {
753 /* Field does not exist: not an error */
754 goto end;
755 }
756
98b15851 757 BT_ASSERT_DBG(((struct bt_ctf_field_type_common *) ft)->id ==
16ca5ff0 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);
94c1a13b
FD
779 ret = -1;
780 goto end;
3dca2276
PP
781 }
782
16ca5ff0
PP
783 ret = bt_ctf_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
784 (void *) ft_copy, stream_class->clock->clock_class);
98b15851 785 BT_ASSERT_DBG(ret == 0);
3dca2276 786
16ca5ff0 787 ret = bt_ctf_field_type_common_structure_replace_field(
3dca2276 788 (void *) parent_ft, field_name, (void *) ft_copy);
e1e02a22 789 bt_ctf_object_put_ref(ft_copy);
ef267d12 790 BT_LOGT("Automatically mapped field type to stream class's clock class: "
3dca2276
PP
791 "stream-class-addr=%p, stream-class-name=\"%s\", "
792 "stream-class-id=%" PRId64 ", ft-addr=%p, "
793 "ft-copy-addr=%p",
794 stream_class,
795 bt_ctf_stream_class_get_name(stream_class),
796 bt_ctf_stream_class_get_id(stream_class), ft, ft_copy);
797 }
798
799end:
e1e02a22
PP
800 bt_ctf_object_put_ref(ft);
801 bt_ctf_object_put_ref(mapped_clock_class);
3dca2276
PP
802 return ret;
803}
804
805BT_HIDDEN
806int bt_ctf_stream_class_map_clock_class(
807 struct bt_ctf_stream_class *stream_class,
808 struct bt_ctf_field_type *packet_context_type,
809 struct bt_ctf_field_type *event_header_type)
810{
811 int ret = 0;
812
98b15851 813 BT_ASSERT_DBG(stream_class);
3dca2276
PP
814
815 if (!stream_class->clock) {
816 /* No clock class to map to */
817 goto end;
818 }
819
820 if (packet_context_type) {
821 if (try_map_clock_class(stream_class, packet_context_type,
822 "timestamp_begin")) {
823 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
824 ret = -1;
825 goto end;
826 }
827
828 if (try_map_clock_class(stream_class, packet_context_type,
829 "timestamp_end")) {
830 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
831 ret = -1;
832 goto end;
833 }
834 }
835
836 if (event_header_type) {
837 if (try_map_clock_class(stream_class, event_header_type,
838 "timestamp")) {
839 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
840 ret = -1;
841 goto end;
842 }
843 }
844
845end:
846 return ret;
847}
848
849struct bt_ctf_clock *bt_ctf_stream_class_get_clock(
850 struct bt_ctf_stream_class *stream_class)
851{
852 struct bt_ctf_clock *clock = NULL;
853
854 if (!stream_class) {
855 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
856 goto end;
857 }
858
859 if (!stream_class->clock) {
ef267d12 860 BT_LOGT("Stream class has no clock: "
3dca2276
PP
861 "addr=%p, name=\"%s\", id=%" PRId64,
862 stream_class,
863 bt_ctf_stream_class_get_name(stream_class),
864 bt_ctf_stream_class_get_id(stream_class));
865 goto end;
866 }
867
e1e02a22 868 clock = bt_ctf_object_get_ref(stream_class->clock);
3dca2276
PP
869
870end:
871 return clock;
872}
873
874int bt_ctf_stream_class_set_clock(
875 struct bt_ctf_stream_class *stream_class,
876 struct bt_ctf_clock *clock)
877{
878 int ret = 0;
879
880 if (!stream_class || !clock) {
881 BT_LOGW("Invalid parameter: stream class or clock is NULL: "
882 "stream-class-addr=%p, clock-addr=%p",
883 stream_class, clock);
884 ret = -1;
885 goto end;
886 }
887
888 if (stream_class->common.frozen) {
889 BT_LOGW("Invalid parameter: stream class is frozen: "
890 "addr=%p, name=\"%s\", id=%" PRId64,
891 stream_class,
892 bt_ctf_stream_class_get_name(stream_class),
893 bt_ctf_stream_class_get_id(stream_class));
894 ret = -1;
895 goto end;
896 }
897
898 /* Replace the current clock of this stream class. */
e1e02a22
PP
899 bt_ctf_object_put_ref(stream_class->clock);
900 stream_class->clock = bt_ctf_object_get_ref(clock);
ef267d12 901 BT_LOGT("Set stream class's clock: "
3dca2276
PP
902 "addr=%p, name=\"%s\", id=%" PRId64 ", "
903 "clock-addr=%p, clock-name=\"%s\"",
904 stream_class,
905 bt_ctf_stream_class_get_name(stream_class),
906 bt_ctf_stream_class_get_id(stream_class),
907 stream_class->clock,
908 bt_ctf_clock_get_name(stream_class->clock));
909
910end:
911 return ret;
912}
913
914BT_HIDDEN
915int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
916 struct metadata_context *context)
917{
918 int ret = 0;
919 size_t i;
920 struct bt_ctf_trace *trace;
921 struct bt_ctf_field_type *packet_header_type = NULL;
922
923 BT_LOGD("Serializing stream class's metadata: "
924 "stream-class-addr=%p, stream-class-name=\"%s\", "
925 "stream-class-id=%" PRId64 ", metadata-context-addr=%p",
926 stream_class,
927 bt_ctf_stream_class_get_name(stream_class),
928 bt_ctf_stream_class_get_id(stream_class), context);
929 g_string_assign(context->field_name, "");
930 context->current_indentation_level = 1;
931 if (!stream_class->common.id_set) {
932 BT_LOGW_STR("Stream class's ID is not set.");
933 ret = -1;
934 goto end;
935 }
936
937 g_string_append(context->string, "stream {\n");
938
939 /*
940 * The reference to the trace is only borrowed since the
941 * serialization of the stream class might have been triggered
942 * by the trace's destruction. In such a case, the trace's
943 * reference count would, unexepectedly, go through the sequence
944 * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
945 * and serialization.
946 */
16ca5ff0
PP
947 trace = BT_CTF_FROM_COMMON(bt_ctf_stream_class_common_borrow_trace(
948 BT_CTF_TO_COMMON(stream_class)));
98b15851 949 BT_ASSERT_DBG(trace);
3dca2276
PP
950 packet_header_type = bt_ctf_trace_get_packet_header_field_type(trace);
951 trace = NULL;
952 if (packet_header_type) {
953 struct bt_ctf_field_type *stream_id_type;
954
955 stream_id_type =
956 bt_ctf_field_type_structure_get_field_type_by_name(
957 packet_header_type, "stream_id");
958 if (stream_id_type) {
959 /*
960 * Only set the stream's id if the trace's packet header
961 * contains a stream_id field. This field is only
962 * needed if the trace contains only one stream
963 * class.
964 */
965 g_string_append_printf(context->string,
966 "\tid = %" PRId64 ";\n",
967 stream_class->common.id);
968 }
e1e02a22 969 bt_ctf_object_put_ref(stream_id_type);
3dca2276
PP
970 }
971 if (stream_class->common.event_header_field_type) {
972 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
973 g_string_append(context->string, "\tevent.header := ");
974 ret = bt_ctf_field_type_serialize_recursive(
975 (void *) stream_class->common.event_header_field_type,
976 context);
977 if (ret) {
978 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
979 "ret=%d", ret);
980 goto end;
981 }
982 g_string_append(context->string, ";");
983 }
984
985
986 if (stream_class->common.packet_context_field_type) {
987 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
988 g_string_append(context->string, "\n\n\tpacket.context := ");
989 ret = bt_ctf_field_type_serialize_recursive(
990 (void *) stream_class->common.packet_context_field_type,
991 context);
992 if (ret) {
993 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
994 "ret=%d", ret);
995 goto end;
996 }
997 g_string_append(context->string, ";");
998 }
999
1000 if (stream_class->common.event_context_field_type) {
1001 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
1002 g_string_append(context->string, "\n\n\tevent.context := ");
1003 ret = bt_ctf_field_type_serialize_recursive(
1004 (void *) stream_class->common.event_context_field_type,
1005 context);
1006 if (ret) {
1007 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
1008 "ret=%d", ret);
1009 goto end;
1010 }
1011 g_string_append(context->string, ";");
1012 }
1013
1014 g_string_append(context->string, "\n};\n\n");
1015
1016 for (i = 0; i < stream_class->common.event_classes->len; i++) {
1017 struct bt_ctf_event_class *event_class =
1018 stream_class->common.event_classes->pdata[i];
1019
1020 ret = bt_ctf_event_class_serialize(event_class, context);
1021 if (ret) {
1022 BT_LOGW("Cannot serialize event class's metadata: "
1023 "event-class-addr=%p, event-class-name=\"%s\", "
1024 "event-class-id=%" PRId64,
1025 event_class,
1026 bt_ctf_event_class_get_name(event_class),
1027 bt_ctf_event_class_get_id(event_class));
1028 goto end;
1029 }
1030 }
1031
1032end:
e1e02a22 1033 bt_ctf_object_put_ref(packet_header_type);
3dca2276
PP
1034 context->current_indentation_level = 0;
1035 return ret;
1036}
1037
1038struct bt_ctf_trace *bt_ctf_stream_class_get_trace(
1039 struct bt_ctf_stream_class *stream_class)
1040{
e1e02a22 1041 return bt_ctf_object_get_ref(bt_ctf_stream_class_common_borrow_trace(
16ca5ff0 1042 BT_CTF_TO_COMMON(stream_class)));
3dca2276
PP
1043}
1044
1045const char *bt_ctf_stream_class_get_name(
1046 struct bt_ctf_stream_class *stream_class)
1047{
16ca5ff0 1048 return bt_ctf_stream_class_common_get_name(BT_CTF_TO_COMMON(stream_class));
3dca2276
PP
1049}
1050
1051int bt_ctf_stream_class_set_name(
1052 struct bt_ctf_stream_class *stream_class, const char *name)
1053{
16ca5ff0 1054 return bt_ctf_stream_class_common_set_name(BT_CTF_TO_COMMON(stream_class),
3dca2276
PP
1055 name);
1056}
1057
1058int64_t bt_ctf_stream_class_get_id(
1059 struct bt_ctf_stream_class *stream_class)
1060{
16ca5ff0 1061 return bt_ctf_stream_class_common_get_id(BT_CTF_TO_COMMON(stream_class));
3dca2276
PP
1062}
1063
1064int bt_ctf_stream_class_set_id(
1065 struct bt_ctf_stream_class *stream_class, uint64_t id)
1066{
16ca5ff0 1067 return bt_ctf_stream_class_common_set_id(BT_CTF_TO_COMMON(stream_class), id);
3dca2276
PP
1068}
1069
1070struct bt_ctf_field_type *bt_ctf_stream_class_get_packet_context_type(
1071 struct bt_ctf_stream_class *stream_class)
1072{
e1e02a22 1073 return bt_ctf_object_get_ref(
16ca5ff0
PP
1074 bt_ctf_stream_class_common_borrow_packet_context_field_type(
1075 BT_CTF_TO_COMMON(stream_class)));
3dca2276
PP
1076}
1077
1078int bt_ctf_stream_class_set_packet_context_type(
1079 struct bt_ctf_stream_class *stream_class,
1080 struct bt_ctf_field_type *packet_context_type)
1081{
16ca5ff0
PP
1082 return bt_ctf_stream_class_common_set_packet_context_field_type(
1083 BT_CTF_TO_COMMON(stream_class), (void *) packet_context_type);
3dca2276
PP
1084}
1085
1086struct bt_ctf_field_type *
1087bt_ctf_stream_class_get_event_header_type(
1088 struct bt_ctf_stream_class *stream_class)
1089{
e1e02a22 1090 return bt_ctf_object_get_ref(
16ca5ff0
PP
1091 bt_ctf_stream_class_common_borrow_event_header_field_type(
1092 BT_CTF_TO_COMMON(stream_class)));
3dca2276
PP
1093}
1094
1095int bt_ctf_stream_class_set_event_header_type(
1096 struct bt_ctf_stream_class *stream_class,
1097 struct bt_ctf_field_type *event_header_type)
1098{
16ca5ff0
PP
1099 return bt_ctf_stream_class_common_set_event_header_field_type(
1100 BT_CTF_TO_COMMON(stream_class), (void *) event_header_type);
3dca2276
PP
1101}
1102
1103struct bt_ctf_field_type *
1104bt_ctf_stream_class_get_event_context_type(
1105 struct bt_ctf_stream_class *stream_class)
1106{
e1e02a22 1107 return bt_ctf_object_get_ref(
16ca5ff0
PP
1108 bt_ctf_stream_class_common_borrow_event_context_field_type(
1109 BT_CTF_TO_COMMON(stream_class)));
3dca2276
PP
1110}
1111
1112int bt_ctf_stream_class_set_event_context_type(
1113 struct bt_ctf_stream_class *stream_class,
1114 struct bt_ctf_field_type *event_context_type)
1115{
16ca5ff0
PP
1116 return bt_ctf_stream_class_common_set_event_context_field_type(
1117 BT_CTF_TO_COMMON(stream_class), (void *) event_context_type);
3dca2276
PP
1118}
1119
1120int64_t bt_ctf_stream_class_get_event_class_count(
1121 struct bt_ctf_stream_class *stream_class)
1122{
16ca5ff0
PP
1123 return bt_ctf_stream_class_common_get_event_class_count(
1124 BT_CTF_TO_COMMON(stream_class));
3dca2276
PP
1125}
1126
1127struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_index(
1128 struct bt_ctf_stream_class *stream_class, uint64_t index)
1129{
e1e02a22 1130 return bt_ctf_object_get_ref(
16ca5ff0
PP
1131 bt_ctf_stream_class_common_borrow_event_class_by_index(
1132 BT_CTF_TO_COMMON(stream_class), index));
3dca2276
PP
1133}
1134
1135struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_id(
1136 struct bt_ctf_stream_class *stream_class, uint64_t id)
1137{
e1e02a22 1138 return bt_ctf_object_get_ref(
16ca5ff0
PP
1139 bt_ctf_stream_class_common_borrow_event_class_by_id(
1140 BT_CTF_TO_COMMON(stream_class), id));
3dca2276
PP
1141}
1142
1143int bt_ctf_stream_class_add_event_class(
1144 struct bt_ctf_stream_class *stream_class,
1145 struct bt_ctf_event_class *event_class)
1146{
16ca5ff0
PP
1147 return bt_ctf_stream_class_common_add_event_class(
1148 BT_CTF_TO_COMMON(stream_class), BT_CTF_TO_COMMON(event_class),
1149 (bt_ctf_validation_flag_copy_field_type_func) bt_ctf_field_type_copy);
3dca2276 1150}
This page took 0.100568 seconds and 4 git commands to generate.