BT_CTF_BYTE_ORDER_NONE -> BT_CTF_BYTE_ORDER_UNSPECIFIED to match base
[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
286static
287void event_class_set_stream_id(gpointer event_class, gpointer data)
288{
9ac68eb1 289 struct event_class_set_stream_class_id_data *typed_data = data;
29664b2a
PP
290
291 typed_data->ret |= bt_ctf_event_class_set_stream_id(event_class,
9ac68eb1 292 typed_data->stream_class_id);
29664b2a
PP
293}
294
295BT_HIDDEN
296int bt_ctf_stream_class_set_id_no_check(
9ac68eb1 297 struct bt_ctf_stream_class *stream_class, int64_t id)
2f100782
JG
298{
299 int ret = 0;
9ac68eb1
PP
300 struct event_class_set_stream_class_id_data data =
301 { .stream_class_id = id, .ret = 0 };
2f100782 302
29664b2a
PP
303 /*
304 * Make sure all event classes have their "stream_id" attribute
305 * set to this value.
306 */
307 g_ptr_array_foreach(stream_class->event_classes,
308 event_class_set_stream_id, &data);
309 ret = data.ret;
310 if (ret) {
d2f71f12
PP
311 BT_LOGE("Cannot set the IDs of all stream class's event classes: "
312 "addr=%p, name=\"%s\", id=%" PRId64,
313 stream_class, bt_ctf_stream_class_get_name(stream_class),
314 bt_ctf_stream_class_get_id(stream_class));
2f100782
JG
315 goto end;
316 }
317
d2f71f12 318 _bt_ctf_stream_class_set_id(stream_class, id);
2f100782
JG
319end:
320 return ret;
321}
322
29664b2a 323int bt_ctf_stream_class_set_id(struct bt_ctf_stream_class *stream_class,
9ac68eb1 324 uint64_t id_param)
29664b2a
PP
325{
326 int ret = 0;
9ac68eb1 327 int64_t id = (int64_t) id_param;
29664b2a 328
d2f71f12
PP
329 if (!stream_class) {
330 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
331 ret = -1;
332 goto end;
333 }
334
335 if (stream_class->frozen) {
336 BT_LOGW("Invalid parameter: stream class is frozen: "
337 "addr=%p, name=\"%s\", id=%" PRId64,
338 stream_class, bt_ctf_stream_class_get_name(stream_class),
339 bt_ctf_stream_class_get_id(stream_class));
340 ret = -1;
341 goto end;
342 }
343
344 if (id < 0) {
345 BT_LOGW("Invalid parameter: invalid stream class's ID: "
346 "stream-class-addr=%p, stream-class-name=\"%s\", "
347 "stream-class-id=%" PRId64 ", id=%" PRIu64,
348 stream_class, bt_ctf_stream_class_get_name(stream_class),
349 bt_ctf_stream_class_get_id(stream_class),
350 id_param);
29664b2a
PP
351 ret = -1;
352 goto end;
353 }
354
355 ret = bt_ctf_stream_class_set_id_no_check(stream_class, id);
d2f71f12
PP
356 if (ret == 0) {
357 BT_LOGV("Set stream class's ID: "
358 "addr=%p, name=\"%s\", id=%" PRId64,
359 stream_class, bt_ctf_stream_class_get_name(stream_class),
360 bt_ctf_stream_class_get_id(stream_class));
361 }
29664b2a
PP
362end:
363 return ret;
364}
365
0d23acbe
PP
366static
367void event_class_exists(gpointer element, gpointer query)
368{
369 struct bt_ctf_event_class *event_class_a = element;
370 struct search_query *search_query = query;
371 struct bt_ctf_event_class *event_class_b = search_query->value;
372 int64_t id_a, id_b;
373
374 if (search_query->value == element) {
375 search_query->found = 1;
376 goto end;
377 }
378
0d23acbe
PP
379 /*
380 * Two event classes cannot share the same ID in a given
381 * stream class.
382 */
383 id_a = bt_ctf_event_class_get_id(event_class_a);
384 id_b = bt_ctf_event_class_get_id(event_class_b);
385
386 if (id_a < 0 || id_b < 0) {
387 /* at least one ID is not set: will be automatically set later */
388 goto end;
389 }
390
391 if (id_a == id_b) {
66871d36 392 BT_LOGW("Event class with this ID already exists in the stream class: "
d2f71f12
PP
393 "id=%" PRId64 ", name=\"%s\"",
394 id_a, bt_ctf_event_class_get_name(event_class_a));
0d23acbe
PP
395 search_query->found = 1;
396 goto end;
397 }
398
399end:
400 return;
401}
402
11b0cdc8
JG
403int bt_ctf_stream_class_add_event_class(
404 struct bt_ctf_stream_class *stream_class,
405 struct bt_ctf_event_class *event_class)
406{
407 int ret = 0;
0b9ce69f 408 int64_t *event_id = NULL;
e6a8e8e4
JG
409 struct bt_ctf_trace *trace = NULL;
410 struct bt_ctf_stream_class *old_stream_class = NULL;
09840de5
PP
411 struct bt_ctf_validation_output validation_output = { 0 };
412 struct bt_ctf_field_type *packet_header_type = NULL;
413 struct bt_ctf_field_type *packet_context_type = NULL;
414 struct bt_ctf_field_type *event_header_type = NULL;
415 struct bt_ctf_field_type *stream_event_ctx_type = NULL;
416 struct bt_ctf_field_type *event_context_type = NULL;
417 struct bt_ctf_field_type *event_payload_type = NULL;
418 const enum bt_ctf_validation_flag validation_flags =
419 BT_CTF_VALIDATION_FLAG_EVENT;
11b0cdc8 420
e011d2c1
PP
421 if (!stream_class || !event_class) {
422 BT_LOGW("Invalid parameter: stream class or event class is NULL: "
423 "stream-class-addr=%p, event-class-addr=%p",
424 stream_class, event_class);
425 ret = -1;
426 goto end;
427 }
428
d2f71f12
PP
429 BT_LOGD("Adding event class to stream class: "
430 "stream-class-addr=%p, stream-class-name=\"%s\", "
431 "stream-class-id=%" PRId64 ", event-class-addr=%p, "
432 "event-class-name=\"%s\", event-class-id=%" PRId64,
433 stream_class, bt_ctf_stream_class_get_name(stream_class),
434 bt_ctf_stream_class_get_id(stream_class),
435 event_class,
436 bt_ctf_event_class_get_name(event_class),
437 bt_ctf_event_class_get_id(event_class));
438
5acf2ae6
PP
439 trace = bt_ctf_stream_class_get_trace(stream_class);
440 if (trace && trace->is_static) {
441 ret = -1;
442 goto end;
443 }
444
0b9ce69f
JG
445 event_id = g_new(int64_t, 1);
446 if (!event_id) {
d2f71f12 447 BT_LOGE_STR("Failed to allocate one int64_t.");
0b9ce69f
JG
448 ret = -1;
449 goto end;
450 }
451
11b0cdc8
JG
452 /* Check for duplicate event classes */
453 struct search_query query = { .value = event_class, .found = 0 };
0d23acbe
PP
454 g_ptr_array_foreach(stream_class->event_classes, event_class_exists,
455 &query);
11b0cdc8 456 if (query.found) {
d2f71f12 457 BT_LOGW_STR("Another event class part of this stream class has the same ID.");
11b0cdc8
JG
458 ret = -1;
459 goto end;
460 }
461
09840de5 462 old_stream_class = bt_ctf_event_class_get_stream_class(event_class);
e6a8e8e4
JG
463 if (old_stream_class) {
464 /* Event class is already associated to a stream class. */
d2f71f12
PP
465 BT_LOGW("Event class is already part of another stream class: "
466 "event-class-stream-class-addr=%p, "
467 "event-class-stream-class-name=\"%s\", "
468 "event-class-stream-class-id=%" PRId64,
469 old_stream_class,
470 bt_ctf_stream_class_get_name(old_stream_class),
471 bt_ctf_stream_class_get_id(old_stream_class));
e6a8e8e4
JG
472 ret = -1;
473 goto end;
474 }
475
e6a8e8e4 476 if (trace) {
09840de5
PP
477 /*
478 * If the stream class is associated with a trace, then
479 * both those objects are frozen. Also, this event class
480 * is about to be frozen.
481 *
482 * Therefore the event class must be validated here.
483 * The trace and stream class should be valid at this
484 * point.
485 */
486 assert(trace->valid);
487 assert(stream_class->valid);
488 packet_header_type =
489 bt_ctf_trace_get_packet_header_type(trace);
490 packet_context_type =
491 bt_ctf_stream_class_get_packet_context_type(
492 stream_class);
493 event_header_type =
494 bt_ctf_stream_class_get_event_header_type(stream_class);
495 stream_event_ctx_type =
496 bt_ctf_stream_class_get_event_context_type(
497 stream_class);
498 event_context_type =
499 bt_ctf_event_class_get_context_type(event_class);
500 event_payload_type =
501 bt_ctf_event_class_get_payload_type(event_class);
502 ret = bt_ctf_validate_class_types(
503 trace->environment, packet_header_type,
504 packet_context_type, event_header_type,
505 stream_event_ctx_type, event_context_type,
506 event_payload_type, trace->valid,
507 stream_class->valid, event_class->valid,
508 &validation_output, validation_flags);
509 BT_PUT(packet_header_type);
510 BT_PUT(packet_context_type);
511 BT_PUT(event_header_type);
512 BT_PUT(stream_event_ctx_type);
513 BT_PUT(event_context_type);
514 BT_PUT(event_payload_type);
515
26079216 516 if (ret) {
09840de5
PP
517 /*
518 * This means something went wrong during the
519 * validation process, not that the objects are
520 * invalid.
521 */
d2f71f12 522 BT_LOGE("Failed to validate event class: ret=%d", ret);
09840de5
PP
523 goto end;
524 }
525
526 if ((validation_output.valid_flags & validation_flags) !=
527 validation_flags) {
528 /* Invalid event class */
66871d36 529 BT_LOGW("Invalid trace, stream class, or event class: "
d2f71f12
PP
530 "valid-flags=0x%x",
531 validation_output.valid_flags);
09840de5 532 ret = -1;
26079216
JG
533 goto end;
534 }
535 }
536
09840de5 537 /* Only set an event ID if none was explicitly set before */
0b9ce69f 538 *event_id = bt_ctf_event_class_get_id(event_class);
24626e8b 539 if (*event_id < 0) {
d2f71f12
PP
540 BT_LOGV("Event class has no ID: automatically setting it: "
541 "id=%" PRId64, stream_class->next_event_id);
542
2f100782 543 if (bt_ctf_event_class_set_id(event_class,
d2f71f12
PP
544 stream_class->next_event_id)) {
545 BT_LOGE("Cannot set event class's ID: id=%" PRId64,
546 stream_class->next_event_id);
2f100782
JG
547 ret = -1;
548 goto end;
549 }
d2f71f12 550 stream_class->next_event_id++;
0b9ce69f 551 *event_id = stream_class->next_event_id;
2f100782
JG
552 }
553
29664b2a
PP
554 ret = bt_ctf_event_class_set_stream_id(event_class, stream_class->id);
555 if (ret) {
d2f71f12
PP
556 BT_LOGE("Cannot set event class's stream class ID attribute: ret=%d",
557 ret);
29664b2a
PP
558 goto end;
559 }
560
e6a8e8e4 561 bt_object_set_parent(event_class, stream_class);
09840de5
PP
562
563 if (trace) {
564 /*
565 * At this point we know that the function will be
566 * successful. Therefore we can replace the event
567 * class's field types with what's in the validation
568 * output structure and mark this event class as valid.
569 */
570 bt_ctf_validation_replace_types(NULL, NULL, event_class,
571 &validation_output, validation_flags);
572 event_class->valid = 1;
573
574 /*
575 * Put what was not moved in
576 * bt_ctf_validation_replace_types().
577 */
578 bt_ctf_validation_output_put_types(&validation_output);
579 }
580
581 /* Add to the event classes of the stream class */
11b0cdc8 582 g_ptr_array_add(stream_class->event_classes, event_class);
0b9ce69f
JG
583 g_hash_table_insert(stream_class->event_classes_ht, event_id,
584 event_class);
585 event_id = NULL;
09840de5
PP
586
587 /* Freeze the event class */
58203827 588 bt_ctf_event_class_freeze(event_class);
5ca83563 589
9b888ff3
JG
590 /* Notifiy listeners of the trace's schema modification. */
591 if (trace) {
d9a13d86
PP
592 struct bt_ctf_object obj = { .object = event_class,
593 .type = BT_CTF_OBJECT_TYPE_EVENT_CLASS };
9b888ff3 594
d9a13d86 595 (void) bt_ctf_trace_object_modification(&obj, trace);
9b888ff3 596 }
d2f71f12
PP
597
598 BT_LOGD("Added event class to stream class: "
599 "stream-class-addr=%p, stream-class-name=\"%s\", "
600 "stream-class-id=%" PRId64 ", event-class-addr=%p, "
601 "event-class-name=\"%s\", event-class-id=%" PRId64,
602 stream_class, bt_ctf_stream_class_get_name(stream_class),
603 bt_ctf_stream_class_get_id(stream_class),
604 event_class,
605 bt_ctf_event_class_get_name(event_class),
606 bt_ctf_event_class_get_id(event_class));
607
11b0cdc8 608end:
e6a8e8e4
JG
609 BT_PUT(trace);
610 BT_PUT(old_stream_class);
09840de5
PP
611 bt_ctf_validation_output_put_types(&validation_output);
612 assert(!packet_header_type);
613 assert(!packet_context_type);
614 assert(!event_header_type);
615 assert(!stream_event_ctx_type);
616 assert(!event_context_type);
617 assert(!event_payload_type);
0b9ce69f 618 g_free(event_id);
09840de5 619
11b0cdc8
JG
620 return ret;
621}
622
544d0515 623int64_t bt_ctf_stream_class_get_event_class_count(
69dc4535
JG
624 struct bt_ctf_stream_class *stream_class)
625{
544d0515 626 int64_t ret;
69dc4535
JG
627
628 if (!stream_class) {
d2f71f12 629 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
9ac68eb1 630 ret = (int64_t) -1;
69dc4535
JG
631 goto end;
632 }
633
9ac68eb1 634 ret = (int64_t) stream_class->event_classes->len;
69dc4535
JG
635end:
636 return ret;
637}
638
9ac68eb1
PP
639struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_index(
640 struct bt_ctf_stream_class *stream_class, uint64_t index)
69dc4535
JG
641{
642 struct bt_ctf_event_class *event_class = NULL;
643
d2f71f12
PP
644 if (!stream_class) {
645 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
646 goto end;
647 }
648
649 if (index >= stream_class->event_classes->len) {
650 BT_LOGW("Invalid parameter: index is out of bounds: "
651 "addr=%p, name=\"%s\", id=%" PRId64 ", "
652 "index=%" PRIu64 ", count=%u",
653 stream_class, bt_ctf_stream_class_get_name(stream_class),
654 bt_ctf_stream_class_get_id(stream_class),
655 index, stream_class->event_classes->len);
69dc4535
JG
656 goto end;
657 }
658
659 event_class = g_ptr_array_index(stream_class->event_classes, index);
83509119 660 bt_get(event_class);
69dc4535
JG
661end:
662 return event_class;
663}
664
0863f950 665struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_id(
9ac68eb1 666 struct bt_ctf_stream_class *stream_class, uint64_t id)
0863f950 667{
9ac68eb1 668 int64_t id_key = (int64_t) id;
0863f950
PP
669 struct bt_ctf_event_class *event_class = NULL;
670
d2f71f12
PP
671 if (!stream_class) {
672 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
673 goto end;
674 }
675
676 if (id_key < 0) {
677 BT_LOGW("Invalid parameter: invalid event class's ID: "
678 "stream-class-addr=%p, stream-class-name=\"%s\", "
679 "stream-class-id=%" PRId64 ", event-class-id=%" PRIu64,
680 stream_class,
681 bt_ctf_stream_class_get_name(stream_class),
682 bt_ctf_stream_class_get_id(stream_class), id);
0863f950
PP
683 goto end;
684 }
685
0b9ce69f
JG
686 event_class = g_hash_table_lookup(stream_class->event_classes_ht,
687 &id_key);
688 bt_get(event_class);
0863f950
PP
689end:
690 return event_class;
691}
692
12c8a1a3
JG
693struct bt_ctf_field_type *bt_ctf_stream_class_get_packet_context_type(
694 struct bt_ctf_stream_class *stream_class)
695{
696 struct bt_ctf_field_type *ret = NULL;
697
698 if (!stream_class) {
d2f71f12 699 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
12c8a1a3
JG
700 goto end;
701 }
702
83509119 703 bt_get(stream_class->packet_context_type);
12c8a1a3
JG
704 ret = stream_class->packet_context_type;
705end:
706 return ret;
707}
708
709int bt_ctf_stream_class_set_packet_context_type(
710 struct bt_ctf_stream_class *stream_class,
711 struct bt_ctf_field_type *packet_context_type)
712{
713 int ret = 0;
714
d2f71f12
PP
715 if (!stream_class) {
716 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
717 ret = -1;
718 goto end;
719 }
720
721 if (stream_class->frozen) {
722 BT_LOGW("Invalid parameter: stream class is frozen: "
723 "addr=%p, name=\"%s\", id=%" PRId64,
724 stream_class, bt_ctf_stream_class_get_name(stream_class),
725 bt_ctf_stream_class_get_id(stream_class));
12c8a1a3
JG
726 ret = -1;
727 goto end;
728 }
729
835b2d10
JG
730 if (packet_context_type &&
731 bt_ctf_field_type_get_type_id(packet_context_type) !=
1487a16a 732 BT_CTF_FIELD_TYPE_ID_STRUCT) {
835b2d10 733 /* A packet context must be a structure. */
d2f71f12
PP
734 BT_LOGW("Invalid parameter: stream class's packet context field type must be a structure: "
735 "addr=%p, name=\"%s\", id=%" PRId64 ", "
736 "packet-context-ft-addr=%p, packet-context-ft-id=%s",
737 stream_class, bt_ctf_stream_class_get_name(stream_class),
738 bt_ctf_stream_class_get_id(stream_class),
739 packet_context_type,
740 bt_ctf_field_type_id_string(
741 bt_ctf_field_type_get_type_id(packet_context_type)));
12c8a1a3
JG
742 ret = -1;
743 goto end;
744 }
745
83509119
JG
746 bt_put(stream_class->packet_context_type);
747 bt_get(packet_context_type);
12c8a1a3 748 stream_class->packet_context_type = packet_context_type;
d2f71f12
PP
749 BT_LOGV("Set stream class's packet context field type: "
750 "addr=%p, name=\"%s\", id=%" PRId64 ", "
751 "packet-context-ft-addr=%p",
752 stream_class, bt_ctf_stream_class_get_name(stream_class),
753 bt_ctf_stream_class_get_id(stream_class),
754 packet_context_type);
755
12c8a1a3
JG
756end:
757 return ret;
758}
759
662e778c
JG
760struct bt_ctf_field_type *bt_ctf_stream_class_get_event_header_type(
761 struct bt_ctf_stream_class *stream_class)
762{
763 struct bt_ctf_field_type *ret = NULL;
764
d2f71f12
PP
765 if (!stream_class) {
766 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
767 goto end;
768 }
769
770 if (!stream_class->event_header_type) {
771 BT_LOGV("Stream class has no event header field type: "
772 "addr=%p, name=\"%s\", id=%" PRId64,
773 stream_class, bt_ctf_stream_class_get_name(stream_class),
774 bt_ctf_stream_class_get_id(stream_class));
662e778c
JG
775 goto end;
776 }
777
83509119 778 bt_get(stream_class->event_header_type);
662e778c
JG
779 ret = stream_class->event_header_type;
780end:
781 return ret;
782}
783
784int bt_ctf_stream_class_set_event_header_type(
785 struct bt_ctf_stream_class *stream_class,
786 struct bt_ctf_field_type *event_header_type)
787{
788 int ret = 0;
789
d2f71f12
PP
790 if (!stream_class) {
791 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
792 ret = -1;
793 goto end;
794 }
795
796 if (stream_class->frozen) {
797 BT_LOGW("Invalid parameter: stream class is frozen: "
798 "addr=%p, name=\"%s\", id=%" PRId64,
799 stream_class, bt_ctf_stream_class_get_name(stream_class),
800 bt_ctf_stream_class_get_id(stream_class));
662e778c
JG
801 ret = -1;
802 goto end;
803 }
804
835b2d10
JG
805 if (event_header_type &&
806 bt_ctf_field_type_get_type_id(event_header_type) !=
1487a16a 807 BT_CTF_FIELD_TYPE_ID_STRUCT) {
835b2d10 808 /* An event header must be a structure. */
d2f71f12
PP
809 BT_LOGW("Invalid parameter: stream class's event header field type must be a structure: "
810 "addr=%p, name=\"%s\", id=%" PRId64 ", "
811 "event-header-ft-addr=%p, event-header-ft-id=%s",
812 stream_class, bt_ctf_stream_class_get_name(stream_class),
813 bt_ctf_stream_class_get_id(stream_class),
814 event_header_type,
815 bt_ctf_field_type_id_string(
816 bt_ctf_field_type_get_type_id(event_header_type)));
662e778c
JG
817 ret = -1;
818 goto end;
819 }
820
83509119 821 bt_put(stream_class->event_header_type);
835b2d10 822 stream_class->event_header_type = bt_get(event_header_type);
d2f71f12
PP
823 BT_LOGV("Set stream class's event header field type: "
824 "addr=%p, name=\"%s\", id=%" PRId64 ", "
825 "event-header-ft-addr=%p",
826 stream_class, bt_ctf_stream_class_get_name(stream_class),
827 bt_ctf_stream_class_get_id(stream_class),
828 event_header_type);
662e778c
JG
829end:
830 return ret;
831}
832
af181248
JG
833struct bt_ctf_field_type *bt_ctf_stream_class_get_event_context_type(
834 struct bt_ctf_stream_class *stream_class)
835{
836 struct bt_ctf_field_type *ret = NULL;
837
d2f71f12
PP
838 if (!stream_class) {
839 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
840 goto end;
841 }
842
843 if (!stream_class->event_context_type) {
af181248
JG
844 goto end;
845 }
846
83509119 847 bt_get(stream_class->event_context_type);
af181248
JG
848 ret = stream_class->event_context_type;
849end:
850 return ret;
851}
852
853int bt_ctf_stream_class_set_event_context_type(
854 struct bt_ctf_stream_class *stream_class,
855 struct bt_ctf_field_type *event_context_type)
856{
857 int ret = 0;
858
d2f71f12
PP
859 if (!stream_class) {
860 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
861 ret = -1;
862 goto end;
863 }
864
865 if (stream_class->frozen) {
866 BT_LOGW("Invalid parameter: stream class is frozen: "
867 "addr=%p, name=\"%s\", id=%" PRId64,
868 stream_class, bt_ctf_stream_class_get_name(stream_class),
869 bt_ctf_stream_class_get_id(stream_class));
af181248
JG
870 ret = -1;
871 goto end;
872 }
873
835b2d10
JG
874 if (event_context_type &&
875 bt_ctf_field_type_get_type_id(event_context_type) !=
1487a16a 876 BT_CTF_FIELD_TYPE_ID_STRUCT) {
835b2d10 877 /* A packet context must be a structure. */
d2f71f12
PP
878 BT_LOGW("Invalid parameter: stream class's event context field type must be a structure: "
879 "addr=%p, name=\"%s\", id=%" PRId64 ", "
880 "event-context-ft-addr=%p, event-context-ft-id=%s",
881 stream_class, bt_ctf_stream_class_get_name(stream_class),
882 bt_ctf_stream_class_get_id(stream_class),
883 event_context_type,
884 bt_ctf_field_type_id_string(
885 bt_ctf_field_type_get_type_id(event_context_type)));
af181248
JG
886 ret = -1;
887 goto end;
888 }
889
83509119 890 bt_put(stream_class->event_context_type);
835b2d10 891 stream_class->event_context_type = bt_get(event_context_type);
d2f71f12
PP
892 BT_LOGV("Set stream class's event context field type: "
893 "addr=%p, name=\"%s\", id=%" PRId64 ", "
894 "event-context-ft-addr=%p",
895 stream_class, bt_ctf_stream_class_get_name(stream_class),
896 bt_ctf_stream_class_get_id(stream_class),
897 event_context_type);
af181248
JG
898end:
899 return ret;
900}
901
d2f71f12 902/* Pre-2.0 CTF writer backward compatibility */
11b0cdc8
JG
903void bt_ctf_stream_class_get(struct bt_ctf_stream_class *stream_class)
904{
83509119 905 bt_get(stream_class);
11b0cdc8
JG
906}
907
d2f71f12 908/* Pre-2.0 CTF writer backward compatibility */
11b0cdc8
JG
909void bt_ctf_stream_class_put(struct bt_ctf_stream_class *stream_class)
910{
83509119 911 bt_put(stream_class);
11b0cdc8
JG
912}
913
8bf65fbd 914static
544d0515 915int64_t get_event_class_count(void *element)
8bf65fbd
JG
916{
917 return bt_ctf_stream_class_get_event_class_count(
918 (struct bt_ctf_stream_class *) element);
919}
920
921static
922void *get_event_class(void *element, int i)
923{
9ac68eb1 924 return bt_ctf_stream_class_get_event_class_by_index(
8bf65fbd
JG
925 (struct bt_ctf_stream_class *) element, i);
926}
927
928static
d9a13d86 929int visit_event_class(void *object, bt_ctf_visitor visitor,void *data)
8bf65fbd 930{
d9a13d86
PP
931 struct bt_ctf_object obj =
932 { .object = object,
933 .type = BT_CTF_OBJECT_TYPE_EVENT_CLASS };
8bf65fbd 934
d9a13d86 935 return visitor(&obj, data);
8bf65fbd
JG
936}
937
938int bt_ctf_stream_class_visit(struct bt_ctf_stream_class *stream_class,
d9a13d86 939 bt_ctf_visitor visitor, void *data)
8bf65fbd
JG
940{
941 int ret;
d9a13d86
PP
942 struct bt_ctf_object obj =
943 { .object = stream_class,
944 .type = BT_CTF_OBJECT_TYPE_STREAM_CLASS };
8bf65fbd
JG
945
946 if (!stream_class || !visitor) {
d2f71f12
PP
947 BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
948 "stream-class-addr=%p, visitor=%p",
949 stream_class, visitor);
8bf65fbd
JG
950 ret = -1;
951 goto end;
952 }
953
d9a13d86 954 ret = visitor_helper(&obj, get_event_class_count,
8bf65fbd
JG
955 get_event_class,
956 visit_event_class, visitor, data);
d2f71f12 957 BT_LOGV("visitor_helper() returned: ret=%d", ret);
8bf65fbd
JG
958end:
959 return ret;
960}
961
11b0cdc8
JG
962BT_HIDDEN
963void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class *stream_class)
964{
d2f71f12 965 if (!stream_class || stream_class->frozen) {
11b0cdc8
JG
966 return;
967 }
968
d2f71f12
PP
969 BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64,
970 stream_class, bt_ctf_stream_class_get_name(stream_class),
971 bt_ctf_stream_class_get_id(stream_class));
11b0cdc8 972 stream_class->frozen = 1;
662e778c 973 bt_ctf_field_type_freeze(stream_class->event_header_type);
12c8a1a3 974 bt_ctf_field_type_freeze(stream_class->packet_context_type);
af181248 975 bt_ctf_field_type_freeze(stream_class->event_context_type);
ac0c6bdd
PP
976
977 if (stream_class->clock) {
978 bt_ctf_clock_class_freeze(stream_class->clock->clock_class);
979 }
11b0cdc8
JG
980}
981
11b0cdc8
JG
982BT_HIDDEN
983int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
984 struct metadata_context *context)
985{
9ac68eb1 986 int ret = 0;
11b0cdc8 987 size_t i;
6a5c98a5
JG
988 struct bt_ctf_trace *trace;
989 struct bt_ctf_field_type *packet_header_type = NULL;
11b0cdc8 990
d2f71f12
PP
991 BT_LOGD("Serializing stream class's metadata: "
992 "stream-class-addr=%p, stream-class-name=\"%s\", "
993 "stream-class-id=%" PRId64 ", metadata-context-addr=%p",
994 stream_class, bt_ctf_stream_class_get_name(stream_class),
995 bt_ctf_stream_class_get_id(stream_class), context);
11b0cdc8
JG
996 g_string_assign(context->field_name, "");
997 context->current_indentation_level = 1;
998 if (!stream_class->id_set) {
d2f71f12 999 BT_LOGW_STR("Stream class's ID is not set.");
11b0cdc8
JG
1000 ret = -1;
1001 goto end;
1002 }
1003
6a5c98a5
JG
1004 g_string_append(context->string, "stream {\n");
1005
1006 /*
1007 * The reference to the trace is only borrowed since the
1008 * serialization of the stream class might have been triggered
1009 * by the trace's destruction. In such a case, the trace's
1010 * reference count would, unexepectedly, go through the sequence
1011 * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
1012 * and serialization.
1013 */
1014 trace = bt_ctf_stream_class_borrow_trace(stream_class);
1015 assert(trace);
1016 packet_header_type = bt_ctf_trace_get_packet_header_type(trace);
1017 trace = NULL;
1018 if (packet_header_type) {
1019 struct bt_ctf_field_type *stream_id_type;
1020
1021 stream_id_type =
1022 bt_ctf_field_type_structure_get_field_type_by_name(
1023 packet_header_type, "stream_id");
1024 if (stream_id_type) {
1025 /*
1026 * Only set the stream's id if the trace's packet header
1027 * contains a stream_id field. This field is only
1028 * needed if the trace contains only one stream
1029 * class.
1030 */
1031 g_string_append_printf(context->string,
1032 "\tid = %" PRId64 ";\n", stream_class->id);
1033 }
1034 bt_put(stream_id_type);
1035 }
e011d2c1
PP
1036 if (stream_class->event_header_type) {
1037 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
1038 g_string_append(context->string, "\tevent.header := ");
1039 ret = bt_ctf_field_type_serialize(stream_class->event_header_type,
1040 context);
1041 if (ret) {
1042 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
1043 "ret=%d", ret);
1044 goto end;
1045 }
1046 g_string_append(context->string, ";");
11b0cdc8
JG
1047 }
1048
e011d2c1 1049
98edd02c 1050 if (stream_class->packet_context_type) {
e011d2c1
PP
1051 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
1052 g_string_append(context->string, "\n\n\tpacket.context := ");
98edd02c
JG
1053 ret = bt_ctf_field_type_serialize(stream_class->packet_context_type,
1054 context);
1055 if (ret) {
66871d36 1056 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
d2f71f12 1057 "ret=%d", ret);
98edd02c
JG
1058 goto end;
1059 }
e011d2c1 1060 g_string_append(context->string, ";");
11b0cdc8
JG
1061 }
1062
1063 if (stream_class->event_context_type) {
e011d2c1
PP
1064 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
1065 g_string_append(context->string, "\n\n\tevent.context := ");
11b0cdc8
JG
1066 ret = bt_ctf_field_type_serialize(
1067 stream_class->event_context_type, context);
1068 if (ret) {
66871d36 1069 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
d2f71f12 1070 "ret=%d", ret);
11b0cdc8
JG
1071 goto end;
1072 }
e011d2c1 1073 g_string_append(context->string, ";");
11b0cdc8
JG
1074 }
1075
e011d2c1
PP
1076 g_string_append(context->string, "\n};\n\n");
1077
11b0cdc8
JG
1078 for (i = 0; i < stream_class->event_classes->len; i++) {
1079 struct bt_ctf_event_class *event_class =
1080 stream_class->event_classes->pdata[i];
1081
11b0cdc8
JG
1082 ret = bt_ctf_event_class_serialize(event_class, context);
1083 if (ret) {
66871d36 1084 BT_LOGW("Cannot serialize event class's metadata: "
d2f71f12
PP
1085 "event-class-addr=%p, event-class-name=\"%s\", "
1086 "event-class-id=%" PRId64,
1087 event_class,
1088 bt_ctf_event_class_get_name(event_class),
1089 bt_ctf_event_class_get_id(event_class));
11b0cdc8
JG
1090 goto end;
1091 }
1092 }
1093end:
6a5c98a5 1094 bt_put(packet_header_type);
11b0cdc8
JG
1095 context->current_indentation_level = 0;
1096 return ret;
1097}
1098
1099static
83509119 1100void bt_ctf_stream_class_destroy(struct bt_object *obj)
11b0cdc8
JG
1101{
1102 struct bt_ctf_stream_class *stream_class;
1103
83509119 1104 stream_class = container_of(obj, struct bt_ctf_stream_class, base);
d2f71f12
PP
1105 BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64,
1106 stream_class, bt_ctf_stream_class_get_name(stream_class),
1107 bt_ctf_stream_class_get_id(stream_class));
83509119 1108 bt_put(stream_class->clock);
11b0cdc8 1109
0b9ce69f
JG
1110 if (stream_class->event_classes_ht) {
1111 g_hash_table_destroy(stream_class->event_classes_ht);
1112 }
11b0cdc8 1113 if (stream_class->event_classes) {
8c8cb0f2 1114 BT_LOGD_STR("Destroying event classes.");
11b0cdc8
JG
1115 g_ptr_array_free(stream_class->event_classes, TRUE);
1116 }
1117
1118 if (stream_class->name) {
1119 g_string_free(stream_class->name, TRUE);
1120 }
1121
8c8cb0f2 1122 BT_LOGD_STR("Putting event header field type.");
83509119 1123 bt_put(stream_class->event_header_type);
8c8cb0f2 1124 BT_LOGD_STR("Putting packet context field type.");
83509119 1125 bt_put(stream_class->packet_context_type);
8c8cb0f2 1126 BT_LOGD_STR("Putting event context field type.");
83509119 1127 bt_put(stream_class->event_context_type);
11b0cdc8
JG
1128 g_free(stream_class);
1129}
1130
1131static
662e778c 1132int init_event_header(struct bt_ctf_stream_class *stream_class)
11b0cdc8
JG
1133{
1134 int ret = 0;
1135 struct bt_ctf_field_type *event_header_type =
1136 bt_ctf_field_type_structure_create();
1137 struct bt_ctf_field_type *_uint32_t =
1138 get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
1139 struct bt_ctf_field_type *_uint64_t =
1140 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
1141
1142 if (!event_header_type) {
d2f71f12 1143 BT_LOGE_STR("Cannot create empty structure field type.");
11b0cdc8
JG
1144 ret = -1;
1145 goto end;
1146 }
1147
11b0cdc8
JG
1148 ret = bt_ctf_field_type_structure_add_field(event_header_type,
1149 _uint32_t, "id");
1150 if (ret) {
d2f71f12 1151 BT_LOGE_STR("Cannot add `id` field to event header field type.");
11b0cdc8
JG
1152 goto end;
1153 }
1154
1155 ret = bt_ctf_field_type_structure_add_field(event_header_type,
1156 _uint64_t, "timestamp");
1157 if (ret) {
d2f71f12 1158 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
11b0cdc8
JG
1159 goto end;
1160 }
1161
e0e2946b 1162 BT_MOVE(stream_class->event_header_type, event_header_type);
11b0cdc8
JG
1163end:
1164 if (ret) {
83509119 1165 bt_put(event_header_type);
11b0cdc8
JG
1166 }
1167
83509119
JG
1168 bt_put(_uint32_t);
1169 bt_put(_uint64_t);
11b0cdc8
JG
1170 return ret;
1171}
1172
1173static
662e778c 1174int init_packet_context(struct bt_ctf_stream_class *stream_class)
11b0cdc8
JG
1175{
1176 int ret = 0;
1177 struct bt_ctf_field_type *packet_context_type =
1178 bt_ctf_field_type_structure_create();
1179 struct bt_ctf_field_type *_uint64_t =
1180 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
e011d2c1 1181 struct bt_ctf_field_type *ts_begin_end_uint64_t;
11b0cdc8
JG
1182
1183 if (!packet_context_type) {
d2f71f12 1184 BT_LOGE_STR("Cannot create empty structure field type.");
11b0cdc8
JG
1185 ret = -1;
1186 goto end;
1187 }
1188
e011d2c1
PP
1189 ts_begin_end_uint64_t = bt_ctf_field_type_copy(_uint64_t);
1190 if (!ts_begin_end_uint64_t) {
1191 BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
1192 ret = -1;
1193 goto end;
1194 }
1195
11b0cdc8
JG
1196 /*
1197 * We create a stream packet context as proposed in the CTF
1198 * specification.
1199 */
11b0cdc8 1200 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
e011d2c1 1201 ts_begin_end_uint64_t, "timestamp_begin");
11b0cdc8 1202 if (ret) {
d2f71f12 1203 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
11b0cdc8
JG
1204 goto end;
1205 }
1206
1207 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
e011d2c1 1208 ts_begin_end_uint64_t, "timestamp_end");
11b0cdc8 1209 if (ret) {
d2f71f12 1210 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
11b0cdc8
JG
1211 goto end;
1212 }
1213
1214 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
1215 _uint64_t, "content_size");
1216 if (ret) {
d2f71f12 1217 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
11b0cdc8
JG
1218 goto end;
1219 }
1220
1221 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
1222 _uint64_t, "packet_size");
1223 if (ret) {
d2f71f12 1224 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
11b0cdc8
JG
1225 goto end;
1226 }
1227
1228 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
1229 _uint64_t, "events_discarded");
1230 if (ret) {
d2f71f12 1231 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
11b0cdc8
JG
1232 goto end;
1233 }
1234
e0e2946b 1235 BT_MOVE(stream_class->packet_context_type, packet_context_type);
11b0cdc8
JG
1236end:
1237 if (ret) {
83509119 1238 bt_put(packet_context_type);
11b0cdc8
JG
1239 goto end;
1240 }
1241
83509119 1242 bt_put(_uint64_t);
e011d2c1
PP
1243 bt_put(ts_begin_end_uint64_t);
1244 return ret;
1245}
1246
1247static
1248int try_map_clock_class(struct bt_ctf_stream_class *stream_class,
1249 struct bt_ctf_field_type *ft)
1250{
1251 struct bt_ctf_clock_class *mapped_clock_class = NULL;
1252 int ret = 0;
1253
1254 if (!ft) {
1255 /* Field does not exist: not an error */
1256 goto end;
1257 }
1258
1259 assert(bt_ctf_field_type_is_integer(ft));
1260 mapped_clock_class =
1261 bt_ctf_field_type_integer_get_mapped_clock_class(ft);
1262 if (!mapped_clock_class) {
1263 if (!stream_class->clock) {
1264 BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
1265 "stream-class-addr=%p, stream-class-name=\"%s\", "
1266 "stream-class-id=%" PRId64 ", ft-addr=%p",
1267 stream_class, bt_ctf_stream_class_get_name(stream_class),
1268 bt_ctf_stream_class_get_id(stream_class), ft);
1269 ret = -1;
1270 goto end;
1271 }
1272
1273 ret = bt_ctf_field_type_integer_set_mapped_clock_class_no_check(
1274 ft, stream_class->clock->clock_class);
1275 if (ret) {
1276 BT_LOGW("Cannot set field type's mapped clock class: "
1277 "stream-class-addr=%p, stream-class-name=\"%s\", "
1278 "stream-class-id=%" PRId64 ", ft-addr=%p",
1279 stream_class, bt_ctf_stream_class_get_name(stream_class),
1280 bt_ctf_stream_class_get_id(stream_class), ft);
1281 goto end;
1282 }
1283
1284 BT_LOGV("Automatically mapped field type to stream class's clock class: "
1285 "stream-class-addr=%p, stream-class-name=\"%s\", "
1286 "stream-class-id=%" PRId64 ", ft-addr=%p",
1287 stream_class, bt_ctf_stream_class_get_name(stream_class),
1288 bt_ctf_stream_class_get_id(stream_class), ft);
1289 }
1290
1291end:
1292 bt_put(mapped_clock_class);
1293 return ret;
1294}
1295
1296BT_HIDDEN
1297int bt_ctf_stream_class_map_clock_class(
1298 struct bt_ctf_stream_class *stream_class,
1299 struct bt_ctf_field_type *packet_context_type,
1300 struct bt_ctf_field_type *event_header_type)
1301{
1302 struct bt_ctf_field_type *ft = NULL;
1303 int ret = 0;
1304
1305 assert(stream_class);
1306
1307 if (packet_context_type) {
1308 ft = bt_ctf_field_type_structure_get_field_type_by_name(
1309 packet_context_type, "timestamp_begin");
1310 if (try_map_clock_class(stream_class, ft)) {
1311 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
1312 ret = -1;
1313 goto end;
1314 }
1315
1316 bt_put(ft);
1317 ft = bt_ctf_field_type_structure_get_field_type_by_name(
1318 packet_context_type, "timestamp_end");
1319 if (try_map_clock_class(stream_class, ft)) {
1320 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
1321 ret = -1;
1322 goto end;
1323 }
1324
1325 BT_PUT(ft);
1326 }
1327
1328 if (event_header_type) {
1329 ft = bt_ctf_field_type_structure_get_field_type_by_name(
1330 event_header_type, "timestamp");
1331 if (try_map_clock_class(stream_class, ft)) {
1332 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
1333 ret = -1;
1334 goto end;
1335 }
1336
1337 BT_PUT(ft);
1338 }
1339
1340end:
11b0cdc8
JG
1341 return ret;
1342}
This page took 0.101847 seconds and 4 git commands to generate.