Fix: event, stream names can be strings
[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
JG
987 size_t i;
988
d2f71f12
PP
989 BT_LOGD("Serializing stream class's metadata: "
990 "stream-class-addr=%p, stream-class-name=\"%s\", "
991 "stream-class-id=%" PRId64 ", metadata-context-addr=%p",
992 stream_class, bt_ctf_stream_class_get_name(stream_class),
993 bt_ctf_stream_class_get_id(stream_class), context);
11b0cdc8
JG
994 g_string_assign(context->field_name, "");
995 context->current_indentation_level = 1;
996 if (!stream_class->id_set) {
d2f71f12 997 BT_LOGW_STR("Stream class's ID is not set.");
11b0cdc8
JG
998 ret = -1;
999 goto end;
1000 }
1001
1002 g_string_append_printf(context->string,
e011d2c1
PP
1003 "stream {\n\tid = %" PRId64 ";\n", stream_class->id);
1004 if (stream_class->event_header_type) {
1005 BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
1006 g_string_append(context->string, "\tevent.header := ");
1007 ret = bt_ctf_field_type_serialize(stream_class->event_header_type,
1008 context);
1009 if (ret) {
1010 BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
1011 "ret=%d", ret);
1012 goto end;
1013 }
1014 g_string_append(context->string, ";");
11b0cdc8
JG
1015 }
1016
e011d2c1 1017
98edd02c 1018 if (stream_class->packet_context_type) {
e011d2c1
PP
1019 BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
1020 g_string_append(context->string, "\n\n\tpacket.context := ");
98edd02c
JG
1021 ret = bt_ctf_field_type_serialize(stream_class->packet_context_type,
1022 context);
1023 if (ret) {
66871d36 1024 BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
d2f71f12 1025 "ret=%d", ret);
98edd02c
JG
1026 goto end;
1027 }
e011d2c1 1028 g_string_append(context->string, ";");
11b0cdc8
JG
1029 }
1030
1031 if (stream_class->event_context_type) {
e011d2c1
PP
1032 BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
1033 g_string_append(context->string, "\n\n\tevent.context := ");
11b0cdc8
JG
1034 ret = bt_ctf_field_type_serialize(
1035 stream_class->event_context_type, context);
1036 if (ret) {
66871d36 1037 BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
d2f71f12 1038 "ret=%d", ret);
11b0cdc8
JG
1039 goto end;
1040 }
e011d2c1 1041 g_string_append(context->string, ";");
11b0cdc8
JG
1042 }
1043
e011d2c1
PP
1044 g_string_append(context->string, "\n};\n\n");
1045
11b0cdc8
JG
1046 for (i = 0; i < stream_class->event_classes->len; i++) {
1047 struct bt_ctf_event_class *event_class =
1048 stream_class->event_classes->pdata[i];
1049
11b0cdc8
JG
1050 ret = bt_ctf_event_class_serialize(event_class, context);
1051 if (ret) {
66871d36 1052 BT_LOGW("Cannot serialize event class's metadata: "
d2f71f12
PP
1053 "event-class-addr=%p, event-class-name=\"%s\", "
1054 "event-class-id=%" PRId64,
1055 event_class,
1056 bt_ctf_event_class_get_name(event_class),
1057 bt_ctf_event_class_get_id(event_class));
11b0cdc8
JG
1058 goto end;
1059 }
1060 }
1061end:
1062 context->current_indentation_level = 0;
1063 return ret;
1064}
1065
1066static
83509119 1067void bt_ctf_stream_class_destroy(struct bt_object *obj)
11b0cdc8
JG
1068{
1069 struct bt_ctf_stream_class *stream_class;
1070
83509119 1071 stream_class = container_of(obj, struct bt_ctf_stream_class, base);
d2f71f12
PP
1072 BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64,
1073 stream_class, bt_ctf_stream_class_get_name(stream_class),
1074 bt_ctf_stream_class_get_id(stream_class));
83509119 1075 bt_put(stream_class->clock);
11b0cdc8 1076
0b9ce69f
JG
1077 if (stream_class->event_classes_ht) {
1078 g_hash_table_destroy(stream_class->event_classes_ht);
1079 }
11b0cdc8 1080 if (stream_class->event_classes) {
8c8cb0f2 1081 BT_LOGD_STR("Destroying event classes.");
11b0cdc8
JG
1082 g_ptr_array_free(stream_class->event_classes, TRUE);
1083 }
1084
1085 if (stream_class->name) {
1086 g_string_free(stream_class->name, TRUE);
1087 }
1088
8c8cb0f2 1089 BT_LOGD_STR("Putting event header field type.");
83509119 1090 bt_put(stream_class->event_header_type);
8c8cb0f2 1091 BT_LOGD_STR("Putting packet context field type.");
83509119 1092 bt_put(stream_class->packet_context_type);
8c8cb0f2 1093 BT_LOGD_STR("Putting event context field type.");
83509119 1094 bt_put(stream_class->event_context_type);
11b0cdc8
JG
1095 g_free(stream_class);
1096}
1097
1098static
662e778c 1099int init_event_header(struct bt_ctf_stream_class *stream_class)
11b0cdc8
JG
1100{
1101 int ret = 0;
1102 struct bt_ctf_field_type *event_header_type =
1103 bt_ctf_field_type_structure_create();
1104 struct bt_ctf_field_type *_uint32_t =
1105 get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
1106 struct bt_ctf_field_type *_uint64_t =
1107 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
1108
1109 if (!event_header_type) {
d2f71f12 1110 BT_LOGE_STR("Cannot create empty structure field type.");
11b0cdc8
JG
1111 ret = -1;
1112 goto end;
1113 }
1114
11b0cdc8
JG
1115 ret = bt_ctf_field_type_structure_add_field(event_header_type,
1116 _uint32_t, "id");
1117 if (ret) {
d2f71f12 1118 BT_LOGE_STR("Cannot add `id` field to event header field type.");
11b0cdc8
JG
1119 goto end;
1120 }
1121
1122 ret = bt_ctf_field_type_structure_add_field(event_header_type,
1123 _uint64_t, "timestamp");
1124 if (ret) {
d2f71f12 1125 BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
11b0cdc8
JG
1126 goto end;
1127 }
1128
e0e2946b 1129 BT_MOVE(stream_class->event_header_type, event_header_type);
11b0cdc8
JG
1130end:
1131 if (ret) {
83509119 1132 bt_put(event_header_type);
11b0cdc8
JG
1133 }
1134
83509119
JG
1135 bt_put(_uint32_t);
1136 bt_put(_uint64_t);
11b0cdc8
JG
1137 return ret;
1138}
1139
1140static
662e778c 1141int init_packet_context(struct bt_ctf_stream_class *stream_class)
11b0cdc8
JG
1142{
1143 int ret = 0;
1144 struct bt_ctf_field_type *packet_context_type =
1145 bt_ctf_field_type_structure_create();
1146 struct bt_ctf_field_type *_uint64_t =
1147 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
e011d2c1 1148 struct bt_ctf_field_type *ts_begin_end_uint64_t;
11b0cdc8
JG
1149
1150 if (!packet_context_type) {
d2f71f12 1151 BT_LOGE_STR("Cannot create empty structure field type.");
11b0cdc8
JG
1152 ret = -1;
1153 goto end;
1154 }
1155
e011d2c1
PP
1156 ts_begin_end_uint64_t = bt_ctf_field_type_copy(_uint64_t);
1157 if (!ts_begin_end_uint64_t) {
1158 BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
1159 ret = -1;
1160 goto end;
1161 }
1162
11b0cdc8
JG
1163 /*
1164 * We create a stream packet context as proposed in the CTF
1165 * specification.
1166 */
11b0cdc8 1167 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
e011d2c1 1168 ts_begin_end_uint64_t, "timestamp_begin");
11b0cdc8 1169 if (ret) {
d2f71f12 1170 BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
11b0cdc8
JG
1171 goto end;
1172 }
1173
1174 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
e011d2c1 1175 ts_begin_end_uint64_t, "timestamp_end");
11b0cdc8 1176 if (ret) {
d2f71f12 1177 BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
11b0cdc8
JG
1178 goto end;
1179 }
1180
1181 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
1182 _uint64_t, "content_size");
1183 if (ret) {
d2f71f12 1184 BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
11b0cdc8
JG
1185 goto end;
1186 }
1187
1188 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
1189 _uint64_t, "packet_size");
1190 if (ret) {
d2f71f12 1191 BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
11b0cdc8
JG
1192 goto end;
1193 }
1194
1195 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
1196 _uint64_t, "events_discarded");
1197 if (ret) {
d2f71f12 1198 BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
11b0cdc8
JG
1199 goto end;
1200 }
1201
e0e2946b 1202 BT_MOVE(stream_class->packet_context_type, packet_context_type);
11b0cdc8
JG
1203end:
1204 if (ret) {
83509119 1205 bt_put(packet_context_type);
11b0cdc8
JG
1206 goto end;
1207 }
1208
83509119 1209 bt_put(_uint64_t);
e011d2c1
PP
1210 bt_put(ts_begin_end_uint64_t);
1211 return ret;
1212}
1213
1214static
1215int try_map_clock_class(struct bt_ctf_stream_class *stream_class,
1216 struct bt_ctf_field_type *ft)
1217{
1218 struct bt_ctf_clock_class *mapped_clock_class = NULL;
1219 int ret = 0;
1220
1221 if (!ft) {
1222 /* Field does not exist: not an error */
1223 goto end;
1224 }
1225
1226 assert(bt_ctf_field_type_is_integer(ft));
1227 mapped_clock_class =
1228 bt_ctf_field_type_integer_get_mapped_clock_class(ft);
1229 if (!mapped_clock_class) {
1230 if (!stream_class->clock) {
1231 BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
1232 "stream-class-addr=%p, stream-class-name=\"%s\", "
1233 "stream-class-id=%" PRId64 ", ft-addr=%p",
1234 stream_class, bt_ctf_stream_class_get_name(stream_class),
1235 bt_ctf_stream_class_get_id(stream_class), ft);
1236 ret = -1;
1237 goto end;
1238 }
1239
1240 ret = bt_ctf_field_type_integer_set_mapped_clock_class_no_check(
1241 ft, stream_class->clock->clock_class);
1242 if (ret) {
1243 BT_LOGW("Cannot set field type's mapped clock class: "
1244 "stream-class-addr=%p, stream-class-name=\"%s\", "
1245 "stream-class-id=%" PRId64 ", ft-addr=%p",
1246 stream_class, bt_ctf_stream_class_get_name(stream_class),
1247 bt_ctf_stream_class_get_id(stream_class), ft);
1248 goto end;
1249 }
1250
1251 BT_LOGV("Automatically mapped field type to stream class's clock class: "
1252 "stream-class-addr=%p, stream-class-name=\"%s\", "
1253 "stream-class-id=%" PRId64 ", ft-addr=%p",
1254 stream_class, bt_ctf_stream_class_get_name(stream_class),
1255 bt_ctf_stream_class_get_id(stream_class), ft);
1256 }
1257
1258end:
1259 bt_put(mapped_clock_class);
1260 return ret;
1261}
1262
1263BT_HIDDEN
1264int bt_ctf_stream_class_map_clock_class(
1265 struct bt_ctf_stream_class *stream_class,
1266 struct bt_ctf_field_type *packet_context_type,
1267 struct bt_ctf_field_type *event_header_type)
1268{
1269 struct bt_ctf_field_type *ft = NULL;
1270 int ret = 0;
1271
1272 assert(stream_class);
1273
1274 if (packet_context_type) {
1275 ft = bt_ctf_field_type_structure_get_field_type_by_name(
1276 packet_context_type, "timestamp_begin");
1277 if (try_map_clock_class(stream_class, ft)) {
1278 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
1279 ret = -1;
1280 goto end;
1281 }
1282
1283 bt_put(ft);
1284 ft = bt_ctf_field_type_structure_get_field_type_by_name(
1285 packet_context_type, "timestamp_end");
1286 if (try_map_clock_class(stream_class, ft)) {
1287 BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
1288 ret = -1;
1289 goto end;
1290 }
1291
1292 BT_PUT(ft);
1293 }
1294
1295 if (event_header_type) {
1296 ft = bt_ctf_field_type_structure_get_field_type_by_name(
1297 event_header_type, "timestamp");
1298 if (try_map_clock_class(stream_class, ft)) {
1299 BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
1300 ret = -1;
1301 goto end;
1302 }
1303
1304 BT_PUT(ft);
1305 }
1306
1307end:
11b0cdc8
JG
1308 return ret;
1309}
This page took 0.103565 seconds and 4 git commands to generate.