test_ctf_writer.c: set PACKET_RESIZE_TEST_LENGTH to 100000 again
[babeltrace.git] / lib / ctf-ir / stream-class.c
CommitLineData
11b0cdc8 1/*
3f043b05 2 * stream-class.c
11b0cdc8 3 *
d2dc44b6 4 * Babeltrace CTF IR - Stream Class
11b0cdc8 5 *
de9dd397 6 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
11b0cdc8
JG
7 *
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
d2f71f12
PP
29#define BT_LOG_TAG "STREAM-CLASS"
30#include <babeltrace/lib-logging-internal.h>
31
11b0cdc8 32#include <babeltrace/ctf-writer/clock.h>
ac0c6bdd
PP
33#include <babeltrace/ctf-writer/clock-internal.h>
34#include <babeltrace/ctf-ir/clock-class-internal.h>
11b0cdc8 35#include <babeltrace/ctf-writer/event.h>
272df73e 36#include <babeltrace/ctf-ir/event-class-internal.h>
11b0cdc8 37#include <babeltrace/ctf-ir/event-internal.h>
2e33ac5a
PP
38#include <babeltrace/ctf-ir/field-types-internal.h>
39#include <babeltrace/ctf-ir/fields-internal.h>
11b0cdc8
JG
40#include <babeltrace/ctf-writer/stream.h>
41#include <babeltrace/ctf-ir/stream-class-internal.h>
09840de5 42#include <babeltrace/ctf-ir/validation-internal.h>
8bf65fbd 43#include <babeltrace/ctf-ir/visitor-internal.h>
11b0cdc8 44#include <babeltrace/ctf-writer/functor-internal.h>
654c1444 45#include <babeltrace/ctf-ir/utils.h>
83509119 46#include <babeltrace/ref.h>
3d9990ac
PP
47#include <babeltrace/compiler-internal.h>
48#include <babeltrace/align-internal.h>
49#include <babeltrace/endian-internal.h>
dc3fffef 50#include <inttypes.h>
544d0515 51#include <stdint.h>
e011d2c1 52#include <stdbool.h>
11b0cdc8
JG
53
54static
83509119 55void bt_ctf_stream_class_destroy(struct bt_object *obj);
11b0cdc8 56static
662e778c 57int init_event_header(struct bt_ctf_stream_class *stream_class);
11b0cdc8 58static
662e778c 59int init_packet_context(struct bt_ctf_stream_class *stream_class);
11b0cdc8
JG
60
61struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *name)
62{
d2f71f12 63 struct bt_ctf_stream_class *stream_class;
12c8a1a3 64 int ret;
e0e2946b 65
d2f71f12
PP
66 BT_LOGD("Creating default stream class object: name=\"%s\"", name);
67 stream_class = bt_ctf_stream_class_create_empty(name);
e0e2946b 68 if (!stream_class) {
d2f71f12 69 BT_LOGD_STR("Cannot create empty stream class.");
e0e2946b
PP
70 goto error;
71 }
72
73 ret = init_event_header(stream_class);
74 if (ret) {
d2f71f12 75 BT_LOGE_STR("Cannot initialize stream class's event header field type.");
e0e2946b
PP
76 goto error;
77 }
78
79 ret = init_packet_context(stream_class);
80 if (ret) {
d2f71f12 81 BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
e0e2946b
PP
82 goto error;
83 }
84
d2f71f12
PP
85 BT_LOGD("Created default stream class object: addr=%p, name=\"%s\"",
86 stream_class, name);
e0e2946b
PP
87 return stream_class;
88
89error:
90 BT_PUT(stream_class);
91 return stream_class;
92}
93
94struct bt_ctf_stream_class *bt_ctf_stream_class_create_empty(const char *name)
95{
11b0cdc8
JG
96 struct bt_ctf_stream_class *stream_class = NULL;
97
d2f71f12
PP
98 BT_LOGD("Creating empty stream class object: name=\"%s\"", name);
99
11b0cdc8
JG
100 stream_class = g_new0(struct bt_ctf_stream_class, 1);
101 if (!stream_class) {
d2f71f12 102 BT_LOGE_STR("Failed to allocate one stream class.");
11b0cdc8
JG
103 goto error;
104 }
105
106 stream_class->name = g_string_new(name);
107 stream_class->event_classes = g_ptr_array_new_with_free_func(
e6a8e8e4 108 (GDestroyNotify) bt_object_release);
11b0cdc8 109 if (!stream_class->event_classes) {
d2f71f12 110 BT_LOGE_STR("Failed to allocate a GPtrArray.");
83509119 111 goto error;
11b0cdc8
JG
112 }
113
0b9ce69f
JG
114 stream_class->event_classes_ht = g_hash_table_new_full(g_int64_hash,
115 g_int64_equal, g_free, NULL);
d2f71f12
PP
116 if (!stream_class->event_classes_ht) {
117 BT_LOGE_STR("Failed to allocate a GHashTable.");
118 goto error;
119 }
0b9ce69f 120
83509119 121 bt_object_init(stream_class, bt_ctf_stream_class_destroy);
d2f71f12
PP
122 BT_LOGD("Created empty stream class object: addr=%p, name=\"%s\"",
123 stream_class, name);
11b0cdc8
JG
124 return stream_class;
125
11b0cdc8 126error:
e0e2946b 127 BT_PUT(stream_class);
11b0cdc8
JG
128 return stream_class;
129}
130
142c5610
JG
131struct bt_ctf_trace *bt_ctf_stream_class_get_trace(
132 struct bt_ctf_stream_class *stream_class)
133{
dc3fffef
PP
134 return stream_class ?
135 bt_get(bt_ctf_stream_class_borrow_trace(stream_class)) :
136 NULL;
142c5610
JG
137}
138
69dc4535
JG
139const char *bt_ctf_stream_class_get_name(
140 struct bt_ctf_stream_class *stream_class)
141{
142 const char *name = NULL;
143
144 if (!stream_class) {
d2f71f12 145 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
69dc4535
JG
146 goto end;
147 }
148
149 name = stream_class->name->str;
150end:
151 return name;
152}
153
3ea33115
JG
154int bt_ctf_stream_class_set_name(struct bt_ctf_stream_class *stream_class,
155 const char *name)
156{
157 int ret = 0;
158
d2f71f12
PP
159 if (!stream_class) {
160 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
161 ret = -1;
162 goto end;
163 }
164
165 if (stream_class->frozen) {
166 BT_LOGW("Invalid parameter: stream class is frozen: "
167 "addr=%p, name=\"%s\", id=%" PRId64,
168 stream_class, bt_ctf_stream_class_get_name(stream_class),
169 bt_ctf_stream_class_get_id(stream_class));
3ea33115
JG
170 ret = -1;
171 goto end;
172 }
173
174 g_string_assign(stream_class->name, name);
d2f71f12
PP
175 BT_LOGV("Set stream class's name: "
176 "addr=%p, name=\"%s\", id=%" PRId64,
177 stream_class, bt_ctf_stream_class_get_name(stream_class),
178 bt_ctf_stream_class_get_id(stream_class));
3ea33115
JG
179end:
180 return ret;
181}
182
2f100782
JG
183struct bt_ctf_clock *bt_ctf_stream_class_get_clock(
184 struct bt_ctf_stream_class *stream_class)
185{
186 struct bt_ctf_clock *clock = NULL;
187
d2f71f12
PP
188 if (!stream_class) {
189 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
190 goto end;
191 }
192
193 if (!stream_class->clock) {
194 BT_LOGV("Stream class has no clock: "
195 "addr=%p, name=\"%s\", id=%" PRId64,
196 stream_class, bt_ctf_stream_class_get_name(stream_class),
197 bt_ctf_stream_class_get_id(stream_class));
2f100782
JG
198 goto end;
199 }
200
ac0c6bdd 201 clock = bt_get(stream_class->clock);
2f100782
JG
202end:
203 return clock;
204}
205
11b0cdc8
JG
206int bt_ctf_stream_class_set_clock(struct bt_ctf_stream_class *stream_class,
207 struct bt_ctf_clock *clock)
208{
209 int ret = 0;
eee752e5 210 struct bt_ctf_field_type *timestamp_field = NULL;
11b0cdc8 211
d2f71f12
PP
212 if (!stream_class || !clock) {
213 BT_LOGW("Invalid parameter: stream class or clock is NULL: "
214 "stream-class-addr=%p, clock-addr=%p",
215 stream_class, clock);
216 ret = -1;
217 goto end;
218 }
219
220 if (stream_class->frozen) {
221 BT_LOGW("Invalid parameter: stream class is frozen: "
222 "addr=%p, name=\"%s\", id=%" PRId64,
223 stream_class, bt_ctf_stream_class_get_name(stream_class),
224 bt_ctf_stream_class_get_id(stream_class));
11b0cdc8
JG
225 ret = -1;
226 goto end;
227 }
228
ac0c6bdd
PP
229 /* Replace the current clock of this stream class. */
230 bt_put(stream_class->clock);
231 stream_class->clock = bt_get(clock);
d2f71f12
PP
232 BT_LOGV("Set stream class's clock: "
233 "addr=%p, name=\"%s\", id=%" PRId64 ", "
234 "clock-addr=%p, clock-name=\"%s\"",
235 stream_class, bt_ctf_stream_class_get_name(stream_class),
236 bt_ctf_stream_class_get_id(stream_class),
237 stream_class->clock,
238 bt_ctf_clock_get_name(stream_class->clock));
11b0cdc8 239
11b0cdc8 240end:
ac0c6bdd 241 bt_put(timestamp_field);
11b0cdc8
JG
242 return ret;
243}
244
2f100782
JG
245int64_t bt_ctf_stream_class_get_id(struct bt_ctf_stream_class *stream_class)
246{
247 int64_t ret;
248
d2f71f12
PP
249 if (!stream_class) {
250 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
251 ret = (int64_t) -1;
252 goto end;
253 }
254
255 if (!stream_class->id_set) {
256 BT_LOGV("Stream class's ID is not set: addr=%p, name=\"%s\"",
257 stream_class,
258 bt_ctf_stream_class_get_name(stream_class));
9ac68eb1 259 ret = (int64_t) -1;
2f100782
JG
260 goto end;
261 }
262
9ac68eb1 263 ret = stream_class->id;
2f100782
JG
264end:
265 return ret;
266}
267
5ca83563 268BT_HIDDEN
d2f71f12 269void _bt_ctf_stream_class_set_id(
9ac68eb1 270 struct bt_ctf_stream_class *stream_class, int64_t id)
5ca83563 271{
d2f71f12 272 assert(stream_class);
5ca83563
JG
273 stream_class->id = id;
274 stream_class->id_set = 1;
d2f71f12
PP
275 BT_LOGV("Set stream class's ID (internal): "
276 "addr=%p, name=\"%s\", id=%" PRId64,
277 stream_class, bt_ctf_stream_class_get_name(stream_class),
278 bt_ctf_stream_class_get_id(stream_class));
5ca83563
JG
279}
280
9ac68eb1
PP
281struct event_class_set_stream_class_id_data {
282 int64_t stream_class_id;
29664b2a
PP
283 int ret;
284};
285
29664b2a
PP
286BT_HIDDEN
287int bt_ctf_stream_class_set_id_no_check(
9ac68eb1 288 struct bt_ctf_stream_class *stream_class, int64_t id)
2f100782 289{
d2f71f12 290 _bt_ctf_stream_class_set_id(stream_class, id);
cf76ce92 291 return 0;
2f100782
JG
292}
293
29664b2a 294int bt_ctf_stream_class_set_id(struct bt_ctf_stream_class *stream_class,
9ac68eb1 295 uint64_t id_param)
29664b2a
PP
296{
297 int ret = 0;
9ac68eb1 298 int64_t id = (int64_t) id_param;
29664b2a 299
d2f71f12
PP
300 if (!stream_class) {
301 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
302 ret = -1;
303 goto end;
304 }
305
306 if (stream_class->frozen) {
307 BT_LOGW("Invalid parameter: stream class is frozen: "
308 "addr=%p, name=\"%s\", id=%" PRId64,
309 stream_class, bt_ctf_stream_class_get_name(stream_class),
310 bt_ctf_stream_class_get_id(stream_class));
311 ret = -1;
312 goto end;
313 }
314
315 if (id < 0) {
316 BT_LOGW("Invalid parameter: invalid stream class's ID: "
317 "stream-class-addr=%p, stream-class-name=\"%s\", "
318 "stream-class-id=%" PRId64 ", id=%" PRIu64,
319 stream_class, bt_ctf_stream_class_get_name(stream_class),
320 bt_ctf_stream_class_get_id(stream_class),
321 id_param);
29664b2a
PP
322 ret = -1;
323 goto end;
324 }
325
326 ret = bt_ctf_stream_class_set_id_no_check(stream_class, id);
d2f71f12
PP
327 if (ret == 0) {
328 BT_LOGV("Set stream class's ID: "
329 "addr=%p, name=\"%s\", id=%" PRId64,
330 stream_class, bt_ctf_stream_class_get_name(stream_class),
331 bt_ctf_stream_class_get_id(stream_class));
332 }
29664b2a
PP
333end:
334 return ret;
335}
336
0d23acbe
PP
337static
338void event_class_exists(gpointer element, gpointer query)
339{
340 struct bt_ctf_event_class *event_class_a = element;
341 struct search_query *search_query = query;
342 struct bt_ctf_event_class *event_class_b = search_query->value;
343 int64_t id_a, id_b;
344
345 if (search_query->value == element) {
346 search_query->found = 1;
347 goto end;
348 }
349
0d23acbe
PP
350 /*
351 * Two event classes cannot share the same ID in a given
352 * stream class.
353 */
354 id_a = bt_ctf_event_class_get_id(event_class_a);
355 id_b = bt_ctf_event_class_get_id(event_class_b);
356
357 if (id_a < 0 || id_b < 0) {
358 /* at least one ID is not set: will be automatically set later */
359 goto end;
360 }
361
362 if (id_a == id_b) {
66871d36 363 BT_LOGW("Event class with this ID already exists in the stream class: "
d2f71f12
PP
364 "id=%" PRId64 ", name=\"%s\"",
365 id_a, bt_ctf_event_class_get_name(event_class_a));
0d23acbe
PP
366 search_query->found = 1;
367 goto end;
368 }
369
370end:
371 return;
372}
373
11b0cdc8
JG
374int bt_ctf_stream_class_add_event_class(
375 struct bt_ctf_stream_class *stream_class,
376 struct bt_ctf_event_class *event_class)
377{
378 int ret = 0;
0b9ce69f 379 int64_t *event_id = NULL;
e6a8e8e4
JG
380 struct bt_ctf_trace *trace = NULL;
381 struct bt_ctf_stream_class *old_stream_class = NULL;
09840de5
PP
382 struct bt_ctf_validation_output validation_output = { 0 };
383 struct bt_ctf_field_type *packet_header_type = NULL;
384 struct bt_ctf_field_type *packet_context_type = NULL;
385 struct bt_ctf_field_type *event_header_type = NULL;
386 struct bt_ctf_field_type *stream_event_ctx_type = NULL;
387 struct bt_ctf_field_type *event_context_type = NULL;
388 struct bt_ctf_field_type *event_payload_type = NULL;
389 const enum bt_ctf_validation_flag validation_flags =
390 BT_CTF_VALIDATION_FLAG_EVENT;
11b0cdc8 391
e011d2c1
PP
392 if (!stream_class || !event_class) {
393 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
394 "stream-class-addr=%p, event-class-addr=%p",
395 stream_class, event_class);
396 ret = -1;
397 goto end;
398 }
399
d2f71f12
PP
400 BT_LOGD("Adding event class to stream class: "
401 "stream-class-addr=%p, stream-class-name=\"%s\", "
402 "stream-class-id=%" PRId64 ", event-class-addr=%p, "
403 "event-class-name=\"%s\", event-class-id=%" PRId64,
404 stream_class, bt_ctf_stream_class_get_name(stream_class),
405 bt_ctf_stream_class_get_id(stream_class),
406 event_class,
407 bt_ctf_event_class_get_name(event_class),
408 bt_ctf_event_class_get_id(event_class));
409
5acf2ae6
PP
410 trace = bt_ctf_stream_class_get_trace(stream_class);
411 if (trace && trace->is_static) {
412 ret = -1;
413 goto end;
414 }
415
0b9ce69f
JG
416 event_id = g_new(int64_t, 1);
417 if (!event_id) {
d2f71f12 418 BT_LOGE_STR("Failed to allocate one int64_t.");
0b9ce69f
JG
419 ret = -1;
420 goto end;
421 }
422
11b0cdc8
JG
423 /* Check for duplicate event classes */
424 struct search_query query = { .value = event_class, .found = 0 };
0d23acbe
PP
425 g_ptr_array_foreach(stream_class->event_classes, event_class_exists,
426 &query);
11b0cdc8 427 if (query.found) {
d2f71f12 428 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
11b0cdc8
JG
429 ret = -1;
430 goto end;
431 }
432
09840de5 433 old_stream_class = bt_ctf_event_class_get_stream_class(event_class);
e6a8e8e4
JG
434 if (old_stream_class) {
435 /* Event class is already associated to a stream class. */
d2f71f12
PP
436 BT_LOGW("Event class is already part of another stream class: "
437 "event-class-stream-class-addr=%p, "
438 "event-class-stream-class-name=\"%s\", "
439 "event-class-stream-class-id=%" PRId64,
440 old_stream_class,
441 bt_ctf_stream_class_get_name(old_stream_class),
442 bt_ctf_stream_class_get_id(old_stream_class));
e6a8e8e4
JG
443 ret = -1;
444 goto end;
445 }
446
e6a8e8e4 447 if (trace) {
09840de5
PP
448 /*
449 * If the stream class is associated with a trace, then
450 * both those objects are frozen. Also, this event class
451 * is about to be frozen.
452 *
453 * Therefore the event class must be validated here.
454 * The trace and stream class should be valid at this
455 * point.
456 */
457 assert(trace->valid);
458 assert(stream_class->valid);
459 packet_header_type =
460 bt_ctf_trace_get_packet_header_type(trace);
461 packet_context_type =
462 bt_ctf_stream_class_get_packet_context_type(
463 stream_class);
464 event_header_type =
465 bt_ctf_stream_class_get_event_header_type(stream_class);
466 stream_event_ctx_type =
467 bt_ctf_stream_class_get_event_context_type(
468 stream_class);
469 event_context_type =
470 bt_ctf_event_class_get_context_type(event_class);
471 event_payload_type =
472 bt_ctf_event_class_get_payload_type(event_class);
473 ret = bt_ctf_validate_class_types(
474 trace->environment, packet_header_type,
475 packet_context_type, event_header_type,
476 stream_event_ctx_type, event_context_type,
477 event_payload_type, trace->valid,
478 stream_class->valid, event_class->valid,
479 &validation_output, validation_flags);
480 BT_PUT(packet_header_type);
481 BT_PUT(packet_context_type);
482 BT_PUT(event_header_type);
483 BT_PUT(stream_event_ctx_type);
484 BT_PUT(event_context_type);
485 BT_PUT(event_payload_type);
486
26079216 487 if (ret) {
09840de5
PP
488 /*
489 * This means something went wrong during the
490 * validation process, not that the objects are
491 * invalid.
492 */
d2f71f12 493 BT_LOGE("Failed to validate event class: ret=%d", ret);
09840de5
PP
494 goto end;
495 }
496
497 if ((validation_output.valid_flags & validation_flags) !=
498 validation_flags) {
499 /* Invalid event class */
66871d36 500 BT_LOGW("Invalid trace, stream class, or event class: "
d2f71f12
PP
501 "valid-flags=0x%x",
502 validation_output.valid_flags);
09840de5 503 ret = -1;
26079216
JG
504 goto end;
505 }
506 }
507
09840de5 508 /* Only set an event ID if none was explicitly set before */
0b9ce69f 509 *event_id = bt_ctf_event_class_get_id(event_class);
24626e8b 510 if (*event_id < 0) {
d2f71f12
PP
511 BT_LOGV("Event class has no ID: automatically setting it: "
512 "id=%" PRId64, stream_class->next_event_id);
513
2f100782 514 if (bt_ctf_event_class_set_id(event_class,
d2f71f12
PP
515 stream_class->next_event_id)) {
516 BT_LOGE("Cannot set event class's ID: id=%" PRId64,
517 stream_class->next_event_id);
2f100782
JG
518 ret = -1;
519 goto end;
520 }
d2f71f12 521 stream_class->next_event_id++;
0b9ce69f 522 *event_id = stream_class->next_event_id;
2f100782
JG
523 }
524
e6a8e8e4 525 bt_object_set_parent(event_class, stream_class);
09840de5
PP
526
527 if (trace) {
528 /*
529 * At this point we know that the function will be
530 * successful. Therefore we can replace the event
531 * class's field types with what's in the validation
532 * output structure and mark this event class as valid.
533 */
534 bt_ctf_validation_replace_types(NULL, NULL, event_class,
535 &validation_output, validation_flags);
536 event_class->valid = 1;
537
538 /*
539 * Put what was not moved in
540 * bt_ctf_validation_replace_types().
541 */
542 bt_ctf_validation_output_put_types(&validation_output);
543 }
544
545 /* Add to the event classes of the stream class */
11b0cdc8 546 g_ptr_array_add(stream_class->event_classes, event_class);
0b9ce69f
JG
547 g_hash_table_insert(stream_class->event_classes_ht, event_id,
548 event_class);
549 event_id = NULL;
09840de5
PP
550
551 /* Freeze the event class */
58203827 552 bt_ctf_event_class_freeze(event_class);
5ca83563 553
9b888ff3
JG
554 /* Notifiy listeners of the trace's schema modification. */
555 if (trace) {
d9a13d86
PP
556 struct bt_ctf_object obj = { .object = event_class,
557 .type = BT_CTF_OBJECT_TYPE_EVENT_CLASS };
9b888ff3 558
d9a13d86 559 (void) bt_ctf_trace_object_modification(&obj, trace);
9b888ff3 560 }
d2f71f12
PP
561
562 BT_LOGD("Added event class to stream class: "
563 "stream-class-addr=%p, stream-class-name=\"%s\", "
564 "stream-class-id=%" PRId64 ", event-class-addr=%p, "
565 "event-class-name=\"%s\", event-class-id=%" PRId64,
566 stream_class, bt_ctf_stream_class_get_name(stream_class),
567 bt_ctf_stream_class_get_id(stream_class),
568 event_class,
569 bt_ctf_event_class_get_name(event_class),
570 bt_ctf_event_class_get_id(event_class));
571
11b0cdc8 572end:
e6a8e8e4
JG
573 BT_PUT(trace);
574 BT_PUT(old_stream_class);
09840de5
PP
575 bt_ctf_validation_output_put_types(&validation_output);
576 assert(!packet_header_type);
577 assert(!packet_context_type);
578 assert(!event_header_type);
579 assert(!stream_event_ctx_type);
580 assert(!event_context_type);
581 assert(!event_payload_type);
0b9ce69f 582 g_free(event_id);
09840de5 583
11b0cdc8
JG
584 return ret;
585}
586
544d0515 587int64_t bt_ctf_stream_class_get_event_class_count(
69dc4535
JG
588 struct bt_ctf_stream_class *stream_class)
589{
544d0515 590 int64_t ret;
69dc4535
JG
591
592 if (!stream_class) {
d2f71f12 593 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
9ac68eb1 594 ret = (int64_t) -1;
69dc4535
JG
595 goto end;
596 }
597
9ac68eb1 598 ret = (int64_t) stream_class->event_classes->len;
69dc4535
JG
599end:
600 return ret;
601}
602
9ac68eb1
PP
603struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_index(
604 struct bt_ctf_stream_class *stream_class, uint64_t index)
69dc4535
JG
605{
606 struct bt_ctf_event_class *event_class = NULL;
607
d2f71f12
PP
608 if (!stream_class) {
609 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
610 goto end;
611 }
612
613 if (index >= stream_class->event_classes->len) {
614 BT_LOGW("Invalid parameter: index is out of bounds: "
615 "addr=%p, name=\"%s\", id=%" PRId64 ", "
616 "index=%" PRIu64 ", count=%u",
617 stream_class, bt_ctf_stream_class_get_name(stream_class),
618 bt_ctf_stream_class_get_id(stream_class),
619 index, stream_class->event_classes->len);
69dc4535
JG
620 goto end;
621 }
622
623 event_class = g_ptr_array_index(stream_class->event_classes, index);
83509119 624 bt_get(event_class);
69dc4535
JG
625end:
626 return event_class;
627}
628
0863f950 629struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_id(
9ac68eb1 630 struct bt_ctf_stream_class *stream_class, uint64_t id)
0863f950 631{
9ac68eb1 632 int64_t id_key = (int64_t) id;
0863f950
PP
633 struct bt_ctf_event_class *event_class = NULL;
634
d2f71f12
PP
635 if (!stream_class) {
636 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
637 goto end;
638 }
639
640 if (id_key < 0) {
641 BT_LOGW("Invalid parameter: invalid event class's ID: "
642 "stream-class-addr=%p, stream-class-name=\"%s\", "
643 "stream-class-id=%" PRId64 ", event-class-id=%" PRIu64,
644 stream_class,
645 bt_ctf_stream_class_get_name(stream_class),
646 bt_ctf_stream_class_get_id(stream_class), id);
0863f950
PP
647 goto end;
648 }
649
0b9ce69f
JG
650 event_class = g_hash_table_lookup(stream_class->event_classes_ht,
651 &id_key);
652 bt_get(event_class);
0863f950
PP
653end:
654 return event_class;
655}
656
12c8a1a3
JG
657struct bt_ctf_field_type *bt_ctf_stream_class_get_packet_context_type(
658 struct bt_ctf_stream_class *stream_class)
659{
660 struct bt_ctf_field_type *ret = NULL;
661
662 if (!stream_class) {
d2f71f12 663 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
12c8a1a3
JG
664 goto end;
665 }
666
83509119 667 bt_get(stream_class->packet_context_type);
12c8a1a3
JG
668 ret = stream_class->packet_context_type;
669end:
670 return ret;
671}
672
673int bt_ctf_stream_class_set_packet_context_type(
674 struct bt_ctf_stream_class *stream_class,
675 struct bt_ctf_field_type *packet_context_type)
676{
677 int ret = 0;
678
d2f71f12
PP
679 if (!stream_class) {
680 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
681 ret = -1;
682 goto end;
683 }
684
685 if (stream_class->frozen) {
686 BT_LOGW("Invalid parameter: stream class is frozen: "
687 "addr=%p, name=\"%s\", id=%" PRId64,
688 stream_class, bt_ctf_stream_class_get_name(stream_class),
689 bt_ctf_stream_class_get_id(stream_class));
12c8a1a3
JG
690 ret = -1;
691 goto end;
692 }
693
835b2d10
JG
694 if (packet_context_type &&
695 bt_ctf_field_type_get_type_id(packet_context_type) !=
1487a16a 696 BT_CTF_FIELD_TYPE_ID_STRUCT) {
835b2d10 697 /* A packet context must be a structure. */
d2f71f12
PP
698 BT_LOGW("Invalid parameter: stream class's packet context field type must be a structure: "
699 "addr=%p, name=\"%s\", id=%" PRId64 ", "
700 "packet-context-ft-addr=%p, packet-context-ft-id=%s",
701 stream_class, bt_ctf_stream_class_get_name(stream_class),
702 bt_ctf_stream_class_get_id(stream_class),
703 packet_context_type,
704 bt_ctf_field_type_id_string(
705 bt_ctf_field_type_get_type_id(packet_context_type)));
12c8a1a3
JG
706 ret = -1;
707 goto end;
708 }
709
83509119
JG
710 bt_put(stream_class->packet_context_type);
711 bt_get(packet_context_type);
12c8a1a3 712 stream_class->packet_context_type = packet_context_type;
d2f71f12
PP
713 BT_LOGV("Set stream class's packet context field type: "
714 "addr=%p, name=\"%s\", id=%" PRId64 ", "
715 "packet-context-ft-addr=%p",
716 stream_class, bt_ctf_stream_class_get_name(stream_class),
717 bt_ctf_stream_class_get_id(stream_class),
718 packet_context_type);
719
12c8a1a3
JG
720end:
721 return ret;
722}
723
662e778c
JG
724struct bt_ctf_field_type *bt_ctf_stream_class_get_event_header_type(
725 struct bt_ctf_stream_class *stream_class)
726{
727 struct bt_ctf_field_type *ret = NULL;
728
d2f71f12
PP
729 if (!stream_class) {
730 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
731 goto end;
732 }
733
734 if (!stream_class->event_header_type) {
735 BT_LOGV("Stream class has no event header field type: "
736 "addr=%p, name=\"%s\", id=%" PRId64,
737 stream_class, bt_ctf_stream_class_get_name(stream_class),
738 bt_ctf_stream_class_get_id(stream_class));
662e778c
JG
739 goto end;
740 }
741
83509119 742 bt_get(stream_class->event_header_type);
662e778c
JG
743 ret = stream_class->event_header_type;
744end:
745 return ret;
746}
747
748int bt_ctf_stream_class_set_event_header_type(
749 struct bt_ctf_stream_class *stream_class,
750 struct bt_ctf_field_type *event_header_type)
751{
752 int ret = 0;
753
d2f71f12
PP
754 if (!stream_class) {
755 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
756 ret = -1;
757 goto end;
758 }
759
760 if (stream_class->frozen) {
761 BT_LOGW("Invalid parameter: stream class is frozen: "
762 "addr=%p, name=\"%s\", id=%" PRId64,
763 stream_class, bt_ctf_stream_class_get_name(stream_class),
764 bt_ctf_stream_class_get_id(stream_class));
662e778c
JG
765 ret = -1;
766 goto end;
767 }
768
835b2d10
JG
769 if (event_header_type &&
770 bt_ctf_field_type_get_type_id(event_header_type) !=
1487a16a 771 BT_CTF_FIELD_TYPE_ID_STRUCT) {
835b2d10 772 /* An event header must be a structure. */
d2f71f12
PP
773 BT_LOGW("Invalid parameter: stream class's event header field type must be a structure: "
774 "addr=%p, name=\"%s\", id=%" PRId64 ", "
775 "event-header-ft-addr=%p, event-header-ft-id=%s",
776 stream_class, bt_ctf_stream_class_get_name(stream_class),
777 bt_ctf_stream_class_get_id(stream_class),
778 event_header_type,
779 bt_ctf_field_type_id_string(
780 bt_ctf_field_type_get_type_id(event_header_type)));
662e778c
JG
781 ret = -1;
782 goto end;
783 }
784
83509119 785 bt_put(stream_class->event_header_type);
835b2d10 786 stream_class->event_header_type = bt_get(event_header_type);
d2f71f12
PP
787 BT_LOGV("Set stream class's event header field type: "
788 "addr=%p, name=\"%s\", id=%" PRId64 ", "
789 "event-header-ft-addr=%p",
790 stream_class, bt_ctf_stream_class_get_name(stream_class),
791 bt_ctf_stream_class_get_id(stream_class),
792 event_header_type);
662e778c
JG
793end:
794 return ret;
795}
796
af181248
JG
797struct bt_ctf_field_type *bt_ctf_stream_class_get_event_context_type(
798 struct bt_ctf_stream_class *stream_class)
799{
800 struct bt_ctf_field_type *ret = NULL;
801
d2f71f12
PP
802 if (!stream_class) {
803 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
804 goto end;
805 }
806
807 if (!stream_class->event_context_type) {
af181248
JG
808 goto end;
809 }
810
83509119 811 bt_get(stream_class->event_context_type);
af181248
JG
812 ret = stream_class->event_context_type;
813end:
814 return ret;
815}
816
817int bt_ctf_stream_class_set_event_context_type(
818 struct bt_ctf_stream_class *stream_class,
819 struct bt_ctf_field_type *event_context_type)
820{
821 int ret = 0;
822
d2f71f12
PP
823 if (!stream_class) {
824 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
825 ret = -1;
826 goto end;
827 }
828
829 if (stream_class->frozen) {
830 BT_LOGW("Invalid parameter: stream class is frozen: "
831 "addr=%p, name=\"%s\", id=%" PRId64,
832 stream_class, bt_ctf_stream_class_get_name(stream_class),
833 bt_ctf_stream_class_get_id(stream_class));
af181248
JG
834 ret = -1;
835 goto end;
836 }
837
835b2d10
JG
838 if (event_context_type &&
839 bt_ctf_field_type_get_type_id(event_context_type) !=
1487a16a 840 BT_CTF_FIELD_TYPE_ID_STRUCT) {
835b2d10 841 /* A packet context must be a structure. */
d2f71f12
PP
842 BT_LOGW("Invalid parameter: stream class's event context field type must be a structure: "
843 "addr=%p, name=\"%s\", id=%" PRId64 ", "
844 "event-context-ft-addr=%p, event-context-ft-id=%s",
845 stream_class, bt_ctf_stream_class_get_name(stream_class),
846 bt_ctf_stream_class_get_id(stream_class),
847 event_context_type,
848 bt_ctf_field_type_id_string(
849 bt_ctf_field_type_get_type_id(event_context_type)));
af181248
JG
850 ret = -1;
851 goto end;
852 }
853
83509119 854 bt_put(stream_class->event_context_type);
835b2d10 855 stream_class->event_context_type = bt_get(event_context_type);
d2f71f12
PP
856 BT_LOGV("Set stream class's event context field type: "
857 "addr=%p, name=\"%s\", id=%" PRId64 ", "
858 "event-context-ft-addr=%p",
859 stream_class, bt_ctf_stream_class_get_name(stream_class),
860 bt_ctf_stream_class_get_id(stream_class),
861 event_context_type);
af181248
JG
862end:
863 return ret;
864}
865
d2f71f12 866/* Pre-2.0 CTF writer backward compatibility */
11b0cdc8
JG
867void bt_ctf_stream_class_get(struct bt_ctf_stream_class *stream_class)
868{
83509119 869 bt_get(stream_class);
11b0cdc8
JG
870}
871
d2f71f12 872/* Pre-2.0 CTF writer backward compatibility */
11b0cdc8
JG
873void bt_ctf_stream_class_put(struct bt_ctf_stream_class *stream_class)
874{
83509119 875 bt_put(stream_class);
11b0cdc8
JG
876}
877
8bf65fbd 878static
544d0515 879int64_t get_event_class_count(void *element)
8bf65fbd
JG
880{
881 return bt_ctf_stream_class_get_event_class_count(
882 (struct bt_ctf_stream_class *) element);
883}
884
885static
886void *get_event_class(void *element, int i)
887{
9ac68eb1 888 return bt_ctf_stream_class_get_event_class_by_index(
8bf65fbd
JG
889 (struct bt_ctf_stream_class *) element, i);
890}
891
892static
d9a13d86 893int visit_event_class(void *object, bt_ctf_visitor visitor,void *data)
8bf65fbd 894{
d9a13d86
PP
895 struct bt_ctf_object obj =
896 { .object = object,
897 .type = BT_CTF_OBJECT_TYPE_EVENT_CLASS };
8bf65fbd 898
d9a13d86 899 return visitor(&obj, data);
8bf65fbd
JG
900}
901
902int bt_ctf_stream_class_visit(struct bt_ctf_stream_class *stream_class,
d9a13d86 903 bt_ctf_visitor visitor, void *data)
8bf65fbd
JG
904{
905 int ret;
d9a13d86
PP
906 struct bt_ctf_object obj =
907 { .object = stream_class,
908 .type = BT_CTF_OBJECT_TYPE_STREAM_CLASS };
8bf65fbd
JG
909
910 if (!stream_class || !visitor) {
d2f71f12
PP
911 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
912 "stream-class-addr=%p, visitor=%p",
913 stream_class, visitor);
8bf65fbd
JG
914 ret = -1;
915 goto end;
916 }
917
d9a13d86 918 ret = visitor_helper(&obj, get_event_class_count,
8bf65fbd
JG
919 get_event_class,
920 visit_event_class, visitor, data);
d2f71f12 921 BT_LOGV("visitor_helper() returned: ret=%d", ret);
8bf65fbd
JG
922end:
923 return ret;
924}
925
11b0cdc8
JG
926BT_HIDDEN
927void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class *stream_class)
928{
d2f71f12 929 if (!stream_class || stream_class->frozen) {
11b0cdc8
JG
930 return;
931 }
932
d2f71f12
PP
933 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64,
934 stream_class, bt_ctf_stream_class_get_name(stream_class),
935 bt_ctf_stream_class_get_id(stream_class));
11b0cdc8 936 stream_class->frozen = 1;
662e778c 937 bt_ctf_field_type_freeze(stream_class->event_header_type);
12c8a1a3 938 bt_ctf_field_type_freeze(stream_class->packet_context_type);
af181248 939 bt_ctf_field_type_freeze(stream_class->event_context_type);
ac0c6bdd
PP
940
941 if (stream_class->clock) {
942 bt_ctf_clock_class_freeze(stream_class->clock->clock_class);
943 }
11b0cdc8
JG
944}
945
11b0cdc8
JG
946BT_HIDDEN
947int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
948 struct metadata_context *context)
949{
9ac68eb1 950 int ret = 0;
11b0cdc8 951 size_t i;
6a5c98a5
JG
952 struct bt_ctf_trace *trace;
953 struct bt_ctf_field_type *packet_header_type = NULL;
11b0cdc8 954
d2f71f12
PP
955 BT_LOGD("Serializing stream class's metadata: "
956 "stream-class-addr=%p, stream-class-name=\"%s\", "
957 "stream-class-id=%" PRId64 ", metadata-context-addr=%p",
958 stream_class, bt_ctf_stream_class_get_name(stream_class),
959 bt_ctf_stream_class_get_id(stream_class), context);
11b0cdc8
JG
960 g_string_assign(context->field_name, "");
961 context->current_indentation_level = 1;
962 if (!stream_class->id_set) {
d2f71f12 963 BT_LOGW_STR("Stream class's ID is not set.");
11b0cdc8
JG
964 ret = -1;
965 goto end;
966 }
967
6a5c98a5
JG
968 g_string_append(context->string, "stream {\n");
969
970 /*
971 * The reference to the trace is only borrowed since the
972 * serialization of the stream class might have been triggered
973 * by the trace's destruction. In such a case, the trace's
974 * reference count would, unexepectedly, go through the sequence
975 * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
976 * and serialization.
977 */
978 trace = bt_ctf_stream_class_borrow_trace(stream_class);
979 assert(trace);
980 packet_header_type = bt_ctf_trace_get_packet_header_type(trace);
981 trace = NULL;
982 if (packet_header_type) {
983 struct bt_ctf_field_type *stream_id_type;
984
985 stream_id_type =
986 bt_ctf_field_type_structure_get_field_type_by_name(
987 packet_header_type, "stream_id");
988 if (stream_id_type) {
989 /*
990 * Only set the stream's id if the trace's packet header
991 * contains a stream_id field. This field is only
992 * needed if the trace contains only one stream
993 * class.
994 */
995 g_string_append_printf(context->string,
996 "\tid = %" PRId64 ";\n", stream_class->id);
997 }
998 bt_put(stream_id_type);
999 }
e011d2c1
PP
1000 if (stream_class->event_header_type) {
1001 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
1002 g_string_append(context->string, "\tevent.header := ");
1003 ret = bt_ctf_field_type_serialize(stream_class->event_header_type,
1004 context);
1005 if (ret) {
1006 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
1007 "ret=%d", ret);
1008 goto end;
1009 }
1010 g_string_append(context->string, ";");
11b0cdc8
JG
1011 }
1012
e011d2c1 1013
98edd02c 1014 if (stream_class->packet_context_type) {
e011d2c1
PP
1015 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
1016 g_string_append(context->string, "\n\n\tpacket.context := ");
98edd02c
JG
1017 ret = bt_ctf_field_type_serialize(stream_class->packet_context_type,
1018 context);
1019 if (ret) {
66871d36 1020 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
d2f71f12 1021 "ret=%d", ret);
98edd02c
JG
1022 goto end;
1023 }
e011d2c1 1024 g_string_append(context->string, ";");
11b0cdc8
JG
1025 }
1026
1027 if (stream_class->event_context_type) {
e011d2c1
PP
1028 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
1029 g_string_append(context->string, "\n\n\tevent.context := ");
11b0cdc8
JG
1030 ret = bt_ctf_field_type_serialize(
1031 stream_class->event_context_type, context);
1032 if (ret) {
66871d36 1033 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
d2f71f12 1034 "ret=%d", ret);
11b0cdc8
JG
1035 goto end;
1036 }
e011d2c1 1037 g_string_append(context->string, ";");
11b0cdc8
JG
1038 }
1039
e011d2c1
PP
1040 g_string_append(context->string, "\n};\n\n");
1041
11b0cdc8
JG
1042 for (i = 0; i < stream_class->event_classes->len; i++) {
1043 struct bt_ctf_event_class *event_class =
1044 stream_class->event_classes->pdata[i];
1045
11b0cdc8
JG
1046 ret = bt_ctf_event_class_serialize(event_class, context);
1047 if (ret) {
66871d36 1048 BT_LOGW("Cannot serialize event class's metadata: "
d2f71f12
PP
1049 "event-class-addr=%p, event-class-name=\"%s\", "
1050 "event-class-id=%" PRId64,
1051 event_class,
1052 bt_ctf_event_class_get_name(event_class),
1053 bt_ctf_event_class_get_id(event_class));
11b0cdc8
JG
1054 goto end;
1055 }
1056 }
1057end:
6a5c98a5 1058 bt_put(packet_header_type);
11b0cdc8
JG
1059 context->current_indentation_level = 0;
1060 return ret;
1061}
1062
1063static
83509119 1064void bt_ctf_stream_class_destroy(struct bt_object *obj)
11b0cdc8
JG
1065{
1066 struct bt_ctf_stream_class *stream_class;
1067
83509119 1068 stream_class = container_of(obj, struct bt_ctf_stream_class, base);
d2f71f12
PP
1069 BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64,
1070 stream_class, bt_ctf_stream_class_get_name(stream_class),
1071 bt_ctf_stream_class_get_id(stream_class));
83509119 1072 bt_put(stream_class->clock);
11b0cdc8 1073
0b9ce69f
JG
1074 if (stream_class->event_classes_ht) {
1075 g_hash_table_destroy(stream_class->event_classes_ht);
1076 }
11b0cdc8 1077 if (stream_class->event_classes) {
8c8cb0f2 1078 BT_LOGD_STR("Destroying event classes.");
11b0cdc8
JG
1079 g_ptr_array_free(stream_class->event_classes, TRUE);
1080 }
1081
1082 if (stream_class->name) {
1083 g_string_free(stream_class->name, TRUE);
1084 }
1085
8c8cb0f2 1086 BT_LOGD_STR("Putting event header field type.");
83509119 1087 bt_put(stream_class->event_header_type);
8c8cb0f2 1088 BT_LOGD_STR("Putting packet context field type.");
83509119 1089 bt_put(stream_class->packet_context_type);
8c8cb0f2 1090 BT_LOGD_STR("Putting event context field type.");
83509119 1091 bt_put(stream_class->event_context_type);
11b0cdc8
JG
1092 g_free(stream_class);
1093}
1094
1095static
662e778c 1096int init_event_header(struct bt_ctf_stream_class *stream_class)
11b0cdc8
JG
1097{
1098 int ret = 0;
1099 struct bt_ctf_field_type *event_header_type =
1100 bt_ctf_field_type_structure_create();
1101 struct bt_ctf_field_type *_uint32_t =
1102 get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
1103 struct bt_ctf_field_type *_uint64_t =
1104 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
1105
1106 if (!event_header_type) {
d2f71f12 1107 BT_LOGE_STR("Cannot create empty structure field type.");
11b0cdc8
JG
1108 ret = -1;
1109 goto end;
1110 }
1111
11b0cdc8
JG
1112 ret = bt_ctf_field_type_structure_add_field(event_header_type,
1113 _uint32_t, "id");
1114 if (ret) {
d2f71f12 1115 BT_LOGE_STR("Cannot add `id` field to event header field type.");
11b0cdc8
JG
1116 goto end;
1117 }
1118
1119 ret = bt_ctf_field_type_structure_add_field(event_header_type,
1120 _uint64_t, "timestamp");
1121 if (ret) {
d2f71f12 1122 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
11b0cdc8
JG
1123 goto end;
1124 }
1125
e0e2946b 1126 BT_MOVE(stream_class->event_header_type, event_header_type);
11b0cdc8
JG
1127end:
1128 if (ret) {
83509119 1129 bt_put(event_header_type);
11b0cdc8
JG
1130 }
1131
83509119
JG
1132 bt_put(_uint32_t);
1133 bt_put(_uint64_t);
11b0cdc8
JG
1134 return ret;
1135}
1136
1137static
662e778c 1138int init_packet_context(struct bt_ctf_stream_class *stream_class)
11b0cdc8
JG
1139{
1140 int ret = 0;
1141 struct bt_ctf_field_type *packet_context_type =
1142 bt_ctf_field_type_structure_create();
1143 struct bt_ctf_field_type *_uint64_t =
1144 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
e011d2c1 1145 struct bt_ctf_field_type *ts_begin_end_uint64_t;
11b0cdc8
JG
1146
1147 if (!packet_context_type) {
d2f71f12 1148 BT_LOGE_STR("Cannot create empty structure field type.");
11b0cdc8
JG
1149 ret = -1;
1150 goto end;
1151 }
1152
e011d2c1
PP
1153 ts_begin_end_uint64_t = bt_ctf_field_type_copy(_uint64_t);
1154 if (!ts_begin_end_uint64_t) {
1155 BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
1156 ret = -1;
1157 goto end;
1158 }
1159
11b0cdc8
JG
1160 /*
1161 * We create a stream packet context as proposed in the CTF
1162 * specification.
1163 */
11b0cdc8 1164 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
e011d2c1 1165 ts_begin_end_uint64_t, "timestamp_begin");
11b0cdc8 1166 if (ret) {
d2f71f12 1167 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
11b0cdc8
JG
1168 goto end;
1169 }
1170
1171 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
e011d2c1 1172 ts_begin_end_uint64_t, "timestamp_end");
11b0cdc8 1173 if (ret) {
d2f71f12 1174 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
11b0cdc8
JG
1175 goto end;
1176 }
1177
1178 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
1179 _uint64_t, "content_size");
1180 if (ret) {
d2f71f12 1181 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
11b0cdc8
JG
1182 goto end;
1183 }
1184
1185 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
1186 _uint64_t, "packet_size");
1187 if (ret) {
d2f71f12 1188 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
11b0cdc8
JG
1189 goto end;
1190 }
1191
1192 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
1193 _uint64_t, "events_discarded");
1194 if (ret) {
d2f71f12 1195 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
11b0cdc8
JG
1196 goto end;
1197 }
1198
e0e2946b 1199 BT_MOVE(stream_class->packet_context_type, packet_context_type);
11b0cdc8
JG
1200end:
1201 if (ret) {
83509119 1202 bt_put(packet_context_type);
11b0cdc8
JG
1203 goto end;
1204 }
1205
83509119 1206 bt_put(_uint64_t);
e011d2c1
PP
1207 bt_put(ts_begin_end_uint64_t);
1208 return ret;
1209}
1210
1211static
1212int try_map_clock_class(struct bt_ctf_stream_class *stream_class,
1213 struct bt_ctf_field_type *ft)
1214{
1215 struct bt_ctf_clock_class *mapped_clock_class = NULL;
1216 int ret = 0;
1217
1218 if (!ft) {
1219 /* Field does not exist: not an error */
1220 goto end;
1221 }
1222
1223 assert(bt_ctf_field_type_is_integer(ft));
1224 mapped_clock_class =
1225 bt_ctf_field_type_integer_get_mapped_clock_class(ft);
1226 if (!mapped_clock_class) {
1227 if (!stream_class->clock) {
1228 BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
1229 "stream-class-addr=%p, stream-class-name=\"%s\", "
1230 "stream-class-id=%" PRId64 ", ft-addr=%p",
1231 stream_class, bt_ctf_stream_class_get_name(stream_class),
1232 bt_ctf_stream_class_get_id(stream_class), ft);
1233 ret = -1;
1234 goto end;
1235 }
1236
1237 ret = bt_ctf_field_type_integer_set_mapped_clock_class_no_check(
1238 ft, stream_class->clock->clock_class);
1239 if (ret) {
1240 BT_LOGW("Cannot set field type's mapped clock class: "
1241 "stream-class-addr=%p, stream-class-name=\"%s\", "
1242 "stream-class-id=%" PRId64 ", ft-addr=%p",
1243 stream_class, bt_ctf_stream_class_get_name(stream_class),
1244 bt_ctf_stream_class_get_id(stream_class), ft);
1245 goto end;
1246 }
1247
1248 BT_LOGV("Automatically mapped field type to stream class's clock class: "
1249 "stream-class-addr=%p, stream-class-name=\"%s\", "
1250 "stream-class-id=%" PRId64 ", ft-addr=%p",
1251 stream_class, bt_ctf_stream_class_get_name(stream_class),
1252 bt_ctf_stream_class_get_id(stream_class), ft);
1253 }
1254
1255end:
1256 bt_put(mapped_clock_class);
1257 return ret;
1258}
1259
1260BT_HIDDEN
1261int bt_ctf_stream_class_map_clock_class(
1262 struct bt_ctf_stream_class *stream_class,
1263 struct bt_ctf_field_type *packet_context_type,
1264 struct bt_ctf_field_type *event_header_type)
1265{
1266 struct bt_ctf_field_type *ft = NULL;
1267 int ret = 0;
1268
1269 assert(stream_class);
1270
1271 if (packet_context_type) {
1272 ft = bt_ctf_field_type_structure_get_field_type_by_name(
1273 packet_context_type, "timestamp_begin");
1274 if (try_map_clock_class(stream_class, ft)) {
1275 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
1276 ret = -1;
1277 goto end;
1278 }
1279
1280 bt_put(ft);
1281 ft = bt_ctf_field_type_structure_get_field_type_by_name(
1282 packet_context_type, "timestamp_end");
1283 if (try_map_clock_class(stream_class, ft)) {
1284 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
1285 ret = -1;
1286 goto end;
1287 }
1288
1289 BT_PUT(ft);
1290 }
1291
1292 if (event_header_type) {
1293 ft = bt_ctf_field_type_structure_get_field_type_by_name(
1294 event_header_type, "timestamp");
1295 if (try_map_clock_class(stream_class, ft)) {
1296 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
1297 ret = -1;
1298 goto end;
1299 }
1300
1301 BT_PUT(ft);
1302 }
1303
1304end:
11b0cdc8
JG
1305 return ret;
1306}
This page took 0.102258 seconds and 4 git commands to generate.